Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
看看 MySQL令人咋舌的隐式转换_创想鸟

看看 MySQL令人咋舌的隐式转换

mysql教程栏目介绍相关的隐式转换

看看 MySQL令人咋舌的隐式转换

更多相关免费学习推荐:mysql教程(视频)

一、问题描述

root@mysqldb 22:12:  [xucl]> show create table t1G*************************** 1. row ***************************       Table: t1Create Table: CREATE TABLE `t1` (  `id` varchar(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec)root@mysqldb 22:19:  [xucl]> select * from t1;+--------------------+| id                 |+--------------------+| 204027026112927605 || 204027026112927603 || 2040270261129276   || 2040270261129275   || 100                || 101                |+--------------------+6 rows in set (0.00 sec)

奇怪的现象:

root@mysqldb 22:19:  [xucl]> select * from t1 where id=204027026112927603;+--------------------+| id                 |+--------------------+| 204027026112927605 || 204027026112927603 |+--------------------+2 rows in set (0.00 sec)

640?wx_fmt=jpeg

什么鬼,明明查的是204027026112927603,为什么204027026112927605也出来了

二、源码解释

堆栈调用关系如下所示:

640?wx_fmt=jpeg

其中JOIN::exec()是执行的入口,Arg_comparator::compare_real()是进行等值判断的函数,其定义如下

int Arg_comparator::compare_real(){  /*    Fix yet another manifestation of Bug#2338. 'Volatile' will instruct    gcc to flush double values out of 80-bit Intel FPU registers before    performing the comparison.  */  volatile double val1, val2;  val1= (*a)->val_real();  if (!(*a)->null_value)  {    val2= (*b)->val_real();    if (!(*b)->null_value)    {      if (set_null)        owner->null_value= 0;      if (val1 null_value= 1;  return -1;}

比较步骤如下图所示,逐行读取t1表的id列放入val1,而常量204027026112927603存在于cache中,类型为double类型(2.0402702611292762E+17),所以到这里传值给val2后val2=2.0402702611292762E+17。

640?wx_fmt=jpeg

当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合

640?wx_fmt=jpeg

如何检测string类型的数字转成doule类型是否溢出呢?这里经过测试,当数字超过16位以后,转成double类型就已经不准确了,例如20402702611292711会表示成20402702611292712(如图中val1)

640?wx_fmt=jpeg

640?wx_fmt=jpeg

MySQL string转成double的定义函数如下:

{  char buf[DTOA_BUFF_SIZE];  double res;  DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) ||                              (str == NULL && *end == NULL)) &&              error != NULL);  res= my_strtod_int(str, end, error, buf, sizeof(buf));  return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX);}

真正转换函数my_strtod_int位置在dtoa.c(太复杂了,简单贴个注释吧)

/*  strtod for IEEE--arithmetic machines.   This strtod returns a nearest machine number to the input decimal  string (or sets errno to EOVERFLOW). Ties are broken by the IEEE round-even  rule.   Inspired loosely by William D. Clinger's paper "How to Read Floating  Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].   Modifications:    1. We only require IEEE (not IEEE double-extended).   2. We get by with floating-point arithmetic in a case that     Clinger missed -- when we're computing d * 10^n     for a small integer d and the integer n is not too     much larger than 22 (the maximum integer k for which     we can represent 10^k exactly), we may be able to     compute (d*10^k) * 10^(e-k) with just one roundoff.   3. Rather than a bit-at-a-time adjustment of the binary     result in the hard case, we use floating-point     arithmetic to determine the adjustment to within     one bit; only in really hard cases do we need to     compute a second residual.   4. Because of 3., we don't need a large table of powers of 10     for ten-to-e (just some small tables, e.g. of 10^k     for 0 <= k <= 22).*/

既然是这样,我们测试下没有溢出的案例

root@mysqldb 23:30:  [xucl]> select * from t1 where id=2040270261129276;+------------------+| id               |+------------------+| 2040270261129276 |+------------------+1 row in set (0.00 sec)root@mysqldb 23:30:  [xucl]> select * from t1 where id=101;+------+| id   |+------+| 101  |+------+1 row in set (0.00 sec)

结果符合预期,而在本例中,正确的写法应当是

root@mysqldb 22:19:  [xucl]> select * from t1 where id='204027026112927603';+--------------------+| id                 |+--------------------+| 204027026112927603 |+--------------------+1 row in set (0.01 sec)

三、结论

避免发生隐式类型转换,隐式转换的类型主要有字段类型不一致、in参数包含多个类型、字符集类型或校对规则不一致等

隐式类型转换可能导致无法使用索引、查询结果不准确等,因此在使用时必须仔细甄别

数字类型的建议在字段定义时就定义为int或者bigint,表关联时关联字段必须保持类型、字符集、校对规则都一致

最后贴一下官网对于隐式类型转换的说明吧

1、If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe equality comparison operator. For NULL  NULL, the result is true. No conversion is needed.2、If both arguments in a comparison operation are strings, they are compared as strings.3、If both arguments are integers, they are compared as integers.4、Hexadecimal values are treated as binary strings if not compared to a number.5、If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is aconstant, the constant is converted to a timestamp before the comparison is performed. This isdone to be more ODBC-friendly. This is not done for the arguments to IN(). To be safe, alwaysuse complete datetime, date, or time strings when doing comparisons. For example, to achieve bestresults when using BETWEEN with date or time values, use CAST() to explicitly convert the values tothe desired data type.A single-row subquery from a table or tables is not considered a constant. For example, if a subqueryreturns an integer to be compared to a DATETIME value, the comparison is done as two integers.The integer is not converted to a temporal value. To compare the operands as DATETIME values,use CAST() to explicitly convert the subquery value to DATETIME.6、If one of the arguments is a decimal value, comparison depends on the other argument. Thearguments are compared as decimal values if the other argument is a decimal or integer value, or asfloating-point values if the other argument is a floating-point value.7、In all other cases, the arguments are compared as floating-point (real) numbers.

以上就是看看 MySQL令人咋舌的隐式转换的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/189655.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Steam限时喜加一:经典刷宝游戏《无主之地2》免费领取
上一篇 2026年9月6日 17:18:53
使用Holer服务端软件搭建属于自己的内网穿透
下一篇 2026年9月6日 17:22:46

相关推荐

  • mysql安装后如何优化配置文件

    答案:优化MySQL配置需先定位配置文件,再根据硬件和业务调整内存、InnoDB、连接等核心参数。具体包括设置innodb_buffer_pool_size为物理内存50%~70%,合理配置日志参数与连接数,启用慢查询日志,并使用工具辅助调优,避免过度配置,确保稳定高效。 MySQL 安装后,优化配…

    2026年9月21日
    000
  • mysql如何设计数据归档表

    归档目标是解决主表数据量过大问题,需明确归档范围如时间维度冷数据,设计与原表一致或简化的归档表结构,保留必要索引并可添加archive_time字段和分区,通过分批迁移、限流休眠、事务安全和断点记录策略执行归档,避免影响线上服务,同时建立查询视图、定期备份、监控任务及生命周期管理,确保数据可用与系统…

    2026年9月21日
    000
  • 如何基于Swoole开发自定义框架?

    基于swoole开发自定义框架可以通过以下步骤实现:1. 创建核心app类,初始化swoole服务器并定义回调函数;2. 实现路由功能,使用router类处理请求分发;3. 添加中间件支持,使用middleware类处理请求;4. 集成异步数据库操作,使用swoole的mysql协程客户端;5. 实…

    2026年9月21日
    000
  • mysql如何理解数据压缩

    MySQL数据压缩通过减少存储空间提升I/O效率,主要在InnoDB引擎中实现页级压缩,使用zlib算法对BLOB、TEXT等大字段表压缩效果显著,需设置ROW_FORMAT=COMPRESSED和KEY_BLOCK_SIZE;压缩可降低磁盘使用并加速全表扫描,但增加CPU开销,频繁更新可能导致页分…

    2026年9月21日
    000
  • mysql如何使用savepoint

    SAVEPOINT用于在事务中设置回滚点,支持部分回滚。开启事务后可用SAVEPOINT命名保存点,通过ROLLBACK TO回滚至指定点,RELEASE SAVEPOINT可释放保存点。例如转账时先扣款并设保存点,若后续操作失败可回滚到该点,保留前置操作。保存点仅在当前事务有效,提交或回滚后自动清…

    2026年9月21日
    100
  • mysqlmysql如何优化in条件大列表查询

    使用EXPLAIN和慢查询日志判断IN性能问题,type为ALL且possible_keys为空或rows过大说明需优化;JOIN在有索引时通常优于IN,尤其当列表值来自另一表时;大IN列表可拆分为多个小IN结合UNION ALL,或存入临时表后用JOIN提升效率。 优化 MySQL 中 IN 条件…

    2026年9月21日
    000
  • 如何配置mysql初始用户和密码

    答案:MySQL安装后默认用户为root,密码为空或自动生成。需先确认服务运行,再登录并设置密码;若为空密码则直接登录后用ALTER USER修改,若为临时密码需从日志获取并强制修改;可创建远程用户并授权;推荐运行mysql_secure_installation进行安全加固,包括设密码、删匿名用户…

    2026年9月21日
    000
  • mysql如何排查磁盘IO瓶颈

    首先检查系统级磁盘IO,使用iostat、iotop等工具分析磁盘利用率和进程IO行为;再通过MySQL慢查询日志、sys.schema视图及SHOW ENGINE INNODB STATUS排查高IO消耗的SQL与内部等待事件;接着评估innodb_buffer_pool_size、innodb_…

    2026年9月21日
    000
  • 如何在Laravel中配置数据库连接?

    在laravel中配置数据库连接需要以下步骤:1. 编辑.env文件,设置db_connection、db_host、db_port、db_database、db_username、db_password。2. 确保config/database.php文件正确引用.env文件中的配置。3. 利用环…

    2026年9月21日
    000
  • mysql如何调试事务问题

    首先通过日志和锁信息确认事务状态,1. 启用通用日志追踪事务操作,2. 查询INNODB_TRX和INNODB_LOCK_WAITS分析活跃事务与阻塞关系,3. 查看死锁日志定位冲突原因,4. 调整隔离级别并优化事务逻辑以避免异常。 调试 MySQL 事务问题需要结合日志分析、锁信息查看和事务状态监…

    2026年9月21日
    100
  • mysql如何设置自动重连

    答案:通过连接配置、连接池和应用层逻辑实现MySQL自动重连。启用MYSQL_OPT_RECONNECT选项(旧版本),推荐使用连接池如PooledDB、HikariCP并配置ping机制,应用层捕获连接异常后重试,结合指数退避策略提升稳定性。 MySQL 客户端或应用程序在连接断开后无法自动恢复,…

    2026年9月21日
    100
  • mysql如何理解数据完整性

    数据完整性在MySQL中通过主键、外键、约束等机制确保数据准确一致。1. 实体完整性用主键保证记录唯一,主键非空且不重复;2. 域完整性通过数据类型、CHECK约束、默认值等确保字段数据合法;3. 参照完整性利用外键维护表间关系,支持级联操作;4. 用户定义完整性由开发者通过触发器或程序实现业务规则…

    2026年9月21日
    100
  • 如何迁移触发器

    迁移触发器需确保逻辑重建与行为一致,须考虑平台差异、依赖对象及权限。首先确认源与目标数据库对触发事件、时机、级别及功能支持的兼容性,如MySQL支持BEFORE/AFTER行级触发器,SQLite不支持语句级触发器,跨平台可能需重写。接着通过元数据查询或系统表导出触发器定义,如MySQL使用SHOW…

    2026年9月21日
    100
  • mysql如何配置默认存储引擎

    首先查看当前默认存储引擎,通过SHOW VARIABLES命令确认;然后编辑my.cnf或my.ini文件,在[mysqld]下添加default-storage-engine=InnoDB;接着重启MySQL服务使配置生效;最后验证更改结果并检查建表默认引擎。 MySQL 默认存储引擎的配置可以通…

    2026年9月21日
    100
  • mysql索引的类型和作用有哪些

    MySQL常见索引类型包括:1. 普通索引用于加速查询;2. 唯一索引确保列值唯一;3. 主键索引为唯一非空且自动创建聚簇索引;4. 聚簇索引决定数据物理存储顺序,每表仅一个;5. 非聚簇索引保存主键值,需回表查询;6. 覆盖索引避免回表提升性能;7. 联合索引遵循最左前缀原则;8. 全文索引支持文…

    2026年9月21日
    100
  • Linux怎么使用systemctl管理服务

    Linux怎么使用systemctl管理服务Linux怎么使用systemctl管理服务Linux怎么使用systemctl管理服务Linux怎么使用systemctl管理服务

    systemctl是Linux中管理systemd服务的核心工具,提供统一命令集来启动、停止、重启、查看服务状态及设置开机自启,支持并行启动、依赖管理与Cgroups资源控制,相比SysVinit更高效;通过创建/etc/systemd/system/下的.service文件可自定义服务,包含[Un…

    2026年9月21日 • 用户投稿
    200
  • mysql如何优化子查询

    优先使用JOIN替代相关子查询,减少扫描行数并利用索引;对子查询字段建立合适索引;用EXISTS代替IN处理大量数据;物化不相关子查询结果;避免无索引的标量子查询;通过EXPLAIN分析执行计划优化性能。 MySQL中子查询如果使用不当,容易导致性能下降,尤其是在数据量大的情况下。优化子查询的核心是…

    2026年9月21日
    100
  • 如何在服务器上优化mysql安装

    优化MySQL需从系统环境、配置参数、存储引擎到日常维护多层面入手,首先确保内存合理分配、选用XFS等高性能文件系统、关闭非必要服务并调整内核参数;其次在MySQL配置中优先使用InnoDB引擎,科学设置innodb_buffer_pool_size、innodb_log_file_size、max…

    2026年9月21日
    100
  • mysql如何启用binlog日志

    MySQL启用binlog需修改配置文件添加log-bin和server-id,重启服务后执行SHOW VARIABLES LIKE ‘log_bin’验证是否为ON,确认启用。 MySQL启用binlog日志需要修改配置文件并重启服务,同时可进行简单验证确保生效。以下是具体…

    2026年9月21日
    200
  • mysql如何使用事务保证操作原子性

    答案:MySQL中事务通过START TRANSACTION开启,需使用InnoDB引擎并关闭自动提交,执行SQL后根据结果COMMIT或ROLLBACK,结合异常处理确保原子性。 在MySQL中,事务是保证数据库操作原子性的核心机制。通过事务,可以确保一组SQL操作要么全部成功执行,要么全部不执行…

    2026年9月21日
    600

发表回复

登录后才能评论
关注微信