MySQL 原理与优化:原数据锁的应用
MySQL 中原数据锁是系统自动控制添加的,对于用户来说无需显示调用,当我们使用一张表的时候就会加上原数据锁。
原数据锁的作用是为了保护表原数据的一致性,如果在表上有活动事务的时候,不可以对元数据进行写入操作。也就是为了避免 DML 和 DDL 之间的冲突,保证读写的正确性。
说白了就是,在对数据表进行读写操作的时候,不能进行修改表结构的操作。
如上图所示,在执行 select 操作的时候,MySQL 会自动加上 shared_read 锁,在 insert,update, delete 以及 select for update 操作的时候会加上 shared_write 锁,这两类锁是兼容的。
在执行 alter table 操作的时候,会加上 exclusive 锁,这个锁与 shared_read 和 shared_write 锁 是互斥的,换句话说在做查询和更新表数据的时候,是不能够修改表结构的。
来看个例子
首先开启事务,使用 select 语句会针对表加上 shared_read 的共享锁
begin;
select * from course;
此时查看原数据锁的信息
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
通过上图我们可以发现,course 表加上了 shared_read 锁。
接着,开启另外一个事务,记住刚才的事务不要 commit
begin;
update course set name = 'Jason' where id =2;
如上图所示,此时的 update 语句可以执行成功,并没有被阻塞。说明 select 和 update 是不冲突的,他们的锁是兼容的。
再次查看原数据锁
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
从上面的截图可以看出,此时原数据锁的表中记录了两条记录分别是针对 course 表的 shared_read 和 shared_write 锁,也刚好对应我们执行的 select 和 update 操作。
最后,我们再启动第三个客户端,并且启动 第三个事务,执行 alter 语句,在 course 表中加入一个字段 hello 如下 。
begin;
alter table course add column hello int;
由于之前的事务没有提交所以修改表的操作会被阻塞,因为 shared_read 以及 shared_write 这两个锁 与 exclusive 之间是互斥的,所以会阻塞。
此时,回到最开始的两个客户端,对两个事务进行 commit 操作,再返回到第三个事务执行的 alter 语句出,发现语句顺利执行。
版权声明: 本文为 InfoQ 作者【崔皓】的原创文章。
原文链接:【http://xie.infoq.cn/article/31c336c02a99b8af093731e51】。文章转载请联系作者。
评论