其他分享
首页 > 其他分享> > 06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?

06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?

作者:互联网

原文链接:https://time.geekbang.org/column/article/69862

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

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

 

全局锁

顾名思义,就是对整个数据库实例加锁。加锁命令Flush tables with read lock(FTWRL)。加上锁以后,数据更新语句、数据定义语句和更新类食物的提交语句都会被阻塞。

典型使用场景:做全库逻辑备份。

这种锁使得整个库在一段时间之内完全处于只读状态,业务基本上停滞,主从延迟。

可以使用事务的“可重复度隔离级别”,就是在可重复读隔离级别下开启一个事务(官方自带的逻辑备份工具mysqldump,使用参数-single-transaction的时候,导数据之前就会启动一个事务),由于MVCC的支持,这个过程中数据是可以正常更新的。

有好方法,为什么还要FTWRL?因为需要引擎支持这个隔离级别。比如,MySIAM就不支持事务。所以single-transaction方法只适用于所有的表使用事务引擎的库。

 

要全库只读,为什么不使用set global readonly=true的方式?

1.在有些系统中,readonly的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此修改global变量的方式影响面更大,不建议使用。

2.在异常处理机制上有差异。如果执行FTWRL命令执行之后有客户端发生异常断开,那么MySQL会自动释放这个全局锁。而将整个库设置为readonly之后,则不会,风险较高。

表级所

表级所有两种:表锁、元数据锁(meta data lock,MDL)。

表锁语法:lock tables ... read/write(例如lock tables t1 read,t2 write)。可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

InnoDB支持行锁,一般不使用lock tables命令来控制并发。

 

元数据锁MDL(meta data lock)。不需要显示使用,在访问一个表的时候会被自动加上。

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

读锁之间不互斥

读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。

 

如何给小表安全的加字段?

1.解决已经存在的长事务,避免加字段语句等待时间过长。通过information_schema库的innodb_trx表,可以查到当前执行中的事务,如果正好有长事务在执行,可以考虑先暂停DDL(加字段操作),或者kill掉这个长事务。

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

 

上一篇:05 | 深入浅出索引(下)

下一篇:07 | 行锁功过:怎么减少行锁对性能的影响?

 

标签:语句,表加个,事务,06,MDL,tables,lock,行锁,表锁
来源: https://blog.csdn.net/u012131610/article/details/90199938