数据库事务的隔离级别

常用数据库的默认隔离级别

MySQL的默认隔离级别是Repeatable
Oracle的默认隔离级别是Read committed

事务的隔离级别

1、读取未提交内容(Read uncommitted)
2、提交读(Read committed)
3、可重复读(Repeatable reads)
4、可序列化(Serializable)

读未提交(Read uncommitted)会导致脏读

1、加锁情况

事务在读数据的时候并未对数据加锁
事务在修改数据的时候只对数据增加行级共享锁

2、举例(第一行,第三行属于同一事务内语句)

A事务执行SELECT age FROM users WHERE id = 1; 查到结果为20
B事务执行UPDATE users SET age = 21 WHERE id = 1; 但并未提交
此时A事务再次执行SELECT age FROM users WHERE id = 1; 查到结果为21

3、总结

一个事务读到另一个事务未提交的数据为脏读

读已提交(Read committed)

1、加锁情况

事务对当前被读取的数据加行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁
事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁,直到事务结束才释放

2、举例

A事务执行SELECT * FROM users WHERE id = 1; 查到结果为20
B事务执行UPDATE users SET age = 21 WHERE id = 1;
A事务执行SELECT * FROM users WHERE id = 1; 查到结果为20
B事务 commit;
A事务执行SELECT * FROM users WHERE id = 1; 查到结果为21
最后一次读取的结果已经变了

3、总结

一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
这种隔离级别保证了读到的任何数据都是提交的数据,避免了脏读(dirty reads)。

可重复读(Repeatable reads)

事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加 行级共享锁,直到事务结束才释放
事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。

2、可重复读举例

A事务执行SELECT * FROM users WHERE id = 1;
B事务执行UPDATE users SET age = 21 WHERE id = 1;,此时处于阻塞状态,无法执行,需等待A事务执行完毕
A事务commit
B事务继续执行

3、幻读举例

A事务执行SELECT * FROM users WHERE age BETWEEN 10 AND 30; 此时查到两条数据
B事务执行INSERT INTO users(age) VALUES (30); commit;
A事务再次执行SELECT * FROM users WHERE age BETWEEN 10 AND 30; 此时查到了三条数据

幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。

也就是说,当前事务读第一次取到的数据比后来读取到数据条目少。

4、总结

A事务执行期间,所做的查询和修改都会加锁,其他事务只能查询不能修改,若要修改,只能等待A事务执行完成
解决了不可重复读,但是解决不了幻读

可序列化(Serializable)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

1、加锁情况

事务在读取数据时,必须先对其加表级共享锁 ,直到事务结束才释放;
事务在更新数据时,必须先对其加表级排他锁 ,直到事务结束才释放。

2、举例

事务1正在读取A表中的记录时,则事务2也能读取A表,但不能对A表做更新、新增、删除,直到事务1结束
事务1正在更新A表中的记录时,则事务2不能读取A表的任意记录,更不可能对A表做更新、新增、删除,直到事务1结束

3、总结

可序列化可以解决幻读,但是同时会带来其他问题。

 

这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

  • 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
  • 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,如果此时插入和另外一个事务插入的数据,就会报错。

preview

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值