数据隔离Isolation
在数据库系统处理并发读写的情况下,不可避免的要引入事务的概念,相应的,事务之间的隔离级别也就决定了事务所表现出来的效果。
一 读未提交
最低级别的隔离,如果存在两个事务A,B,A可以读取到B事务尚未提交的数据,这种隔离级别导致的最大问题就是脏读,典型场景例如转账,A转给B 100,A的事务还没有提交成功的时候,B就已经能查询到账户的增加100,如果此时A的事务处理失败,而B之前的读取可能已经将这100消费出去。
二 读已提交:(不可重复读)
只能读取其他事务已经提交过的内容,避免了上述脏读的问题,只有在A的事物提交已经完成后,B才能读取到账户增加100的操作,如果中途回滚,B完全不受影响。在这种隔离级别下,带来的一个问题就是不可重复读,例如,B事务中有两次读取相同数据,A事务发生在这两次读取之间,若A事务成功执行,则B事务中两次读取数据是不一致的,不可重复读的意思就是在一个事务中重复读取可能得到不一样的结果,这个问题对于一般用户来说没什么问题,只需要重新刷新就可以了,但是对于某些数据备份的场景,有可能读取到部分事务发生前和发生后的混合数据。
三 快照隔离:(可重复读)
这种隔离级别通过使用 MVCC 多版本并发控制来解决不可重复读的问题 做到本事务内重复读结果是一致的也就是可重复读,通过在事务处理时给数据添加递增的事务编号,控制低版本的事务不会读取到高版本事务的内容,这样在同一个事务中解决上述不可重复读的问题,在数据库同步事务中保证所有数据都是处于固定版本而不是关联的数据不在同一事务版本中。
即使我们已经这么做了,我们还是不能保证事务是完全安全的,比如“幻读”这个场景,例如当前有两个医生值班,医院系统要求最少有一个医生值班,这时两名医生都要离岗,发起离岗请求:先统计当前在岗人数,大于1时进行离岗操作,这种场景下,在各自的事务中,都查询到在岗人数是2,此时都进行离岗,这就违反了系统要求。
四 串行:(最高级别隔离)
在上述描述中,似乎只有保证各个事物是串行执行的,才能满足要求
可以通过Select for Update,通过数据库的行级排他锁来控制,保证发生在某行数据上的操作是串行执行的。
或者CAS(Compare And Sweap)来控制写入。