MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?

大家好 , 我是小林 。
最近重新补充了《MySQL 有哪些锁》文章内容:

  • 增加记录锁、间隙锁、net-key 锁
  • 增加插入意向锁
  • 增加自增锁为 innodb_autoinc_lock_mode = 2 模式时 , 为什么主从环境会有不安全问题的说明
所以 , 现在内容还是比较全面的 , 基本把 MySQL 用到的锁都说了一遍 , 大家可以在复习复习 。
这次 , 来说说 MySQL 的锁 , 主要是 Q&A 的形式 , 看起来会比较轻松 。
不多 BB 了 , 发车!
在 MySQL 里 , 根据加锁的范围 , 可以分为全局锁、表级锁和行锁三类 。
MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?

文章插图
全局锁
全局锁是怎么用的?
要使用全局锁 , 则要执行这条命:
flush tables with read lock执行后 , 整个数据库就处于只读状态了 , 这时其他线程执行以下操作 , 都会被阻塞:
  • 对数据的增删改操作 , 比如 insert、delete、update等语句;
  • 对表结构的更改操作 , 比如 alter table、drop table 等语句 。
如果要释放全局锁 , 则要执行这条命令:
unlock tables当然 , 当会话断开了 , 全局锁会被自动释放 。
全局锁应用场景是什么?
全局锁主要应用于做全库逻辑备份 , 这样在备份数据库期间 , 不会因为数据或表结构的更新 , 而出现备份文件的数据与预期的不一样 。
举个例子大家就知道了 。
在全库逻辑备份期间 , 假设不加全局锁的场景 , 看看会出现什么意外的情况 。
如果在全库逻辑备份期间 , 有用户购买了一件商品 , 一般购买商品的业务逻辑是会涉及到多张数据库表的更新 , 比如在用户表更新该用户的余额 , 然后在商品表更新被购买的商品的库存 。
那么 , 有可能出现这样的顺序:
  1. 先备份了用户表的数据;
  2. 然后有用户发起了购买商品的操作;
  3. 接着再备份商品表的数据 。
也就是在备份用户表和商品表之间 , 有用户购买了商品 。
这种情况下 , 备份的结果是用户表中该用户的余额并没有扣除 , 反而商品表中该商品的库存被减少了 , 如果后面用这个备份文件恢复数据库数据的话 , 用户钱没少 , 而库存少了 , 等于用户白嫖了一件商品 。
所以 , 在全库逻辑备份期间 , 加上全局锁 , 就不会出现上面这种情况了 。
加全局锁又会带来什么缺点呢?
加上全局锁 , 意味着整个数据库都是只读状态 。
那么如果数据库里有很多数据 , 备份就会花费很多的时间 , 关键是备份期间 , 业务只能读数据 , 而不能更新数据 , 这样会造成业务停滞 。
既然备份数据库数据的时候 , 使用全局锁会影响业务 , 那有什么其他方式可以避免?
有的 , 如果数据库的引擎支持的事务支持可重复读的隔离级别 , 那么在备份数据库之前先开启事务 , 会先创建 Read View , 然后整个事务执行期间都在用这个 Read View , 而且由于 MVCC 的支持 , 备份期间业务依然可以对数据进行更新操作 。

经验总结扩展阅读