为什么MySQL表崩溃?我该如何预防?


9

我是Moodle网站的管理员,该网站的Users表损坏了,因此无法使用。

幸运的是,一个简单的方法REPAIR TABLE mdl_user使它可以再次工作。问题是我不知道为什么它实际上崩溃了并使它无法使用,我想确保下次可以更好地进行准备。

我不是一个经验丰富的DBA,我只是做很多事情的开发人员,所以请多多包涵。

我可以恢复备份,但是我想有防止崩溃的方法。

这些表是utf8_general_ci并使用MyISAM。

为什么MySQL表崩溃?我该怎么做才能防止这种情况发生?

Answers:


11

MyISAM表崩溃很容易。

每个MyISAM表的标题中都有一个计数器,该计数器跟踪对该表有多少打开的文件句柄。

如果您启动mysql并且标题中的数字与实际文件句柄的数目不匹配,则mysqld将该表视为已崩溃。

如果一个简单的文件REPAIR TABLE mdl_user每次都能重新运行而又不会丢失数据,则可能表明您有一个流量非常高的站点,该站点写入mdl_user

如果数十张表需要此表REPAIR TABLE,我会将所有表都转换为InnoDB。但是,如果该mdl_user表是唯一出现此问题的表,则可以执行某些操作(对于本示例,假设数据库为moodle);

如果要将所有表保留为MyISAM

步骤01:创建维修表脚本

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

步骤02:将修复脚本声明为启动文件

将此添加到/etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

步骤03:重新启动mysql

每次重新启动mysql都会触发修复表脚本

如果您希望所有表都成为InnoDB

运行此代码以将MyISAM表批量转换为InnoDB脚本,然后进行查看

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

对转换脚本的内容满意后,请运行它

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

更新2012-03-15 14:00 EDT

@Kevin,在使用MyISAM时,如果磁盘空间不足,该怎么办?

这里是要考虑的事情:根据MySQL 5.0认证研究指南

在此处输入图片说明

项目符号#11在第408,409页第29.2节中说:

如果在向MyISAM表添加行时磁盘空间不足,则不会发生任何错误。服务器将挂起操作,直到空间可用,然后完成操作。

当磁盘空间不足时,请勿仅关闭或杀死mysql。当前未使用的任何MyISAM中打开文件句柄的数量都不会清除。因此,MyISAM表被标记为崩溃。如果您可以在仍运行mysqld的情况下释放数据卷中的磁盘空间,则一旦磁盘空间可用,mysqld就会继续运行。


反应出色。不知道文件句柄的多少,您已经解决了在出现问题时如何防止(或自动修复)的问题。如果该站点实际上对mdl_user(或任何其他表)进行了大量写操作,那么是否有安全方面的建议?
AeroCross 2012年

您应该做三件事:1)增加RAM,2)增加max_connections,3)切换到InnoDB。
RolandoMySQLDBA 2012年

菜鸟在这里。我在哪里“运行”此代码?从文件上传到服务器还是从某些命令行?
UncaughtTypeError

0

我还在mysql上管理了一个moodle站点,对我们来说,导致表损坏的最常见原因是磁盘空间不足。


@RolandoMySQLDBA-是的,磁盘空间肯定是问题(与其他一些过程以及一般的管理理念有关)。不幸的是,清理空间后,我们看不到问题能够自行解决,或者没有及时解决问题。我的回答只是指出,对于我们的moodle / mysql实例,无论mysql / myisam应该做什么,磁盘空间问题都可能导致表崩溃。
凯文(Kevin)

-3

我找到了一条很好的行将所有表转换为InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName

这段代码可能还可以,但是它不能回答第一部分的问题(为什么MySQL表会崩溃?)。如果您的意思是它回答了第二部分(如何预防),请添加更多说明。
ypercubeᵀᴹ

还添加更多详细信息。运行此命令会转换数据库中的所有表吗?还是整个服务器?如果表转换失败并出现错误,将会发生什么?我们最终可能会转换一些表,而另一些表留在MyiSAM中?通常,DBA在运行此功能之前还应考虑哪些其他事项?
ypercubeᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.