全局锁和表锁

霸气de小男生 提交于 2020-02-08 09:39:37

定义

  • 当出现并发访问时,数据库需要合理地控制资源的访问规则,锁就是用来实现这些访问规则的
  • 根据加锁的范围,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...
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!