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

这是一把好锁,真香!

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

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

一夫当关万夫莫开,MySQL全局锁(FTWRL)真香
Flush tables with read lock

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

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

Flush tables with read lock;

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

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

一夫当关万夫莫开,MySQL全局锁(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

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

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

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

原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/252419.html

(0)
上一篇 2022年5月4日
下一篇 2022年5月4日

相关推荐

发表回复

登录后才能评论