A.8.1. MySQL中的打开事宜

下面列出了已知问题,更正它们具有较高的优先级:

  • 如果将NULL值与使用ALL/ANY/SOME的子查询进行比较,而且子查询返回空的结果,比较操作会评估NULL的非标准结果而不是TRUEFALSE。在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命令等待,直至表未在任何事务中使用为止。
  • 将大的整数值(介于2632641之间)插入数值或字符串列时,它将作为负值插入,这是因为该数值是在有符号整数环境下评估的。
  • 如果服务器运行在不具备二进制日志功能的条件下,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 TABLEOPTIMIZE TABLEREPAIR 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 BYINSERT ... SELECTSELECT可能会以不同的顺序返回行(它会导致具有不同等级的行,从而导致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表中使用的表一起工作。
  • 由于表定义文件的保存方式,不能在表名、列名或枚举中使用字符255CHAR(255))。按照安排,当我们实施了新的表定义格式文件时,将在5.1版中更正该问题。
  • 使用SET CHARACTER SET时,不能在数据库、表和列名中使用转换的字符。
  • 不能在LIKE ... ESCAPE中与ESCAPE一起使用_’或‘%’。
  • 如果你有1DECIMAL列,其中,相同的数值以不同的格式保存(例如,+01.001.0001.00),GROUP BY可能会将每个值当作不同的值。
  • 使用MIT-pthreads时,不能在另一个目录下创建服务器。这是因为它需要更改MIT-pthreads,我们不太会更正该问题。请参见2.8.5 MIT-pthreads注意事项”
  • GROUP BYORDER BYDISTINCT中,不能可靠地使用BLOBTEXT值。在这类情况下,与BLOB值进行比较时,仅使用最前的max_sort_length字节。max_sort_length的默认值是1024,可在服务器启动时或运行时更改它。
  • 数值计算是使用BIGINTDOUBLE(正常情况下均为64位长)进行的。你所能获得的精度取决于函数。通用规则是位函数是按BIGINT精度执行的,IFELT()是按BIGINTDOUBLE精度执行的,其余的函数是按DOUBLE精度执行的。对于除位字段外的其他数,如果大于63位(9223372036854775807),应避免使用无符号长long值。
  • 1个表中,最多能有255ENUMSET列。
  • MIN()MAX()以及其他聚合函数中,MySQL目前会根据其字符串值比较ENUMSET列,而不是根据字符串在集合中的相对位置。
  • mysqld_safe会将来自mysqld的所有消息再定向到mysqld日志。与之相关的1个问题是,如果你执行mysqladmin refresh关闭并再次打开日志,stdoutstderr仍会被重定向到旧的日志。如果你以广义方式使用“--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 TABLEMERGE表中使用的表增加了UNIQUE索引,然后在MERGE表上增加了正常索引,如果在表中存在旧的、非UNIQUE键,对于这些表,键顺序是不同的。这是因为,ALTER TABLE会将UNIQUE索引放在正常索引之前,以便能尽早检测到重复的键。
 
关注编程学问公众号