MySQL数据库锁

MySQL数据库锁主要有:

1、共享锁也叫读锁(select…in share mode)

使用共享锁的事务会锁柱被筛选出来的数据行,别的事务只能读取这些数据,但不能修改,如果修改会被阻塞住。

2、排他锁也叫写锁(select…for update)

使用共享锁的事务会锁柱被筛选出来的数据行,别的事务即不能读取这些数据,也不能修改这些数据,如果读取或修改会被阻塞住。

3、记录锁

锁住索引查询筛查选出来的数据行,当按索引条件执行修改操作时会自动应用记录锁,比如:

UPDATE table_name SET column_name = new_value WHERE index_column = some_value;

4、间隙锁

锁住数据行之间的间隙,比如 select * from table where id between 3 and 7 for update。假如表中只有id为4和6的数据,id为5的数据间隙也会被锁住,不允许插入或删除id为5 数据。间隙锁被设计用在可重复读隔离级别下避免幻读。使用写锁select…for update。数据库就会自动应用间隙锁。

5、表锁

锁住整张表,上锁:lock tables table_name write;解锁:unlock tables;

6、页级锁

控制对数据库页的并发访问,由数据库系统自动管理。

7、意向锁

分为意象共享锁,意象排他锁
表明事物的意图,比如事务要给某些数据行放置一个排他锁,数据库系统会自动的首先给这些数据行所在表加一个意象排他锁。不需要人为介入,数据库系统会自动应用。

真正常用的(相对来说),也就是排他锁 select…for update

读已提交隔离级别下使用排他锁,筛选条件用主键可以防止幻读,主键间隙也会被锁定。可以解决不可重复读和幻读。
可重复读隔离级别下使用排他锁,可以解决幻读。

能不用锁还是不要用锁,毕竟MySQL的优势就是支持高并发量

不同隔离级别下的锁

读未提交

事务的读写都不加锁,但基本上也很少用这种隔离级别,毕竟有脏读,除非是只读不写的业务场景

串行化

事物之间加排他锁,这种场景也不常用,毕竟没有事务的并发,性能太低

读已提交

事务中读的时候不加锁,并发性能火力全开。
写的时候加锁,写完立马解锁。这里写完实际指的是事务提交。没有手动开启事务,每个修改数据的sql都是自动开启事务,自动提交事务。如果使用@Transactionnal这样的注释,就等到注释的方法结束自动提交事务。

可重复读

事务中读操作也会对目标数据加读锁,允许其他事务读取,但不能修改要等待锁释放。
写操作跟读已提交一样,等到事务提交释放锁。

这里需要注意锁的范围,不管是查询还是更新,如果查询条件没有加索引就会全表扫描,全表都会被锁住。

读已提交并发情况

读已提交隔离级别下,只要某个事务先执行到更新操作,就会锁住要更新的数据,直到事务提交,其他要更新目标数据的事务都得等待,此时所有事务读取的目标数据都是一致的,如果目标数据的目标字段不冲突,各个抢到锁的事务一次提交事务即可,没有更新冲突的情况,如果两个或两个以上的事务要更新的目标字段冲突,也会按抢到锁的顺序一次更新,目标字段的更新结果就是最后一个事务的更新结果。由于所有并发的事务都是基于同一个原目标数据做计算,所以即使是只有最后一个事务的更新也被保留下来,也是数据一致的,因为原数据已经是最新的数据。
此模式有个问题:就是幻读,更新目标数据期间由于没有加间隙锁,可能会有符合更新条件的数据插入进来,也可能会有符合更新条件的数据被删除。如果是有符合更新条件的数据被删除,大不了更新失败。有符合更新条件的数据插入进来,就会导致少更新数据。实际业务场景中,这种情况很少出现。,大不了再更新一次。如果确实有这种业务场景而且很频繁,可以考虑整个定时任务,定期更新。

隔离级别选择

读已提交隔离级别下并发性高于可重复读,而且读已提交隔离级别下,如果要更新的数据被另一个事务锁住,MySQL会再确认一下,要更新的数据是否真的需要被锁,如果发现要更新的数据实际不需要被锁(需要更新的数据被锁住可能是查询条件没有加索引导致扫描全表,锁全表),此条数据就会解锁不影响本次更新。这个特性有人叫半一致读,我也是参考了这篇文章https://zhuanlan.zhihu.com/p/150248692,然后做实验确实如此。
所以综合考量,虽然MySQL默认隔离级别是可重复读,但实际应用中用读已提交更能利用它的并发性能。
MySQL读已提交隔离级别下只要合理使用事务就能保证数据的一致性,不需要手动加锁,更新操作会自动那个加上排他锁

MySQL之所以把默认隔离级别设为可重复读,看别人说是历史原因:5.0版本之前主从复制的bin log格式只有statement,即sql原始执行语句,从机执行这些同步数据的sql语句时,不能保证跟主机一样的事务顺序,导致同步的数据跟主机不一致,可参看这个https://www.cnblogs.com/yizhiamumu/p/16726845.html。所以用了可重复读,这种模式下保证事务同步进行,但串行提交,保证同步结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值