第15章:存储引擎和表类型 / 15.2. InnoDB存储引擎 / 15.2.17. InnoDB故障诊断和排除

15.2.17.1. InnoDB数据词典操作的错误诊断和排除

·         一个总的规则是,当一个操作失败或这你怀疑有一个缺陷。你应该查看MySQL服务器的错误日志,该日志典型地有一个有些象hostname.err这样的名字,或者在Windows上是mysql.err这样的。

·         故障诊断与排除之时,通常最好从命令提示符运行MySQL服务器,而不是从mysqld_safe包运行,或不作为一个Windows服务来运行。你可以看mysqld打印到控制台上的内容,因此更好掌握发生了什么。在Windows上,你必须用--console选项启动服务器将输出定向到控制台窗口

·         使用InnoDB Monitors获取关于某问题的信息。如果问题是性能相关的,或者你的服务器看起来被挂起,你应该使用innodb_monitor来打印InnoDB内部状态的信息,如果问题是关于锁定,则使用innodb_lock_monitor。如果问题是在表的创建或其它数据词典操作,使用innodb_table_monitor来打印InnoDB内部数据词典的内容。

·         如果你猜测一个表被破坏,则在该表上运行CHECK TABLE。

15.2.17.1. InnoDB数据词典操作错误诊断和排除

表的一个特殊问题是MySQL服务器以.frm文件来保存数据词典信息,它被放在数据库目录,然而InnoDB也存储信息到表空间文件里它自己的数据词典里。如果你把.frm文件移来移去 ;或者,如果服务器在数据词典操作的中间崩溃,.frm文件可能结束与InnoDB内部数据词典的同步。

一个不同步的数据词典的症状是CREATE TABLE语句失败。如果发生这种情况,你应该查看服务器的错误日志。如果日志说表已经存在于InnoDB内部数据词典当中,你在InnoDB表空间文件内有一个孤表,它没有对应的.frm文件。错误信息看起来象如下的:

InnoDB: Error: table test/parent already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? Have you used DROP DATABASE
InnoDB: for InnoDB tables in MySQL version <= 3.23.43?
InnoDB: See the Restrictions section of the InnoDB manual.
InnoDB: You can drop the orphaned table inside InnoDB by
InnoDB: creating an InnoDB table with the same name in another
InnoDB: database and moving the .frm file to the current database.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.

你可以按照错误日志里给的指示移除一个孤表。如果还是不能成功地使用DROP TABLE,问题可能是因为在mysql客户端里的名字完成。要解决这个问题,用--disable-auto-rehash选项来启动mysql客户端并再次尝试DROP TABLE 。(有名字完成打开着,mysql试着构建个表名字的列表,当一个正如描述的问题存在之时,这个列表就不起作用)。

不同步数据词典的另一个“同义词”是MySQL打印一个不能打开.InnoDB文件的错误:

ERROR 1016: Can't open file: 'child2.InnoDB'. (errno: 1)

在错误日志你可以发现一个类似于此的信息:

InnoDB: Cannot find table test/child2 from the internal data dictionary
InnoDB: of InnoDB though the .frm file for the table exists. Maybe you
InnoDB: have deleted and recreated InnoDB data files but have forgotten
InnoDB: to delete the corresponding .frm files of InnoDB tables?

这意味这有一个孤单的.frm文件,在InnoDB内没有相对应的表。你可以通过手动删除来移除这个孤单的.frm文件。

如果MySQL在一个 ALTER TABLE操作的中间崩溃,你可以用InnoDB表空间内临时孤表来结束。你可以用innodb_table_monitor看一个列出的表,名为#sql-...。如果你把表的名字包在`(backticks)里,你可以在名字包含“#”字符的表上执行SQL语句。因此,你可以用前述的的方法象移除其它孤表一样移除这样一个孤表。注意,要在Unix外壳里复制或重命名一个文件,如果文件名包含"#"字符,你需要把文件名放在双引号里。