数据库事务隔离级别问题

查看 362|回复 30
demoshengxw   
面试官最喜欢问这个问题了,那么我有一个问题:这个事务隔离机制,有人改动过 mysql 默认配置的值吗?
buaasoftdavid   
我以前也不理解可重复读的现实意义是什么,直到我看到一个例子后面就忘不了了 例子如下:假设你在管理一个个人银行账户表。一个表存了账户余额,一个表存了账单明细。到了月底你要做数据校对,也就是判断上个月的余额和当前余额的差额,是否与本月的账单明细一致。你一定希望在校对过程中,即使有用户发生了一笔新的交易,也不影响你的校对结果。
cnsdytedison   
2.第二个方面,MySQL 中,A 事务在执行过程中,要多次使用某条记录,我怕它两次访问查出来结果不一样,反正都是同一条记录,我咋不只查一次,一直就用第一次查出来的。
--------
比如飞机选座,一个 A 用户先查询座位图,花 10 分钟做决定,选了一个位置 X ,提交。在这 10 分钟内,B 用户查询座位图,选 X ,提交。这个时候如果 A 只查一次然后提交(也就是不可重复读),那 A 和 B 会选同一个座位(冲突)。但实际上在可重复读级别下会再读一次,然后 A 事务提交失败的。
waytodelay   
@abccccabc 有,不过原因是从 oracle 迁移到 mysql 有一些本来可以的写法会导致死锁。为了减少改动所以主要是通过改这个来解决也最。
buaasoftdavid   
@demoshengxw 我的理解也是对账之类的才走这个 RR 。其他的业务为了并发还是用 RC
leichnX
OP
  
@haython 大大提高并发当然是相对于可窜行化级别来说的。
watzds   
@demoshengxw 认真读了你的例子,我感觉在这个例子中也没有什么数据需要获取两次呀,中途插入了啥也不会有影响吧。把获取对账需要的数据当作事务 A, 它执行两个操作,1 获取用户两个月的余额快照记录,2 获取用户本月账单明细
select *
from account where userId = 10 and time > 上个月;
select *
from order where userId = 0 and time >= 这个月 1 号;
leonshaw   
隔离就是看不到其他事务的操作,如果两次读取结果不一样,肯定要么其他事务修改了数据,要么是自己改的(这种情况是可见的),这个实际影响是各种各样的,比如
A() {
是否发通知 = B(); //检查余额,判断是否欠费
C(是否发通知); //发送欠费通知邮件,邮件内容中包含余额
}
A 方法整个是一个事务,B C 方法内部都有读数据库操作,如果重复读结果不一样,发送的通知内容中余额可能是 100 非欠费
watzds   
> 那么此时我这个 A 事务还有必要用旧数据往下走吗,走出来的结果能符合预期吗
这种问题要靠锁(乐观锁)解决,更低的隔离级别并不能保证最后一次读之后到提交前不会有其它改动。
me1onsoda   
@watzds #16 当然也可以只读一次,后续复用,但是这样对代码有要求,可能根据不同情况,复用的内容也不一样,那多麻烦,一不小心就出错,那还叫事务吗
另外
A() {
是否发通知 = B(); //检查余额,判断是否欠费
//这时刚好其他事务充值成功
C(是否发通知,余额); //发送欠费通知邮件,邮件内容中包含余额和最近 N 次充值记录
}
就算余额被你复用了,但是充值记录读取到最新的,导致看起来明明刚充值,还是欠费
您需要登录后才可以回帖 登录 | 立即注册

返回顶部