MySQL面试复习笔记(二)

1、表级锁

mysql中存在两种表级锁,一种是表锁,另一种是MDL锁(元数据锁)。

表锁可以自己主动去申请,比如lock tables t1 read, t2 write;这样就申请了一个表t1的读锁,一个表t2的写锁,释放锁可以通过语句unlock tables来实现。表锁除了限制其他线程的操作之外,还会影响到自己接下来的操作,以lock table t1 read, t2 write;为例,这里除了其他线程不能对表t1进行写,对表t2进行读写之外,还限制了本线程只能对表t1进行读,只能对表t2进行读写,本线程也不能写表t1。

MDL锁是系统自动获取与释放的锁,一般对表中的数据进行读写的时候(dml操作)就会自动加上MDL读锁,这个时候其他线程就不能对表进行DDL的操作了,比如往表中新增字段、在表中修改索引等等。

注意MDL锁会导致阻塞,比如sessionA对表t1进行数据查询的时候,sessionB想对表t1进行字段的删除,这个时候sessionB需要等到sessionA释放MDL锁,也就是sessionA的事务提交,如果这个时候sessionC想读表t1,这个时候就sessionC也会发生阻塞,知道sessionB拿到了MDL写锁,并且完全释放之后,sessionC才能进行。

所以对表进行DDL操作的时候,需要留意当前是否有长事务正在进行,不然就会阻塞后面的所有请求,如果并没有长事务在进行,但是表的数据访问比较频繁,最好对DDL操作设置一个等待时间。

2、行锁

行锁是跟引擎走的,是innodb引擎特有的一种特性,myisam是没有的。

行锁顾名思义就是给单独的一行上锁,遵循两段协议,在使用的时候加锁,在事务结束的时候才释放锁。和表锁不一样,行锁除了会导致阻塞之外,还有可能导致死锁。

比如sessionA 在时刻1 更新表t1中id为1的记录,这时同时有sessionB在时刻1更新表t1中id为2的记录,两个事务都未提交,此时在时刻2的时候,sessionA更新id为2的记录,由于sessionB还未提交,sessionA会被阻塞,此时sessionB更新id为1的记录,由于sessionA还未提交,导致sessionB也出现了阻塞,这时便出现了死锁。

解决办法:

1、添加超时机制;

2、减少并发度;

3、将逻辑上的一行改为多行;

4、死锁检测(默认开启,如果事务较多,会比较耗性能,因为每一个事务都需要检测)

#笔记##mysql#
全部评论

相关推荐

点赞 8 评论
分享
牛客网
牛客企业服务