mysql四种隔离级别

1 读未提交:read-uncommitted,可能产生脏读,幻读,不可重复读
2 读已提交:read-committed 可能产生幻读,不可重复读
3 可重复读:REPEATABLE-READ,默认的,脏读,不可重复读都不会发生,幻读在innodb引擎下不会发生
4 串行化 脏读,幻读,不可重复读都不会出现
查看数据库默认的隔离级别:select @@tx_isolation
设置为其他的隔离级别:set tx_isolation='read-uncommitted'

innodb是如何解决幻读问题的? 通过加行锁,间隙锁来解决,例如

幻读是指一个事务前后两次范围查询,查出的数据不一致,解决办法是在查询时加for update,如果where条件是主键=某个值,就会加行锁,如果是主键in范围值就会加间隙锁,

这时其他线程更改这个范围的值就会阻塞,这样就能避免发生幻读,但数据库性能会下降,如果隔离级别设为rc就不会有间隙锁,也就产生了幻读问题.
测试读未提交:
select * from isolation_test;

 

更新表数据

update isolation_test set money='11' where id =1
重新开一个会话再次查询:select * from isolation_test,查出了更新后的数据,所以读未提交可以查到别人没提交的数据

 

 如果这时开启事物的人执行了回滚命令:rollback

 

 这时再次查询,数据又回滚回去了

 

 

这样就产生了脏读:读了其他会话未提交的数据
测试读已提交:
set tx_isolation='read-committed'
start TRANSACTION
update isolation_test set money='12' where id =1
select * from isolation_test
commit
会话1更新数据后还没提交时自己可以查出更新后的数据,其他会话开启事务后查询还是旧数据,当会话1提交后其他会话才能查出更新后的数据,不管其他会话的事务提不提交,只要会话一的事务提交了,其他事务都会查到更新的数据(对于其他会话来说一个事务中多次查询的数据不一致,这会导致不可重复读问题),如果其他会话查询前不开启事务,事务1提交后其他会话会查到新数据
测试可重复读:
set tx_isolation='repeatable-read'
start TRANSACTION
update isolation_test set money='14' where id =1
commit
select * from isolation_test
会话1开启事务,更新数据未提交时,其他会话开启事务并查询,查到的数据还是旧的,会话1提交后其他会话查到的数据依然是旧的,其他会话自己提交后查到的数据才是新的
,也就是说其他会话只要开启了事务,在没提交之前查到的数据都是不变的,只有自己提交了事务以后再查询,数据才有可能改变,所以叫可重复读(解决了不可重复读问题,但会产生幻读,就是事务期间自己没改动数据,数据不变,但事务提交后数据变了).如果其他会话查询时不开启事务,在会话1提交后就能查到新数据
测试串行化:
set tx_isolation='serializable'
start TRANSACTION
select * from isolation_test
会话1开启事物后其他会话也开启事务并进行更新操作,这时其他事务会卡住,只/有等到会话一提交后其他事务的更新操作才生效,并发性最差

 

 串行化下所有的select语句后都自动加上lock in share mode,即使用了共享锁

posted @ 2021-06-08 16:39  杨吃羊  阅读(139)  评论(0)    收藏  举报