锁
表锁
表锁是指上锁的时候锁住的是整个表,当下一个事务访问该表的时候,必须等前一个事务释放了锁才能进行对表进行访问;
表锁级别的两种锁:
-
表锁
表锁的语法是 lock tables … read/write
-
原数据锁 MDL (metadata lock)
server 层级别的锁。
主要用于隔离DML和DDL操作之间的干扰。
执行DML,需要申请 MDL 读锁
执行DDL,需要申请 MDL 写锁
给一个小表加个字段,导致整个库挂了
给一个表加字段,或者修改字段,或者加索引,需要扫描全表的数据。
在对大表操作的时候,你肯定会特别小心,以免对线上服务造成影响。而实际上,即使是小表,操作不慎也会出问题。
事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
sessionA 申请 MDL 读锁成功,但不提交事务,MDL读锁不会释放。
sessionB 申请 MDL 读锁成功,但不提交事务,MDL读锁不会释放。
sessionC DDL 操作,申请MDL写锁失败,阻塞住。
sessionD 申请 MDL 读锁失败,也被阻塞住。
申请MDL锁的操作会形成一个队列,队列中写锁获取优先级高于读锁。一旦出现写锁等待,不但当前操作会被阻塞,同时还会阻塞后续该表的所有操作。事务一旦申请到MDL锁后,直到事务执行完才会将锁释放。
特殊情况如果事务中包含DDL操作,mysql会在DDL操作语句执行前,隐式提交commit,以保证该DDL语句操作作为一个单独的事务
存在,同时也保证元数据排他锁的释放。
例如id 44的语句改为
begin;alter table testok add z varchar(10) not Null;select * from testok;
此时一旦alter语句执行完成