编辑手记:前两天同事讨论到一个问题,当mysql从库磁盘满之后,show status及show slave status会被卡住,但其他select操作不受影响,但如果数据库是主库,磁盘满了之后,只有dml会被阻塞,select及show是不会受影响的。于是一群人讨论了一会,最后决定,SMC,以下就是我的结论。
1..以下所有讨论都基于mysql 5.5.37版本及官方文档,不保证适用于其他版本。
2.下文中提到的磁盘满,指的是数据文件(数据文件,日志文件,配置文件)所在磁盘分区。
3.由于篇幅问题,最后面的代码部分,只有关键的函数及逻辑判断部分。
首先查看官方文档(https://dev.mysql.com/doc/refman/5.5/en/full-disk.html),有以下观点:
1.实例每分钟检查是否有足够的空间写入。如果已经有空间了,继续执行操作。 2.每十分钟给日志文件写入一条记录,报告磁盘已经写满。
但是对不对?
下面是我对官方文档的测试结果:
1.如果主库上打开binlog,那么当磁盘满之后,每10分钟,数据库会报告一条Disk is full writing './mysql-bin.000001' (Errcode: 28). Waiting for someone to free space... (Expect up to 60 secs delay for server to continue after freeing disk space),也就是说bin log写满了,等待磁盘空间,这与文档描述相同。 2,如果在主库上关闭binlog,当磁盘满了之后,任何插入行为都会失败,报错为[ERROR] ./mysqld: The table 'x' is full,官方文档没有提到这个情况,此处的表x是innodb表。 上面是对主库所在磁盘写满之后,数据库实例的反应,下面讲讲我们遇到的情况:从库磁盘写满之后,show status及show slave status会被卡住,但其他select操作不受影响。
整个流程涉及3把锁:
1.mi->data_lock 2.LOCK_active_mi 3.LOCK_status
看了以上的结论,是否会想到另外一个操作顺序:磁盘写满->show status,这种操作的结果是:show status不会被阻塞的。
以下是mysql源代码(5.5.37)涉及到的具体部分:
1.io线程阻塞的相关函数及部分代码
slave.cc
slave.cc
log.cc
log.cc
mf_locache.c
my_write.c
errors.c
2.show slave status相关的函数及部分代码
sql_parse.cc
sql_parse.cc
slave.cc
3.show status相关的函数及部分代码
mysqld.cc
sql_show.cc
sql_show.cc