定义
- 当出现并发访问时,数据库需要合理地控制资源的访问规则,锁就是用来实现这些访问规则的
- 根据加锁的范围,Mysql里面的锁大致可以分成全局锁,表级锁和行锁三类。
全局锁
- 对整个数据库实例加锁,命令
Flush tables with read lock(FTWRL)
,在客户端断开时会自动释放,较安全。 - 当你需要让整个库处于只读状态时可以使用,之后其他线程的以下语句会被阻塞:
数据更新语句
,数据定义语句
,更新类事务的提交语句
。 - 典型使用场景是,全库逻辑备份。使用全局锁是为了保持数据一致性。
- 当 mysqldump 使用参数–single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。但是只有InnoDB支持。
表级锁
- Mysql里面表级别的锁有两种:表锁和元数据锁(meta data lock,MDL)。
// 表锁语法:
// 上锁
lock table 表名 read/write;
// 释放锁
// 与FTWRL类似,会在客户端断开时自动释放。
unlock tables;
元数据锁
- 另一类表锁是MDL,不需要显示使用。在访问一个表的时候会被主动加上,保证读写的准确性。
- 比如A线程在遍历,B线程要改表结构,需要保证查询线程拿到的结果和表结构一致,这时候就不能让他改。
- 5.5版本引入MDL,当对表数据增删改查时加MDL 读锁;当要对表做结构变更操作时,加MDL写锁。
读锁之间不互斥,读写之间和写锁之间是互斥的。
事务中的MDL锁,在语句执行时申请,但是只有整个事务提交了才释放。
实际场景
- 在频繁读的表上,执行DDL,比如前面的读语句的事务未提交,执行DDL就拿不到MDL写锁,会阻塞,后面的读语句就会拿不到MDL读锁,都堵住了。
- 解决长事务,在Mysql的information_schema库的innodb_trx中,找到长的事务,可以kill掉。
- 使用以下语句,加上等待时间,等待时间内能拿到MDL写锁最好,拿不到也不要阻塞后面的语句。
ALTER TABLE 表名 NOWAIT ADD COLUMN...
ALTER TABLE 表名 WAIT N ADD COLUMN...
来源:CSDN
作者:KeyboardMan6
链接:https://blog.csdn.net/weixin_40108561/article/details/104186762