
在我们系统中有一张表它的查询概率非常高。 最近有个需求,需要对这个表增加一个字段 ,然而在增加字段的时候发现系统中有多个业务出现了超时 *** 作,那么这个是什么原因导致的呢?经过查阅资料发现是数据库的 MDL锁+事务导致 的。
MDL锁属于表级别的元数据锁。 表级别锁分为数据锁和元数据锁,通常我们说的加锁一般指的是加的数据锁。跟数据锁一样,元数据锁也分读锁和读写锁。
MDL不需要显示使用,在进行表 *** 作时会自动加上 。当对表进行增删改查时,会自动加上MDL读锁;当要对表进行加减字段的结构修改时,会自动加上MDL写锁。
MDL锁的存在,其实是为了保证数据的一致性。 想象一下,假如没有MDL锁,一个查询在遍历表数据的过程中,另外一个线程执行了ALTER TABLE t DELETE COLUMN 'col_1'把col_1这一列删掉了,那查询结果就乱了,结果中是否应该有这一列数据?
:表示正常往下执行
:表示卡住了,即无法往下执行。
解释:
步骤 1 2 正常执行。执行步骤2 时,会申请表customer的MDL的 SHARED_READ 锁。
步骤3 会卡住, 因为此时会申请表customer的MDL的EXCLUSIVE锁,但是事物一的事物没有提交,此时是无法申请到EXCLUSIVE锁,因为它们是互斥的。
步骤4 也会卡住,因为EXCLUSIVE锁和SHARE_READ锁是互斥的, 且EXCLUSIVE锁的优先级更高 ,所以步骤4 也会卡住。
步骤5 事物提交,释放表的SHARE_READ锁,之后就可以执行6 和7 的 *** 作了。
如果先执行事务二,在执行事务三,则是可以成功的,因为alter数据ddl语句,和事物无关。
因此在我们开发的过程中,需要避免大的事务 *** 作,防止占有锁的时间过长。
mysql 为并发事务同时对一条记录进行读写时,提出了两种解决方案:1)使用 mvcc 的方法,实现多事务的并发读写,但是这种读只是“快照读”,一般读的是历史版本数据,还有一种是“当前读”,一般加锁实现“当前读”,或者 insert、update、delete 也是当前读。
2)使用加锁的方法,锁分为共享锁(读锁),排他锁(写锁)
快照读:就是select
当前读:特殊的读 *** 作,插入/更新/删除 *** 作,属于当前读,处理的都是当前的数据,需要加锁。
mysql 在 RR 级别怎么处理幻读的呢?一般来说,RR 级别通过 mvcc 机制,保证读到低于后面事务的数据。但是 select for update 不会触发 mvcc,它是当前读。如果后面事务插入数据并提交,那么在 RR 级别就会读到插入的数据。所以,mysql 使用 行锁 + gap 锁(简称 next-key 锁)来防止当前读的时候插入。
Gap Lock在InnoDB的唯一作用就是防止其他事务的插入 *** 作,以此防止幻读的发生。
Innodb自动使用间隙锁的条件:
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)