oracle
支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。
默认系统事务隔离级别是READ COMMITTED,也就是读已提交
mysql
查看当前的事务隔离级别:
SELECT @@global.tx_isolation;
修改当前事务隔离级别:
set global transaction isolation level REPEATABLE READ;
读未提交(READ UNCOMMITTED)----脏读 不可重复读 幻读:
客户端A,设置事务模式----read uncommitted----查询表account初始值
此时客户端B,更新表,虽然B事务还没有提交,A客户端就可以查询到B更新的数据
一旦B事务因为某原因回滚,所有操作就会被撤销,A读取到的数据就是脏数据
读已提交(READ COMMITTED)----不可重复读 幻读:
客户端A,设置事务模式----read committed----查询表account初始值
此时客户端B,更新表,
B的事务还没有提交,A就不能查询到B已经更新的数据,解决了脏读问题
随后B的事务提交,结果A执行与第一次相同的查询,与第一次的结果不一致,产生“不可重复读”问题
可重复读(REPEATABLE READ)----幻读:
在终端A开启事务A,查询一下
在终端B开启事务B,进行同样的查询,结果和事务A中的结果是一样的
在事务A中,更新一下,将id=3的字段更新为3,然后提交事务A;
在事务B中进行查询,发现查询到的还是事务A更新之前的数据
可重复读隔离级别下使用mvcc机制,select操作不会更新版本号,是快照读,insert,update,delete会更新版本号
串行化(SERIALIZABLE):
打开一个客户端A,并设置当前事务模式为serializable,查询表account的初始值
打开一个客户端B,并设置当前事务模式为serializable,插入一条记录报错,表被锁了插入失败,mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。
脏读:
t1时刻:开启事务1并且新插入一条数据,但是并没有提交
t2时刻:事务2读取到的未提交的数据
幻读(同理update,insert):
t1时刻:事务1,事务2,查询同一条语句,得到同样的结果
t2时刻:事务2删除一条id=1的数据,并提交
t3时刻:事务1查询得到与t1时刻一样的结果,包括已经被删除的id=1的数据
不可重复读(同一个事务前后查询结果不一样):
t1时刻:事务1,事务2,查询同一条语句,得到同样的结果
t2时刻:事务1删除一条id=1的数据,并提交
t3时刻:事务2再次查询,结果发现没有id=1的数据