全局表、表锁、行锁

全局锁
1,全局锁对整个数据库实例加锁,Flush tables with read lock(FTWRL)。
2,使用全局锁后,数据库处于只读状态,数据更新语句增删改、数据定义语句建表和修改表结构、更新类事务提交语句都会被阻塞。

3,全局锁应用于全库逻辑备份场景,整库select出来存成文本。
1)如果在主库上备份,备份期间业务基本停摆;
2)如果在从库上备份,备份期间不能执行主库同步的binlog,导致主从延迟。
3)如果不加锁,备份得到的库不是同一个逻辑时间点。

4,在可重复读隔离级别下开启事务,可确保拿到一致性视图,且备份过程中数据可以正常更新。
1)官方自带逻辑备份工具mysqldump,当mysqldump使用参数single-transaction,导数据前启动事务。
2)single-transaction方法适用于所有的表使用支持事务引擎的库。
3)MyISAM引擎不支持事务,备份中只能使用FTWRL。

5,全库只读,可以设置set global readonly=true,但不适合用于备份整库。
1)在一些系统中,readonly还会用来判断主备库,修改global变量影响面更大。
2)如果备份过程中客户端异常,数据库会一直保持readonly状态,导致整库长时间处于不可写状态,风险太高。
3)FTWRL客户端异常断开,MySQL会自动释放全局锁,整库可以回到正常更新状态。

表锁
1,表级锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL),引擎不支持行锁时使用表级锁。

2,表锁lock tables …read/write,限制当前线程与其他线程对表的读写。
1)read t1当前线程只读t1,其他线程只读t1;
2)write t2当前线程读写t2,其他线程不可读写t2;
3)其他表不可访问;
4)与FTWRL类似,unlock tables主动释放锁,客户端断开后会自动释放。

3,元数据锁不需要显式使用,访问表时自动加上,MDL的作用是保证读写的正确性。
1)对表做增删改查操作时加MDL读锁,对表结构做变更时加MDL写锁。
2)读锁之间不互斥,读写及写锁之间互斥,保证变更表结构的安全性。
3)在事务中执行相关语句,系统自动加上MDL锁,语句结束后不会立即释放,事务提交后才会释放MDL锁。
4)长事务不提交占着MDL读锁,则写锁阻塞,写锁之后的读锁也被阻塞,导致表不可读写,如果客户端有重试机制,库的线程很容易爆满。
5)在alter table语句里设置等待时间WAIT N,如果在等待时间里拿到MDL写锁则执行表的变更,如果没拿到写锁也不会阻塞后面的业务,之后可以重试重复这个过程。

行锁
1,行锁是由引擎层实现,MyISAM引擎不支持行锁,控制并发时只能使用表锁。

2,在InnoDB事务中,更新语句时加上行锁,语句结束不释放锁,事务结束后释放行锁,为两阶段锁。

3,当并发中不同线程出现循环资源依赖,涉及的线程都在等待其他线程释放资源,导致线程进入无限等待状态,称为死锁。出现死锁后,
1)一种策略是进入等待直到超时,innodb_lock_wait_timeout设置超时时间。
2)一种策略是发起死锁检测,发现死锁,主动回滚死锁链表中的一个事务,让其他事务可以继续执行,设置参数innodb_deadlock_detect为on,表示开启死锁检测。
3)innodb_lock_wait_timeout默认值为50s,等待时间较长。设置为小值后,出现死锁可以很快解开,但如果不是死锁,只是锁的等待时间,则会误伤。
4)采用死锁检测策略,每一个事务被锁,需要检测依赖的其他线程有没有被锁,如此循环,最后判断是否出现了循环等待,即使检测结果没有死锁,但检测过程消耗了大量的CPU资源,虽然CPU利用率很高,每秒却执行不了几个事务。

4,比较好的思路是开启死锁检测并控制并发量,出现死锁了就回滚,再业务重试,这是业务无损的。
1)如果关闭死锁检测则可能出现大量超时,这是业务有损的;
2)控制并发量死锁检测的成本比较低,数据库服务端做好并发控制。

扫描二维码关注公众号,回复: 15492333 查看本文章

5,也可以将某一行逻辑修改为逻辑上的多行减少锁冲突。
1)设计一行数据为多行记录之和,可选随机的一行更新数据,降低冲突概率。
2)如果有中间件,可在中间件实现,或者修改MySQL源码,对相同行的更新,在进入引擎前排队,则InnoDB内部不会出现大量死锁检测了。
3)如果事务中需要锁多行,把最可能造成冲突,影响并发的行锁往后放。

6,例:如果要删除一个表里面前10000行数据:
1)直接执行delete from T limit 10000,单个语句占用时间长,锁的时间也比较长,如果是大事务会导致主从延迟。
2)在一个连接中循环执行20次delete from T limit 500,相对较好。
3)在20个连接中同时执行delete from T limit 500,会人为造成锁冲突。

猜你喜欢

转载自blog.csdn.net/mei_true/article/details/127521619