当前位置:网站首页>行锁与隔离级别案例分析
行锁与隔离级别案例分析
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)尽可能低级别事务隔离
边栏推荐
- Detailed contract quantification system development scheme and technical description of quantitative contract system development
- mysql Add column 失败 因为之前有数据,不是默认null 不行
- How to add an application to the deviceidle whitelist?
- Leetcode daily [2022 - 02 - 16]
- 腾讯钱智明:信息流业务中的预训练方法探索与应用实践
- 在国金证券开户怎么样?开户安全吗?
- 14 MySQL tutorial insert insert data
- wechat_ Solve the problem of page Jump and parameter transfer by navigator in wechat applet
- 小程序设置按钮分享功能
- 数据加密标准DES安全性
猜你喜欢

MySQL add column failed because there was data before, not null by default

Here comes the hero League full skin Downloader

Introduction to distributed cache / cache cluster

决策树与随机森林

并发之线程安全

MySQL exports all table indexes in the database

Army chat -- registration of Registration Center

pycharm的plt.show()如何保持不关闭

【uniapp】uniapp手机端使用uni.navigateBack失效问题解决

next(iter(dataloader))的一点点体会
随机推荐
DoS及攻擊方法詳解
正则匹配相同字符
离婚协议中的几个重点
[recommendation system learning] technology stack of recommendation system
如何将应用加入到deviceidle 白名单?
Please advise tonghuashun which securities firm to choose for opening an account? Is it safe to open an account online now?
Tencent qianzhiming: Exploration and application of pre training methods in information flow business
How sparksql returns a specific day of the week by date -dayofweek function
[ten thousand words summary] starting from the end, analyze in detail how to fill in the college entrance examination volunteers
MySQL add column failed because there was data before, not null by default
关于FlowUs这一款国民好笔记
Concept and working principle of data encryption standard (DES)
陈强:阿里千亿级大规模数字商业知识图谱助力业务增长
玩轉Linux,輕松安裝配置MySQL
KDD 2022 | 如何在跨域推荐中使用对比学习?
Leetcode daily [2022 - 02 - 16]
How to add an application to the deviceidle whitelist?
Introduction to distributed cache / cache cluster
wechat_ Solve the problem of page Jump and parameter transfer by navigator in wechat applet
How about opening an account at Guojin securities? Is it safe?