当前位置:网站首页>行锁与隔离级别案例分析
行锁与隔离级别案例分析
2022-06-26 17:54:00 【 时光清浅ぴ许你安然】
更多内容,可前往深入理解MySQL锁与事务隔离级别查看
现有如下表:
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
一个session开启事务更新不提交,另一个session更新同一条记录会阻塞,更 新不同记录时不会阻塞。
1 读未提交
(1)打开一个客户端A,设置当前事务模式为read uncommitted(读未提交)并开启事务,查询初始化数据
①设置隔离级别并开启事务
set tx_isolation='read-uncommitted';

②查询表的初始数据
select * from account;

(2)在客户端A的事务提交之前,打开另一个客户端B,设置当前事务模式为read uncommitted(未提交读)并开始事务,更新表account:
①更新隔离级别为读未提交
set tx_isolation='read-uncommitted';

②查询初始化数据
③、更新数据
(3)这时,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据:
(4)一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那 客户端A查询到的数据其实就是脏数据:
(5)在客户端A执行更新语句update account set balance = balance - 50 where id =1,lilei的balance没有变成350,居然是400,是不是很奇怪,数据不 一致啊,如果你这么想就太天真 了,在应用程序中,我们会用400-50=350,并 不知道其他会话回滚了,要想解决这个问题可以采用读已提交的隔离级别
2 读已提交
(1)打开一个客户端A,设置当前事务模式为read committed(读已提交)并开启事务,查询初始化数据
①设置隔离级别并开启事务
set tx_isolation='read-committed';

②查询表的初始数据
select * from account;

(2)在客户端A的事务提交之前,打开另一个客户端B,设置当前事务模式为read committed(读已提交)并开始事务,更新表account:
①更新隔离级别为读已提交
set tx_isolation='read-committed';

②查询初始化数据
③、更新数据
(3)这时,客户端B的事务还没提交,客户端A不能查询到B已经更新的数 据,解决了脏读问题:
(4)客户端B的事务提交
(5)客户端A执行与上一步相同的查询,结果 与上一步不一致,即产生了不可重复读的问题(同一事务中执行同一SQL返回不同的结果)
3 可重复读
(1)打开一个客户端A,设置当前事务模式为repeatable read(可重复读)并开启事务,查询初始化数据
①设置隔离级别并开启事务
set tx_isolation='repeatable-read';

②查询表的初始数据
select * from account;

(2)在客户端A的事务提交之前,打开另一个客户端B,设置当前事务模式为repeatable read(可重复读)并开始事务,更新表account:
①更新隔离级别为可重复读
set tx_isolation='repeatable-read';

②查询初始化数据
③、更新数据
(3)这时,提交客户端B的事务,查看客户端A的数据

(4)在客户端A,接着执行update account set balance = balance - 50 where id = 1,balance没有变成400-50=350。
lilei的balance值用的是sessionB中的350来算的,所以是300,数据的一致性倒是没有被破坏。可重复读的隔离级别下使用了MVCC(multi-version concurrency control)机(多版本并发控制机制)。
select操作不会更新版本号,是快照读(历史版本);
insert、update和delete会更新版本号,是当前读(当前版本)。
(5)客户端A执行与上一步相同的查询,结果 与上一步不一致,即产生了不可重复读的问题(同一事务中执行同一SQL返回不同的结果)
关于MVCC机制,具体看前往MySQL的MVCC机制详解进行查看
4 幻读
(1)打开一个客户端A,开启事务,查询初始化数据
(2)手动在数据库中插入一条记录,然后再去客户端A查询数据

发现查询出的数据还是第一次查询的三条数据。
(3)更新上一步手动插入的数据
发现更新成功了。
(4)再次查询数据
发现数据确实已被更新,且也可以查询出来了。
这种情况就是幻读,很魔幻的感觉,更新了,就多了一条数据了。
幻读的情况,可设置事务隔离级别为串行化可解决(但是效率低下,几乎不会使用,这里不进行介绍)。
问:Mysql默认级别是repeatable-read,有办法解决幻读问题吗?
答:间隙锁在某些情况下可以解决幻读问题
比如:现在有如下数据
可以看到,id中4和10之间有个间隙、10和20之间是有间隙的(之间还可以插入一些11、12…等数据,还有一些空白的id没有被使用到)
开启事务
查询数据
更新数据
只要事务不提交,那么id 4~10、10 ~ 20之间的间隙就会被加锁。
我们可以手动在数据库里插入数据来验证
直到我们回滚或者提交事务会后,上述阻塞的地方就会正常
以此看来,间隙锁是可以帮助我们处理幻读的问题。
一旦开启间隙锁,则加锁的部分不再允许插入(未加锁的部分依然可以正常插入),那么session中查询的数据永远都是之前的记录
无索引行锁会升级为表锁:锁主要是加在索引上,如果对非索引字 段更新, 行锁可能会变表锁
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁。
锁定某一行还可以用lock in share mode(共享锁) 和for update(排它锁),
例如:select * from test_innodb_lock where a = 2 for update;
这样其他session只能读这行数据,修改则会被阻塞,直到锁定行的session 提交
5 结论
Innodb存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的 性能损耗可能比表级锁定会要更高一下,但是在整体并发处理能力方面要远远优 于MYISAM的表级锁定的。当系统并发量高的时候,Innodb的整体性能和 MYISAM相比就会有比较明显的优势了。
Innodb但是,Innodb的行级锁定同样也有其脆弱的一面,当我们使用不当的时候, 可能会让Innodb的整体性能表现不仅不能比MYISAM高,甚至可能会更差。
6 优化建议
(1)尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
(2)合理设计索引,尽量缩小锁的范围 尽可能减少检索条件范围,避免间隙锁
(3) 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql 尽量放在事务最后执行
(4)尽可能低级别事务隔离
边栏推荐
- #25class的类继承
- 在国金证券开户怎么样?开户安全吗?
- Strength and appearance Coexist -- an exclusive interview with Liu Yu, a member of Apache pulsar PMC
- Chen Qiang: Alibaba's 100 billion level large-scale digital business knowledge map helps business growth
- JNI的 静态注册与动态注册
- ACL 2022 | zero sample multilingual extracted text summarization based on neural label search
- Live broadcast preview | how can programmers improve R & D efficiency? On the evening of June 21, the video number and station B will broadcast live at the same time. See you or leave!
- 非对称密码体制详解
- 股票开账户如何优惠开户?现在在线开户安全么?
- 手写promise.all
猜你喜欢

二分查找法-1

丰富专业化产品线, 江铃福特领睿·极境版上市

【万字总结】以终为始,详细分析高考志愿该怎么填

padding百分比操作

transforms.RandomCrop()的输入只能是PIL image 不能是tensor

Number of solutions for knapsack problem

Introduction to distributed cache / cache cluster

RSA加密解密详解

Army chat -- registration of Registration Center

Discussion and generation of digital signature and analysis of its advantages
随机推荐
JS 常用正则表达式
Tencent qianzhiming: Exploration and application of pre training methods in information flow business
离婚协议中的几个重点
RSA encryption and decryption details
Detailed explanation of dos and attack methods
并发之线程安全
Problems encountered this week
Introduction to distributed cache / cache cluster
Data Encryption Standard DES security
同花顺开户怎么样安全吗?怎么炒股开户
决策树与随机森林
在国金证券开户怎么样?开户安全吗?
Preparing for the Blue Bridge Cup and ccf-csp
数字签名标准(DSS)
The difference between round and truncate in SQL (round or truncate)
Bayesian network explanation
无需人工先验!港大&同济&LunarAI&旷视提出基于语义分组的自监督视觉表征学习,显著提升目标检测、实例分割和语义分割任务!
Troubleshooting ideas that can solve 80% of faults!
二分查找-2
分布式架构概述