数据库的4中隔离级别
Posted 虚空假面
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库的4中隔离级别相关的知识,希望对你有一定的参考价值。
set tx_isolation=\'READ-UNCOMMITTED\'; select @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+
start transaction; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +------+------+
#事务B:也启动一个事务(那么两个事务交叉了) 在事务B中执行更新语句,且不提交
start transaction; update tx set num=10 where id=1; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 10 | | 2 | 2 | | 3 | 3 | +------+------+
#事务A:那么这时候事务A能看到这个更新了的数据吗?
select * from tx; +------+------+ | id | num | +------+------+ | 1 | 10 | --->可以看到!说明我们读到了事务B还没有提交的数据 | 2 | 2 | | 3 | 3 | +------+------+
#事务B:事务B回滚,仍然未提交
rollback; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +------+------+
#事务A:在事务A里面看到的也是B没有提交的数据
select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | --->脏读意味着我在这个事务中(A中),事务B虽然没有提交,但它任何一条数据变化,我都可以看到! | 2 | 2 | | 3 | 3 | +------+------+
第2级别:Read Committed(读取提交内容)
set tx_isolation=\'read-committed\'; select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+
#事务A:启动一个事务
start transaction; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +------+------+
#事务B:也启动一个事务(那么两个事务交叉了)在这事务中更新数据,且未提交
start transaction; update tx set num=10 where id=1; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 10 | | 2 | 2 | | 3 | 3 | +------+------+
#事务A:这个时候我们在事务A中能看到数据的变化吗?
select * from tx; ---------------> +------+------+ | | id | num | | +------+------+ | | 1 | 1 |--->并不能看到! | | 2 | 2 | | | 3 | 3 | | +------+------+ |——>相同的select语句,结果却不一样 |
#事务B:如果提交了事务B呢?
commit;
#事务A:
select * from tx; ---------------> +------+------+ | id | num | +------+------+ | 1 | 10 |--->因为事务B已经提交了,所以在A中我们看到了数据变化 | 2 | 2 | | 3 | 3 | +------+------+
第3级别:Repeatable Read(可重读)
set tx_isolation=\'repeatable-read\'; select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+
#事务A:启动一个事务
start transaction; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +------+------+
#事务B:开启一个新事务(那么这两个事务交叉了) 在事务B中更新数据,并提交
start transaction; update tx set num=10 where id=1; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 10 | | 2 | 2 | | 3 | 3 | +------+------+ commit;
#事务A:这时候即使事务B已经提交了,但A能不能看到数据变化?
select * from tx; +------+------+ | id | num | +------+------+ | 1 | 1 | --->还是看不到的!(这个级别2不一样,也说明级别3解决了不可重复读问题) | 2 | 2 | | 3 | 3 | +------+------+
#事务A:只有当事务A也提交了,它才能够看到数据变化
commit; select * from tx; +------+------+ | id | num | +------+------+ | 1 | 10 | | 2 | 2 | | 3 | 3 | +------+------+
这里只是演示了可重复读,这个级别仍然会产生幻读的情况,幻读跟不可重复度究竟有啥不同?参见文章:
https://blog.csdn.net/cweeyii/article/details/70991230
https://www.cnblogs.com/itcomputer/articles/5133254.html
可重复读,要求只要查询的关联行没改变就行了,针对的是相关行;幻读要求整个表都不能动,针对的包括行周围的数据,可以认为是整个表,基本关联的就是insert这个操作。比如文章1中提到的:事务1查询记录有5条,事务2在事务1提交前插入一条记录;这时虽然事务1读到的数据仍然是5条,但却不能进行insert操作!!因为第6条记录实际已经有了,而事务1却看不见,它会觉得明明5条记录,为什么老子插不进去呢?!
第4级别:Serializable(可串行化)
set tx_isolation=\'serializable\'; select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+
#事务A:开启一个新事务
start transaction;
#事务B:在A没有commit之前,这个交叉事务是不能更改数据的
start transaction; insert tx values(\'4\',\'4\'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction update tx set num=10 where id=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
以上是关于数据库的4中隔离级别的主要内容,如果未能解决你的问题,请参考以下文章