一夫当关万夫莫开,MySQL全局锁(FTWRL)真香

SQL herman 79浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xmtxtt,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序

这是一把好锁,真香!

MySQL 全局锁,听到的人可能真没多少。一方面是一些人认为 DBA 才需要深入吧,另一方面多数人接触不到这么深的知识。还有一方面可能就真如大家所说的“没有时间学习”!

昨天那篇文章,我提到了一个数据迁移。我们来看一个场景,现在我为了缩小因删除等造成的 MySQL 占用空间居高不下,我需要进行数据迁移。但是在数据迁移之间,如果还有数据被写入数据库了。如何保证我迁移的就是全量数据,一条也不少呢?

Flush tables with read lock

因为我一边读,一边有数据写入。比如一个表,我已经复制完了,你又新增数据了怎么搞?这时最简单的办法就是使用全局锁。

全局锁你也可以理解为数据库级别的锁。也就是锁,这把锁会加给整个数据库。对于上面的场景,我们其实是可以加了全局读锁。一条命令就搞定。

Flush tables with read lock;

Flush tables with read lock 也被简称为 FTWRL。执行这个语句,它会让整个库被处于只读状态。之后的增删改语句就会被阻塞,包括事务的提交,表结构的修改与创建等。

处于只读状态的数据库,我们就可以尽情的去复制了。因为这时你复制的就是整个库,全量数据。所以这把锁一夫当关万夫莫开,真香。

MySQL全局锁

别以为,这把锁力度太大,没什么卵用。其实真实开发工作中,有时候它能帮你解决掉不少麻烦。正所谓存在即合理!

FTWRL 这个命令主要用于备份工具获取一致性备份(数据与binlog位点匹配)。由于 FTWRL 总共需要持有两把全局的 MDL 锁(后面写文章讲),并且还需要关闭所有表对象,因此这个命令的杀伤性很大,执行命令时容易导致库 hang 住。如果是主库,则业务无法正常访问;如果是备库,则会导致 SQL 线程卡住,主备延迟。

数据的一致性有多重要,我就不多说了。最常见的就是你在遍历一个 Java 集合时,可能会出现 ConcurrentModificationException 问题。也就是并发修改异常。这个知识点,我下篇文章来写。这里原谅我先预告一下!

FTWRL 这么牛,背后到底做了哪些事情?它主要干 3 件事。

  1. 上全局读锁(lock_global_read_lock);
  2. 清理表缓存(close_cached_tables);
  3. 上全局COMMIT锁(make_global_read_lock_block_commit)。

上全局读锁会导致所有更新操作都会被堵塞;关闭表过程中,如果有大查询导致关闭表等待,那么所有访问这个表的查询和更新都需要等待;清理表缓存也就是每个表在内存中都有一个 table_cache,不同表的 cache 对象通过 hash 链表维护,刷新它自己的 data,同时也刷新操作系统的 data 到 disk 上;上全局 COMMIT 锁时,会堵塞活跃事务提交。

上全局读锁和上全局 COMMIT 锁都是通过 MDL 锁实现的。这个 MDL 锁 MySQL 底层用到的比较多。后面有文章来重点写。除了本文介绍的锁,MySQL 还有表锁,行级锁等各种锁,我后面会抽时间来一一书写,感兴趣的可以长期的关注!

最后在说一点,当我们执行这个语句后,如何释放锁呢?也就是取消这个锁。也很简单,下面的一条语句即可搞定。

unlock tables

以上,希望能够帮助到大家!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 一夫当关万夫莫开,MySQL全局锁(FTWRL)真香