OR博客
MySQL事务隔离级别测试
OrdinaryRoad
创建于:2021-10-04 16:16:41
0
25
144
0
READ UNCOMMITTED, READ COMMITTED, REPEATED READ, SERIALIZABLE
# 一些命令 ## 设置是否自动commit MySQL默认事务都是自动提交的 ```mysql SELECT @@AUTOCOMMIT; SET AUTOCOMMIT = 0; ``` ## 设置当前会话隔离级别 > 旧版本:tx_isolation,新版本:transaction_isolation。 ISOLATION_LEVEL - READ UNCOMMITTED - READ COMMITTED - READ REPEATABLE - SERIALIZABLE ```mysql SHOW GLOBAL VARIABLES like '%isolation'; SELECT @@tx_isolation; SELECT @@transaction_isolation; SET SESSION TRANSACTION ISOLATION LEVEL ${ISOLATION_LEVEL}; ``` # 测试 建表并初始化 ```mysql DROP TABLE IF EXISTS table1; CREATE TABLE table1( id BIGINT(20) PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10) null ); INSERT INTO table1(id,name) VALUES(null,1),(null,2),(null,3),(null,4),(null,5),(null,6),(null,7),(null,8),(null,9),(null,10); SELECT * FROM table1; ``` ## 赃读问题 **脏读:事务A读取到事务B修改后但回滚的数据,破坏了事务的隔离性** ### 准备 会话隔离级别设置为READ UNCOMMITED,取消自动提交,并查看是否修改 ```mysql SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET AUTOCOMMIT = 0; SELECT @@TRANSACTION_ISOLATION, @@AUTOCOMMIT; ``` ### 流程 | 事务A | 事务B | 说明 | | ---------------------------------- | ----------------------------------------------------- | ------------------------------------------------------ | | | BEGIN; | 开始一个事务B | | | UPDATE table1 SET table1.name = '姓名1' WHERE id = 1; | B更新记录 | | SELECT * FROM table1 WHERE id = 1; | | 因为B后续会发生回滚,所以A读取到的是脏数据,发生了赃读 | | | ROLLBACK; | B回滚,需要手动commit | | | COMMIT; | B提交,结束事务 | ## 不可重读问题 **不可重读:事务A先后两次读取同一条记录,在此之间事务B修改并提交了A读取的数据,导致事务A两次数据不一致,破坏了一致性** ### 准备 隔离级别:READ COMMITTED,取消自动提交 ```mysql SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SET @@AUTOCOMMIT = 0; SELECT @@TRANSACTION_ISOLATION, @@AUTOCOMMIT; ``` ### 流程 | 事务A | 事务B | 说明 | | ---------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------ | | | BEGIN; | 开始一个事务B | | SELECT * FROM table1 WHERE id = 1; | | A读取记录,结果为1,1 | | | UPDATE table1 SET table1.name = '姓名1' WHERE id = 1; | B更新记录 | | SELECT * FROM table1 WHERE id = 1; | | A重复读取记录,结果变为1,姓名1,在一个事务中,重复读取同一条数据结果却不一样,发生了不可重读 | | | COMMIT; | B提交,结束事务 | ## 幻读 **幻读:事务A先后两次读取数据集合,在此之间事务B插入或删除了记录,导致事务A两次读取的集合发生变化,无法进行插入等操作,破坏了一致性** ### 准备 删除ID7 8 9的记录 ```mysql DELETE FROM table1 WHERE id BETWEEN 7 AND 9; ``` 隔离级别:REPEATABLE READ,取消自动提交 ```mysql SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET @@AUTOCOMMIT = 0; SELECT @@TRANSACTION_ISOLATION, @@AUTOCOMMIT; ``` ### 流程 | 事务A | 事务B | 说明 | | ---------------------------------- | ---------------------------------- | ----------------------------------------------------- | | BEGIN; | | 开始一个事务A | | SELECT * FROM table1 WHERE id = 7; | | A查询id为7的数据,发现为空,准备插入一条id为7的数据 | | | BEGIN; | B开始一个事务 | | | SELECT * FROM table1 WHERE id = 7; | B查询id为7的数据,发现为空,也准备插入一条id为7的数据 | | | INSERT INTO table1 VALUES(7,7); | B插入一条id为7的数据 | | | COMMIT; | B提交,结束事务 | | INSERT INTO table1 VALUES(7,7); | | A插入一条id为7的数据,此时却提示主键重复 | | SELECT * FROM table1 WHERE id = 7; | | A颇为吃惊,又查了一下id为7的数据,发现确实为空 | | INSERT INTO table1 VALUES(7,7); | | A又试图插入,还是失败 | | COMMIT; | | A骂骂咧咧地结束了事务,今天出现幻觉了 |
评论
楼主暂时不想被别人评论哦~