数据库隔离级别,第二类更新丢失

隔离级别:

读未提交:

一个事务中可以读到别的事务任何数据,包括已提交 和 未提交的脏数据

读已提交:

一个事务中只能读到其他事物已经提交的数据

可重复读:

一个事务在本事务提交之前读到的数据不会受其它事务crud的影响,所以前后读的数据是一致的,可以重复读

注意:实际上这个可重复读只是针对读(select)所看到的的数据是可以重复读的,仅此而已;

为什么这么说呢?

1 当你事务还没提交,这时外界插入了一条id=10的数据,你select查看,发现没有这条数据,你也想插入id=10的数据,是会报错的,因为有冲突,这就是出现了幻读,数据库感知的是实际的环境,而你事务还没提交之前,你select看到的数据是虚幻的,这就是这个隔离级别的一大特点。

2 当你update 表 set money = money+100,进行这种操作时,这个money是会取到真实的money的。举例:你先select 发现money是100,然后另外一个人开启事务并提交把100更新成200,这时候你再select发现还是100,然后你update 表 set money = money+100,这时候实际上会被修改为300而不是200,但是如果你是update 表 set money = 200,就真的变成200,这还是会发生第二类更新丢失。

所以说为什么说!!可重复读可以解决第二类更新丢失啊??????
明明就不可以!!!!
而且,可重复读到底有什么好处啊,没觉得它比读已提交好在哪啊!!!!

串行化:

某一个事务select的时候会对对应行加上共享锁,这时其他事务直接无法更新改数据
这时最高的隔离级别,不会出现任何问题。

通过对select操作加上共享锁解决第二类更新问题和幻读问题。


问题:

脏读:

某一个事务读到别的事务还没提交的数据,换种说法:即将读到被回滚的虚假数据

不可重复读:

一个事务没提交之前,读写某一行的数据前后不一致
(这个不一致就不一致咯有什么问题吗)

幻读:

近似脏读,就是读取了到了错误的数据,举例:别的事务新增了一条数据,但是我这边没看到,当我我也想新增一条同样的数据时系统报错说已经存在这条数据了。

第一类更新:

事务A事务B
开启事务开启事务
查询到余额为1000查询到余额为1000
-添加100,修改为1100
-提交事务
添加100,修改为1100
回滚事务
余额变成1000 事务B更新丢失

现在所有的隔离级别都不会出现这种错误,可以忽略。

第二类更新:

事务A事务B
开启事务开启事务
查询到余额为1000查询到余额为1000
-添加100,修改为1100
-提交事务
添加100,修改为1100
提交事务
余额变成1100 事务B更新丢失

这也是多线程下经典的并发问题。

解决方案:

通常可通过乐观锁或悲观锁解决。

悲观锁:

前置知识:
数据库悲观锁有共享锁和排他锁两种。
对于任何隔离级别,update,insert,delete会自动添加排它锁。
非串行化隔离级别下,select是不会添加任何锁的,串行化下,select自动添加共享锁。
一行数据被加了共享锁,其它事务也可以一起加共享锁来访问这个数据。但是不能加排它锁来修改它。
一行数据被加了排它锁,其它事务都不能对他加任何锁。

在事务中,对于每个select操作都主动显式地加上共享锁或者排他锁(最好是共享锁),update,delete,insert已经自动加上排他锁了

共享锁获取方式:select * from account where name=‘jack’ lock in share mode;

排它锁获取方式:select * from account where name=‘jack’ for update;

(注意!!单纯的select是不会添加任何锁的,也就是说select在非串行化的隔离级别之下是不受任何控制的)

或者直接把事务隔离设为串行化set tx_isolation=‘SERIALIZABLE’; 这个隔离级别其实恰好就是上诉的加共享锁的方法(已经过测试)
所以说在串行化的隔离级别下是不会出现第二类更新丢失问题的

乐观锁(推荐):
版本号机制,增加一个版本或者时间戳的列,对于进行修改行时先获取版本号,修改的时候比较一下版本号是否一致,一致再进行修改并将版本号加一更新。

附:
在这里插入图片描述
(上图可重复读解决第二类更新那里值得商榷)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值