侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

RR与RC隔离级别下索引和锁的测试脚本示例代码

技术  /  管理员 发布于 7年前   198

基本概念

当前读与快照读

在MVCC中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。 快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且对返回的记录,都会加上锁,保证在事务结束前,这条数据都是最新版本。

快照读:简单的select操作,属于快照读,不加锁(Serializable除外)。

select * from table where ?;

当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。 

select * from table where ? lock in share mode;select * from table where ? for update;insert into table values ();update table set ? where ?;delete from table where ?;

隔离级别与加锁机制

  • Read Uncommitted 会发生脏读,不考虑。
  • Read Committed (RC) 针对当前读,RC隔离级别保证对读取到的记录加锁 (Gap Locking),存在幻读现象。
  • Repeatable Read (RR) 针对当前读,RR隔离级别保证对读取到的记录加锁 (Record Locking),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (Gap Locking),不存在幻读现象。
  • Serializable 所有的读操作均为退化为当前读,读写冲突,因此并发度急剧下降,不考虑。

测试脚本

-- 基本操作 ---- 查询事务隔离级别,默认是RRshow variables like '%isolation%';-- 设置事务隔离级别为RCset session transaction isolation level read committed;-- 数据初始化 --begin;drop table if exists user;CREATE TABLE `user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `email` varchar(64) NOT NULL, `age` int(11) NOT NULL, `address` varchar(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uniq_email` (`email`), KEY `idx_age` (`age`));insert into user (email, age, address) values ("[email protected]", 18, "address1");insert into user (email, age, address) values ("[email protected]", 20, "address2");insert into user (email, age, address) values ("[email protected]", 20, "address3");commit;select * from user;-- 一、trx_id示例begin;SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();select * from user;SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();SHOW ENGINE INNODB STATUS;update user set age = 22 where id = 3;-- 查询事务idSELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();-- INNODB 引擎状态SHOW ENGINE INNODB STATUS;commit;-- 二、可重复读、不可重复读示例-- session1set session transaction isolation level read committed;begin;-- session2set session transaction isolation level repeatable read;begin;-- session1select * from user;-- session2select * from user;-- session3begin;insert into user (email, age, address) values ("[email protected]", 30, "address4");commit;-- session1 这里因为是RC,所以可以读到trx3提交的新数据,这里如果是证明不可重复读的话应该使用update而不是insertselect * from user;commit;-- session2 这里因为是RR,所以不会读到trx3提交的新数据select * from user;commit;-- 三、快照读幻读示例-- session1set session transaction isolation level repeatable read;begin;-- 这里使用快照读select * from user;-- session2begin;insert into user (email, age, address) values ("[email protected]", 30, "address4");commit;select * from user;-- session1select * from user; -- 这里读不到test4@的数据,因为是RR-- 这里发生了幻读insert into user (email, age, address) values ("[email protected]", 30, "address4"); -- 插入失败因为email唯一索引冲突commit;-- 四、当前读幻读示例-- RC-- session1set session transaction isolation level read committed;begin;-- 这里会对所有满足条件的age=20的记录加锁,因为是RC,所以没有GAP锁delete from user where age = 20;select * from user;-- session2set session transaction isolation level read committed;begin;-- 因为trx1没有加GAP锁,所以之类可以插入age=20的记录insert into user (email, age, address) values ("[email protected]", 20, "address4");select * from user; -- 可以查到4条数据,可以读到trx1的删除数据,因为是RC,trx1未提交所以没影响trx2commit;-- session1select * from user; -- 可以读到trx2新插入的数据,虽然trx1是当前读,但是并未添加相应的next-key锁,没有阻止trx2的新数据插入commit;--RR-- session1set session transaction isolation level repeatable read;begin;delete from user where age = 20;select * from user;-- session2begin;-- 这里会阻塞,因为trx1在age=20周围加了GAP锁-- 非唯一索引,首先,通过索引定位到第一条满足查询条件的记录,加记录上的X锁,加GAP上的GAP锁,然后加主键聚簇索引上的记录X锁;-- 然后读取下一条,重复进行。直至进行到第一条不满足条件的记录,此时,不需要加记录X锁,但是仍旧需要加GAP锁,最后返回结束。insert into user (email, age, address) values ("[email protected]", 20, "address4");-- 直到超时,ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction-- 此时如果查询可以看到3条记录commit;-- session1-- 此时只能看到1条记录,另外两条被删除了select * from user;commit;-- 唯一索引+RC-- session1set session transaction isolation level read committed;begin;delete from user where email = "[email protected]";-- session2begin;-- 可以读到,因为trx1是RCselect * from user where email = "[email protected]";-- 尝试更新这个记录的age,会阻塞直到超时,因为email是唯一索引已经被trx1锁住了,同时也会在对应的主键索引上加锁-- 注意这里操作的id=3就是trx1中操作的email的同一行记录update user set age = 40 where id = 3;-- session1commit;-- session2commit;-- 无索引+RC-- session1set session transaction isolation level read committed;begin;-- 由于address字段无索引,所以Innodb会对所有行进行加锁,由MySQL server进行判断并释放锁delete from user where address = "address3";-- session2set session transaction isolation level read committed;begin;-- 这一行会成功,因为这一行没有加锁(先加了后释放了)update user set age = 10 where address = "address2";-- 这一行同样会被阻塞,原因是它已经被trx1的语句加了锁了,全部符合条件的都加锁了update user set age = 10 where address = "address3";-- session1commit;-- session2commit;-- 非唯一索引+RR-- session1set session transaction isolation level repeatable read;begin;delete from user where age = 20;-- session2set session transaction isolation level repeatable read;begin;-- 这里会阻塞,因为trx1中已经锁住了age=20的记录以及加上了GAP锁,所以这里18已经落入锁区间insert into user (email, age, address) values ("[email protected]", 18, "address4");-- session1commit;-- session2commit;-- 无索引RR-- session1set session transaction isolation level repeatable read;begin;-- 没有索引,那么会锁上表中的所有记录,同时会锁上主键索引上的所有GAP,杜绝所有的并发更新操作delete from user where address = "address3";-- session2set session transaction isolation level repeatable read;begin;-- 这里会阻塞,原因是主键已经被加上了GAP锁,所以新的插入不能执行成功insert into user (email, age, address) values ("[email protected]", 18, "address4");-- session1commit;-- session2commit;-- 死锁 简单示例-- session1begin;delete from user where id = 1;-- session2begin;delete from user where id = 3;-- session1delete from user where id = 3;-- seession2-- 这里MySQL判断发生了死锁,中断了一个trx-- ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transactiondelete from user where id = 1;-- session1rollback;-- session2;rollback;-- 五、死锁 insert示例drop table if exists t1;begin;create table t1 ( `id` bigint not null auto_increment, primary key (`id`));insert into t1 values(1);insert into t1 values(5);commit;select * from t1;-- session1begin;insert into t1 values (2);-- sessioin2begin;-- 这里会阻塞insert into t1 values (2);-- session3begin;-- 这里会阻塞insert into t1 values (2);-- session1;-- 此时回滚,trx2和trx3收到通知,MySQL自动中断一个trx,因为发生了死锁-- ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transactionrollback;--session2;rollback;--session3;rollback;

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


  • 上一条:
    你的like语句为什么没索引详解
    下一条:
    解决Can't locate ExtUtils/MakeMaker.pm in @INC报错
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 国外服务器实现api.openai.com反代nginx配置(0个评论)
    • 2024/4/28最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客