MySQL-锁

1、锁

数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实现这些访问规则的重要数据结构。

2、锁定范围分类

根据加锁的范围,MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类。

2.1 全局锁

对整个数据库实例加锁。MySQL中加全局读锁的方法是FTWRL,也就是命令如下:

Flush tables with read lock

使用这个命令,可以让整个库处于只读状态,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

全局锁典型应用就是做全库逻辑备份。加全局锁影响太大,整个库都处于只读状态,一般不使用。为了备份时保持数据一致性,可以在可重复读隔离级别开启事务备份。

在innodb引擎中,使用逻辑备份工具 mysqldump,参数–single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。

还有一种设置全库只读的方法,设置参数 set global readonly=true,这种方式对超级管理员用户无效;还有就是影响太大,当连接异常断开,数据库一直处于只读状态,而使用FTWRL,断开后自动释放全局锁,恢复正常状态。

2.2 表级锁

表级锁分两种,一种是表锁、一种是元数据锁(MDL)。

表锁的语法是 lock tables … read/write。与 FTWRL 类似,可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。lock tables 除了会限制别的线程的读写外,也限定了本线程的操作对象。

对于 InnoDB 这种支持行锁的引擎,一般不使用 lock tables 命令来控制并发,锁住整个表的影响面还是太大。

MDL(metadata lock)。MDL 不需要显式使用,在访问一个表的时候会被自动加上。MDL 的作用是,保证读写的正确性。如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个表结构做变更,删了一列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。

在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

  • 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。

  • 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

因为MDL锁的存在,即使在修改小表的表结构时,也要格外注意。比如,事务A,select查询表T,表T自动加了MDL读锁;事务B,select查询表T,也是正常的,读锁不互斥;事务C,alter table 改变表结构,此事务被阻塞,因为事务A的读锁没有释放;事务D,select查询该表时,因为事务C的原因,也会被阻塞。之后所有要在表 T 上新申请 MDL 读锁的请求都会被事务C阻塞。所有对表的增删改查操作都需要先申请 MDL 读锁,就都被锁住,等于这个表T现在完全不可读写了。

在做表结构变更时,一般有两种方式

  • 要解决长事务,事务不提交,就会一直占着 MDL 锁。通过MySQL 的 information_schema 库的 innodb_trx 表中,可以查到当前执行中的事务。

  • 在 alter table 语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到 MDL 写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后再通过重试命令重复这个过程。

ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ... 

在MySQL5.6版本之后,支持online DDL,优化了对表结构变更的过程。
Online DDL的过程可以理解是这样的:

  1. 拿MDL写锁

  2. 降级成MDL读锁

  3. 真正做DDL

  4. 升级成MDL写锁

  5. 释放MDL锁

1、2、4、5如果没有锁冲突,执行时间非常短。第3步占用了DDL绝大部分时间,这期间这个表可以正常读写数据,是因此称为“online”。

posted @   原来是你~~~  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示