MySQL-14丨MySQL全局锁和表级锁

Posted by jiefang on October 28, 2019

MySQL全局锁和表级锁

全局锁

MySQL全局锁会关闭所有打开的表,并使用全局锁锁定所有的表。简称:FTWRL

1
FLUSH TABLES WITH READ LOCK;

解锁命令

1
UNLOCK TABLES;

当执行 FTWRL 后,所有的表都变成只读状态,数据更新或者字段更新将会被阻塞。

那么全局锁一般什么时候会用到呢?

全局锁一般用在整个库(包含非事务引擎表)做备份(mysqldump或者xtrabackup)时。也就是说,在整个备份过程中,整个库都是只读的,其实这样风险挺大的。如果是在主库备份,会导致业务不能修改数据;而如果是在从库备份,就会导致主从延迟。在mysqldump包含一个参数–single-transaction,可以在一个事务中创建一致性快照,然后进行所有表的备份。增加这个参数,备份期间可以进行数据修改,但是需要所有表都是事务引擎表,这是建议使用InnoDB存储引擎的原因之一。

表级锁

表级锁有两种:表锁元数据锁

表锁

表锁使用场景:

  • 事务需要更新某张大表的大部分或全部数据。如果使用默认的行锁,不仅事务执行效率低,而且可能造成其它事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高事务执行速度;
  • 事务涉及多个表,比较复杂,可能会引起死锁,导致大量事务回滚,可以考虑表锁避免死锁;

表读锁:

1
lock tables t14 read;

表写锁:

1
lock tables t14  write;

对表执行 lock tables xxx read (表读锁)时,本线程和其它线程可以读,本线程写会报错,其它线程写会等待。 对表执行 lock tables xxx write (表写锁)时,本线程可以读写,其它线程读写都会阻塞。

元数据锁

在 MySQL 中,DDL 是不属于事务范畴的。如果事务和 DDL 并行执行同一张表时,可能会出现事务特性被破坏、binlog 顺序错乱等 bug(比如 bug#989)。为了解决这类问题,从 MySQL5.5.3 开始,引入了元数据锁(Metadata Locking,简称:MDL 锁)。应该尽量避免慢查询、尽量保证事务及时提交、避免大事务等,当然对于 DBA 来说,也应该尽量避免在业务高峰执行 DDL 操作。

总结

  • 全局锁会让所有的表变成只读状态,所有更新操作都会被阻塞。 而表级锁分为表锁和元数据锁。表锁分为表读锁和表写锁,两者的区别是:
    • 表读锁:本线程和其它线程可以读,本线程写会报错,其它线程写会等待。
    • 表写锁:本线程可以读写,其它线程读写都会阻塞。

MDL 锁机制,应该注意的几个点是:

  • 尽量避免慢查询;
  • 事务要及时提交;
  • 避免大事务;
  • 避免在业务高峰执行 DDL 操作;