zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

【MySQL】磁盘写满之后,数据库show status受到阻塞的原因

mysql数据库 原因 磁盘 之后 status 阻塞 show
2023-09-11 14:19:43 时间

编辑手记:前两天同事讨论到一个问题,当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



当一个新操作被接收到slave io线程后,如果这时候磁盘写满了,这个写入操作就会被阻塞,然后等待,直到磁盘有空间之后继续写入,这个操作中,会持有mi- data_lock锁,只有操作完成或者操作失败后,这个锁才会被释放,恰好,磁盘满不属于错误,于是操作阻塞,该线程会一直持有mi- data_lock锁。


当发起一个show slave status请求的时候,执行的时候,会首先锁住LOCK_active_mi锁,然后锁定mi- data_lock锁,当然,现在的情况下,mi- data_lock不会得到,于是LOCK_active_mi锁就会被该线程持续持有。


另外其一个会话发起show global status,执行的时候首先锁定LOCK_status锁,由于show status包括,Slave_heartbeat_period,Slave_open_temp_tables,Slave_received_heartbeats               ,Slave_retried_transactions这些状态,于是还需要LOCK_active_mi锁,于是,这个会话也会被阻塞掉。


之后如果再另外发起请求,由于LOCK_status已经被锁定,于是所有涉及show status的请求,都会被阻塞到这里。



看了以上的结论,是否会想到另外一个操作顺序:磁盘写满- show status,这种操作的结果是:show status不会被阻塞的。


以下是mysql源代码(5.5.37)涉及到的具体部分:

1.io线程阻塞的相关函数及部分代码

slave.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1
slave.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

log.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

log.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

mf_locache.c

640?wx_fmt=png wxfrom=5 wx_lazy=1

640?wx_fmt=png wxfrom=5 wx_lazy=1

my_write.c

640?wx_fmt=png wxfrom=5 wx_lazy=1


errors.c

640?wx_fmt=png wxfrom=5 wx_lazy=1


2.show slave status相关的函数及部分代码

sql_parse.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

sql_parse.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

slave.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1


3.show status相关的函数及部分代码

mysqld.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

sql_show.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1

sql_show.cc

640?wx_fmt=png wxfrom=5 wx_lazy=1


本文出自数据和云公众号,原文链接


MySQL 磁盘满了,怎么办?? 使用命令发现磁盘使用率为100%了,还剩几十兆。 一系列神操作: 备份数据库,删除实例、删除数据库表、重启mysql服务.结果磁盘空间均为释放 网上查了很多资源,说要进行磁盘碎片化整理。原因是datafree占据的空间太多啦。具体可以通过这个sql查看。
Mysql数据库表分区存储到指定磁盘路径 0. 前提: mysql5.6.6以上的版本以上的版本才支持单表指定目录,且目录权限是mysql:mysql。 在mysql中数据文件存放于在my.cnf中datadir指定的路径,使用的表引擎不同产生的文件格式、表文件个数也会有所差异。 mysql的表引擎有多种,表的扩展名也不一样,如innodb用“ .ibd”,archive用“.arc ”,csv用“.csv”等。
Mysql数据库表分区存储到指定磁盘路径 在mysql中数据文件存放于在my.cnf中datadir指定的路径,使用的表引擎不同产生的文件格式、表文件个数也会有所差异。
MySQL探秘(四):InnoDB的磁盘文件及落盘机制 任何一个技术都有其底层的关键基础技术,这些关键技术很有可能也是其他技术的关键技术,学习这些底层技术,就可以一通百通,让你很快的掌握其他技术。如何在磁盘上存储数据,如何使用日志文件保证数据不丢失以及如何落盘,不仅是MySQL等数据库的关键技术,也是MQ消息队列或者其他中间件的关键技术之一
[教程]在CentOS7上配置 FTP服务器 Proftpd 支持 MySQL 虚拟用户加密认证以及磁盘限额(Quota) 本文软件采用 yum 安装,不需要编译,而且随时都可以跟随 CentOS 升级 Proftpd 到最新版本,以避免可能的漏洞攻击。利用 Proftpd 现成的配置以及设置好的各种模块,可以实现 sftp 和 ssh 的结合,完美的实现虚拟用户加密密码存放于数据库。