MySQL中的锁可以分为三类:全局锁,表级锁和行锁。
全局锁
全局锁是对整个数据库加锁,可以让整个数据库处于只读状态,其后的数据更新、数据定义、事务更新等语句会被阻塞。
加锁方法:Flush tables with read lock
, 简写为FTWRL。
使用场景:全库逻辑备份。 即将整库的每个表都select出来存储为文本。
全局锁潜在的危险:
- 在主库上备份,备份期间不能更新,业务停滞
- 在从库上备份,备份期间不能执行主库同步过来的binlog,导致主从延迟。
如果不加全局锁可能会出现的问题:
备份系统备份得到的库不是一个逻辑时间点,视图逻辑不一致。
在可重复读隔离级别下开启一个事务可以拿到一致性视图。官方自带的逻辑备份工具是mysqldump,在使用时加上--single-transaction参数会启动事务。
有些存储引擎不支持事务引擎,因此需要用到FTWRL命令。
表级锁
表级锁有两种:表锁、 元数据锁(meta data lock, MDL)。
加锁方法:lock tables ... read/write
。
释放锁的方法:unlock tables主动释放,客户端断开自动释放。 表锁的读锁和写锁,以及写锁与写锁互斥。
MDL锁的作用是防止DDL和DML并发的冲突,也即一个语句为数据的增删改查,一个语句为修改表的结构,字段等。
MDL不需要显示使用,在访问一个表的时候回自动加上。执行增删改查语句是会加MDL读锁,执行表结构变更语句是会加MDL写锁。
长事务情况下事务不提交,可能会一直占用MDL锁,导致后续的语句被阻塞。解决方法是在alter table语句里面设置等待时间,如果在等待时间里面拿不到MDL锁不要阻塞后面的业务语句。
alter table tbl_name NOWAIT add column ...
alter table tbl_name WAIT N add column...
网友评论