本节列出了最新版本 MySQL 中的已知问题。
有关平台特定问题的信息,请参阅第 2.1 节 “一般安装指南”和第 7.9 节 “调试 MySQL”中的安装和调试说明。
已知存在以下问题
IN
的子查询优化不如=
有效。即使您使用
lower_case_table_names=2
(这使 MySQL 能够记住用于数据库和表名的大小写),MySQL 也不会记住用于函数DATABASE()
或各种日志(在不区分大小写的系统上)的数据库名的大小写。删除
FOREIGN KEY
约束在复制中不起作用,因为该约束在副本上可能具有其他名称。如果不在
DISTINCT
列表中使用所有且仅使用这些列,则带有ORDER BY
的DISTINCT
在GROUP_CONCAT()
内不起作用。将大整数值(介于 263 和 264−1 之间)插入 decimal 或字符串列时,它将作为负值插入,因为该数字是在有符号整数上下文中计算的。
使用基于语句的二进制日志记录,源服务器会将执行的查询写入二进制日志。这是一种非常快速、紧凑且高效的日志记录方法,在大多数情况下都能完美运行。但是,如果查询的设计方式使得数据修改是非确定性的(即使在复制之外,通常也不推荐这样做),则源和副本上的数据可能会变得不同。
例如
将零或
NULL
值插入AUTO_INCREMENT
列的CREATE TABLE ... SELECT
或INSERT ... SELECT
语句。如果您要从具有
ON DELETE CASCADE
属性的外键的表中删除行,则使用DELETE
。如果在插入的数据中具有重复的键值,则使用
REPLACE ... SELECT
、INSERT IGNORE ... SELECT
。
当且仅当前面的查询没有
ORDER BY
子句来保证确定性顺序时.例如,对于没有
ORDER BY
的INSERT ... SELECT
,SELECT
可能会以不同的顺序返回行(这会导致行具有不同的排名,因此在AUTO_INCREMENT
列中获得不同的编号),具体取决于源和副本上的优化器做出的选择。仅在以下情况下,查询才会在源和副本上进行不同的优化:
该表在源上使用与副本不同的存储引擎存储。(可以在源和副本上使用不同的存储引擎。例如,如果副本的可用磁盘空间较少,则可以在源上使用
InnoDB
,但在副本上使用MyISAM
。)MySQL 缓冲区大小(
key_buffer_size
等)在源和副本上不同。源和副本运行不同的 MySQL 版本,并且优化器代码在这些版本之间有所不同。
此问题也可能影响使用 mysqlbinlog|mysql 进行的数据库恢复。
避免此问题的最简单方法是向上述非确定性查询添加
ORDER BY
子句,以确保始终以相同的顺序存储或修改行。使用基于行或混合的日志记录格式也可以避免此问题。如果您没有使用启动选项指定文件名,则日志文件名将基于服务器主机名。如果要将主机名更改为其他名称时保留相同的日志文件名,则必须显式使用选项,例如
--log-bin=
。请参阅第 7.1.7 节 “服务器命令选项”。或者,重命名旧文件以反映主机名更改。如果这些是二进制日志,则还必须编辑二进制日志索引文件并在其中修复二进制日志文件名。(对于副本上的中继日志也是如此。)old_host_name
-binmysqlbinlog 不会删除
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
精度执行。如果无符号 long long 值解析为大于 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
的方式可能与不使用时不同。在连接中,隐藏列将被计入结果(即使未显示),而在普通查询中,隐藏列不参与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
向MERGE
表中使用的表添加UNIQUE
索引,然后在MERGE
表上添加普通索引,则如果表中存在旧的非UNIQUE
键,则这些表的键顺序将不同。这是因为ALTER TABLE
会将UNIQUE
索引放在普通索引之前,以便能够尽早检测到重复键。