A.8. MySQL中的已知事宜
- A.8.1. MySQL中的打开事宜
在本节中,列出了当前MySQL版本中的已知事宜。
关于平台相关事宜的更多信息,请参见2.12节,“具体操作系统相关的注意事项”和附录E:移植到其他系统中的安装和移植说明。
A.8.1. MySQL中的打开事宜
下面列出了已知问题,更正它们具有较高的优先级:
- 如果将NULL值与使用ALL/ANY/SOME的子查询进行比较,而且子查询返回空的结果,比较操作会评估NULL的非标准结果而不是TRUE或FALSE。在MySQL
5.1中将更正该问题。
- 对于IN的线子查询优化不像“=”那样有效。
- 即使使用了lower_case_table_names=2(允许MySQL记住数据库名和表名使用的大小写),对于函数DATABASE()或在各种日志内(在不区分大小写的系统上),MySQL也不会记住数据库名使用的大小写情况。
- 在复制操作中,撤销FOREIGN
KEY约束不工作,这是因为约束可能在从服务器上有另一个名称。
- REPLACE(以及具有REPLACE选项的LOAD
DATA)不会触发ON DELETE CASCADE。
- 如果未使用所有列而且仅使用DISTINCT列表中的列,在GROUP_CONCAT()中,DISTINCT不能与ORDER
BY一起工作。
- 如果1位用户拥有长时间运行的事务,而且另1位用户撤销了在事务中更新的某1表,那么在表用于事务本身之前,存在较小的机会,会在二进制日志中包含DROP
TABLE命令。我们计划更正该问题,方法是让DROP TABLE命令等待,直至表未在任何事务中使用为止。
- 将大的整数值(介于263和264–1之间)插入数值或字符串列时,它将作为负值插入,这是因为该数值是在有符号整数环境下评估的。
- 如果服务器运行在不具备二进制日志功能的条件下,FLUSH
TABLES WITH READ LOCK不能屏蔽COMMIT,执行完整备份时这可能会导致问题(表间的一致性问题)。
- 在某些情况下,作用在BDB表上的ANALYZE
TABLE会导致表不可用,直至重启mysqld为止。如果出现该情况,请在MySQL错误文件中查找下述形式的错误:
001207 22:07:56 bdb: log_flush: LSN past current end-of-log
- 在所有事务完成之前,不要在BDB表(正在其上运行多语句事务)上执行ALTER
TABLE(可能会忽略事务)。
- 对于正在使用INSERT
DELAYED的表,在其上执行ANALYZE TABLE、OPTIMIZE
TABLE和REPAIR TABLE时,可能会导致问题。
- 在表上执行LOCK
TABLE ...和FLUSH
TABLES ...时,不保证没有完成一半的事务。
- BDB表打开的速度相对较慢。如果你在数据库上有很多BDB表,如果未使用“-A”选项或正使用再混编功能,要想在数据库上使用mysql客户端,需要花费较长的时间。当你有大的表高速缓冲时,这点尤其明显。
-
复制功能采用了查询级日志功能:主服务器将已执行的查询写入二进制日志。这是一种速度很快、简洁和有效的记录方法,在大多数情况下工作良好。
如果以特定的方式设计查询,使得数据更改是非决定性(通常不推荐,即使在复制之外也同样),主服务器和从服务器上的数据将变得不同。
例如:
- 将0或NULL值插入AUTO_INCREMENT列中的CREATE ... SELECT或INSERT ...
SELECT语句。
- DELETE,如果从具有ON DELETE CASCADE属性的外键的表中删除行。
- 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子句,以确保总是以相同的顺序保存或更改行。
在将来的MySQL版本中,需要时,我们将自动增加ORDER
BY子句。
下面列出了已知的事宜,这些事宜将在恰当的时候更正:
- 日志文件名基于服务器主机名(如果未使用启动选项指定文件名的话)。如果更改了主机名,你将不得不使用诸如“--log-bin=old_host_name-bin”等选下美国。另一种选择是重命名旧文件,以反映主机名变更情况(如果是二进制日志,需要编辑二进制日志索引文件,并更正binlog名称)。请参见5.3.1节,“mysqld命令行选项”。
- Mysqlbinlog不删除执行LOAD
DATA INFILE命令后遗留的临时文件。请参见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具”。
- RENAME不能与TEMPORARY表一起工作,也不能与MERGE表中使用的表一起工作。
- 由于表定义文件的保存方式,不能在表名、列名或枚举中使用字符255(CHAR(255))。按照安排,当我们实施了新的表定义格式文件时,将在5.1版中更正该问题。
- 使用SET
CHARACTER SET时,不能在数据库、表和列名中使用转换的字符。
- 不能在LIKE ...
ESCAPE中与ESCAPE一起使用‘_’或‘%’。
- 如果你有1个DECIMAL列,其中,相同的数值以不同的格式保存(例如,+01.00、1.00、01.00),GROUP
BY可能会将每个值当作不同的值。
- 使用MIT-pthreads时,不能在另一个目录下创建服务器。这是因为它需要更改MIT-pthreads,我们不太会更正该问题。请参见2.8.5
“MIT-pthreads注意事项”。
- 在GROUP BY、ORDER
BY或DISTINCT中,不能可靠地使用BLOB和TEXT值。在这类情况下,与BLOB值进行比较时,仅使用最前的max_sort_length字节。max_sort_length的默认值是1024,可在服务器启动时或运行时更改它。
- 数值计算是使用BIGINT或DOUBLE(正常情况下均为64位长)进行的。你所能获得的精度取决于函数。通用规则是位函数是按BIGINT精度执行的,IF和ELT()是按BIGINT或DOUBLE精度执行的,其余的函数是按DOUBLE精度执行的。对于除位字段外的其他数,如果大于63位(9223372036854775807),应避免使用无符号长long值。
- 在1个表中,最多能有255个ENUM和SET列。
- 在MIN()、MAX()以及其他聚合函数中,MySQL目前会根据其字符串值比较ENUM和SET列,而不是根据字符串在集合中的相对位置。
- mysqld_safe会将来自mysqld的所有消息再定向到mysqld日志。与之相关的1个问题是,如果你执行mysqladmin
refresh关闭并再次打开日志,stdout和stderr仍会被重定向到旧的日志。如果你以广义方式使用“--log”,应编辑mysqld_safe以记录到host_name.err而不是host_name.log,以便通过删除它并执行mysqladmin
refresh,方便地收回为旧日志分配的空间。
- 在UPDATE语句中,列从左向右更新。如果引用了已更新的列,你将得到更新值而不是原始值。例如,下述语句会将KEY增加2,而不是1:
mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;
- 你可以在相同查询中引用多个临时表,但不能引用任何给定的临时表1次以上。例如,下述语句不能正常工作:
mysql> SELECT * FROM temp_table, temp_table AS t2;
错误1137:不能再次打开表:'temp_table'
- 当你在联合操作中使用“隐含”列时,与未使用隐含列相比,优化器将以不同的方式处理DISTINCT。在联合操作中,隐含列将作为结果的组成部份计数(即使未显示),但在正常查询中,隐含列不参与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;
在第2种情况下,使用MySQL服务器3.23.x,可在结果集中获得2个等同行(这是因为,隐藏ID列中的值可能不同)。
注意,在结果集中,仅对不含ORDER
BY列的查询才会出现该情况。
- 如果在返回空集的查询上执行PROCEDURE,在某些情况下,PROCEDURE不转换列。
- 创建具有MERGE类型的表时,不检查基本表是否具有兼容的类型。
- 如果使用ALTER
TABLE为MERGE表中使用的表增加了UNIQUE索引,然后在MERGE表上增加了正常索引,如果在表中存在旧的、非UNIQUE键,对于这些表,键顺序是不同的。这是因为,ALTER
TABLE会将UNIQUE索引放在正常索引之前,以便能尽早检测到重复的键。