本节列出了 MySQL 近期版本中的已知问题。
有关平台特定问题的信息,请参阅 第 2.1 节,“通用安装指南” 和 第 7.9 节,“调试 MySQL”。
以下问题是已知的:
-
子查询优化对于
IN不如对于=有效。 -
即使您使用
lower_case_table_names=2(启用 MySQL 记住数据库和表名的大小写),MySQL 也不会记住数据库名的大小写用于函数DATABASE()或在各种日志中(在不区分大小写的系统上)。 -
删除
FOREIGN KEY约束在复制中不起作用,因为约束可能在副本上有不同的名称。 -
DISTINCT与ORDER BY不在GROUP_CONCAT()中工作,如果您不使用所有且仅使用DISTINCT列表中的列。 -
当将大整数值(介于 263 和 264−1 之间)插入到 decimal 或字符串列中时,它将作为负值插入,因为该数字在 signed 整数上下文中被评估。
-
使用基于语句的二进制日志记录时,源服务器将执行的查询写入二进制日志。这是一种非常快速、紧凑和高效的日志记录方法,通常情况下工作正常。但是,如果查询被设计为使数据修改是非确定性的(通常情况下不建议这样做,即使在复制之外),那么源服务器和副本之间的数据可能会不同。
例如:
-
CREATE TABLE ... SELECT或INSERT ... SELECT语句将零或NULL值插入到AUTO_INCREMENT列中。 -
DELETE如果您删除具有ON DELETE CASCADE属性的外键的表中的行。 -
REPLACE ... SELECT,INSERT IGNORE ... SELECT如果您在插入的数据中有重复的键值。
如果且仅当前面的查询没有
ORDER BY子句保证确定的顺序。例如,对于
INSERT ... SELECT没有ORDER BY子句,SELECT可能以不同的顺序返回行(这将导致行具有不同的排名,从而在AUTO_INCREMENT列中获取不同的数字),这取决于源服务器和副本上的优化器所做的选择。只有在以下情况下,查询在源服务器和副本上才会被优化得不同:
-
表使用不同的存储引擎在源服务器和副本上。(例如,您可以在源服务器上使用
InnoDB,但在副本上使用MyISAM,如果副本上的可用磁盘空间较少。) -
MySQL 缓冲区大小(
key_buffer_size等)在源服务器和副本上不同。 -
源服务器和副本运行不同的 MySQL 版本,并且优化器代码在这些版本之间不同。
这个问题也可能影响使用 mysqlbinlog|mysql 进行数据库还原。
避免这个问题的最简单方法是添加
ORDER BY子句到上述非确定性查询中,以确保行总是以相同的顺序存储或修改。使用基于行的或混合日志格式也可以避免这个问题。 -
-
日志文件名基于服务器主机名,如果您不指定启动选项中的文件名。要保留相同的日志文件名,如果您更改主机名为其他名称,必须显式使用选项,例如:
--log-bin=。见 第 7.1.7 节,“服务器命令选项”。否则,重命名旧文件以反映主机名更改。如果这些是二进制日志,您必须编辑二进制日志索引文件并在那里修复二进制日志文件名。(在副本上也是如此。)old_host_name-bin -
mysqlbinlog 不删除
LOAD DATA语句后留下的临时文件。见 第 6.6.9 节,“mysqlbinlog — 实用程序处理二进制日志文件”。 -
RENAME不适用于TEMPORARY表或MERGE表中的表。 -
使用
SET CHARACTER SET时,不能在数据库、表和列名中使用翻译字符。 -
服务器仅使用第一个
max_sort_length字节来比较数据值。这意味着,如果值仅在第一个max_sort_length字节后不同,则无法可靠地在GROUP BY、ORDER BY或DISTINCT中使用它们。要解决这个问题,可以增加变量值。默认情况下,max_sort_length的值为 1024,可以在服务器启动时或运行时更改。 -
数字计算使用
BIGINT或DOUBLE(通常为 64 位长)。您获得的精度取决于函数。一般规则是,位函数使用BIGINT精度,IF()和ELT()使用BIGINT或DOUBLE精度,其他函数使用DOUBLE精度。您应该避免使用无符号长长值,如果它们解析为大于 63 位(9223372036854775807)的任何其他内容,除了位字段。 -
在
MIN()、MAX()和其他聚合函数中,MySQL 目前根据字符串值而不是字符串在集合中的相对位置来比较ENUM和SET列。 -
在
UPDATE语句中,从左到右更新列。如果您引用更新的列,您将获得更新后的值,而不是原始值。例如,以下语句将KEY增加 2,而不是 1:mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1; -
您可以在同一个查询中引用多个临时表,但不能引用任何给定的临时表多于一次。例如,以下不起作用:
mysql> SELECT * FROM temp_table, temp_table AS t2; ERROR 1137: Can't reopen table: 'temp_table' -
优化器可能会在使用
DISTINCT时对隐藏列的处理方式不同,具体取决于您是在 join 中使用还是在普通查询中使用。在 join 中,隐藏列被计入结果中(即使它们不显示),而在普通查询中,隐藏列不参与DISTINCT比较。例如:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id DESC;和
SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC;在第二种情况下,您可能会在结果集中获取两个相同的行(因为隐藏的
id列中的值可能不同)。请注意,这只发生在不包含
ORDER BY列的查询中。 -
如果您在返回空集的查询上执行
PROCEDURE,在某些情况下,PROCEDURE不会转换列。 -
创建类型为
MERGE的表时,不会检查基础表是否具有兼容的类型。 -
如果您使用
ALTER TABLE将UNIQUE索引添加到用于MERGE表的表中,然后在MERGE表上添加普通索引,那么如果表中曾经存在旧的、非UNIQUE键,则键的顺序将不同。这是因为ALTER TABLE将UNIQUE索引放在普通索引之前,以便尽早检测重复键。