总的说来flush tables with read lock多用于备份的时候对全局表进行锁定来获取binlog信息。虽然持有时间很短,但容易被大 *** 作堵塞造成备份不能完成。那么flush tables with read lock到底做了什么事情呢如下:
(下面的信息是在源码函数 acquire_lock和release_lock增加输出达到的,具体可以安装
https://github.com/gaopengcarl/percona-server-locks-detail-5.7.22.git
查看readme使用)
下面的信息可以看到flush tables with read lock获取MDL LOCK的信息:
下面是unlock tables释放MDL LOCK的信息:
如下是关于范围 MDL LOCK的兼容性:
等待为:Waiting for global read lock
堵塞栈帧:
等待为:Waiting for table flush
堵塞栈帧:
等待为Waiting for commit lock
基本我们看到所有的语句都会堵塞FTWRL。
等待为:Waiting for global read lock
堵塞栈帧:
等待为Waiting for commit lock
堵塞栈帧:
对于FTWRL percona做了改进应该是backup lock和binlog lock来代替。
具体参考如下:
https://www.percona.com/doc/percona-server/5.6/management/backup_locks.html?spm=5176.11156381.0.0.30d8e606aPdjeQ
官方版本测试到8.0.21依旧存在这个问题,Percona已经修复了,修复如下https://www.percona.com/blog/2018/03/27/analyze-table-is-no-longer-a-blocking-operation/
能力有限简单记录。
问题如下:
乍一看来,很是奇怪,这里没有出现我们经常遇到的flush table/flush table with read lock 堵塞,直接出现了 Waiting for table flush的堵塞,有点像
https://www.jianshu.com/p/b141585cd844
以前记录的文章中的案例2,但是其实并不一样,这里是由于analyze table语句造成的。构造非常简单(必须是社区版本,我使用的8.0.21),如下:
此时堵塞的情形就是Waiting for table flush
analyze table 除了更新我们的统计数据,实际上最后做了一个 *** 作如下(栈):
大概看一下做了什么,如下:
这里判断了是否当前table share正在使用,如果正在使用(很显然我们这个table share是不能直接释放的,因为有select一直持有它)那么将share版本的设置为0(share->clear_version(),实际上这个版本由全局变量refresh_version初始化),目的在于下次如果有使用表定义的时候需要重新打开table share。然后释放了当前没有使用的table cache(类型TDC_RT_REMOVE_UNUSED),如下:
当再次访问表的时候(open_table),会去判断如下是否有老的table share存在,如果存在则需要等待释放:
首先如果存在判断是否存在的老版本,判断是通过table share的版本和当前全局版本refresh_version进行比对,前面我们知道这里table share的版本已经设置为0,因此这里必然进入release_table_share环节,然后等待持有者的释放(案例窗口1的select查询),然后再次获取table share。等待栈如下:
进入waiting for table flush状态
Percona在上文中已经提到问题如下:
一个关键的修改点如下
官方版本:
Percona版本:
如此修改后analyze不会进入tdc_remove_table函数,那么table share的版本不会设置为0。因此如果使用官方版本小心本问题。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)