本节列出了 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
索引放在普通索引之前,以便尽早检测重复键。