一、数据库 事务的隔离级别有4个:
由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable、MVCC,这五个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
二、
(1)Read uncommitted(读未提交,存在脏读)
例子:错发工资,空欢喜
小明 辛苦搬砖一个月,领导给他账户存4000,此时领导发工资事物未提交,但小明查看工资发现账户多了4000,满心欢喜,不幸的是领导发现工资算错了,回滚事务,修改金额2000,提交事务。最终小明工资只有2000,空欢喜一场。
总结:此例子中,发生了脏读。即A事物修改,未提交,B事物先读到,A事物在修改提交。
(2)Read committed(读已提交,存在不可重复读)
例子:消费资金被打劫
小明拿工资卡去消费,系统读到卡中余额4000,此时他老婆正在把小明工资卡转账,并成功提交转账事物,当小明消费扣款时,发现资金被打劫,一脸蒙 ~。
总结:此例子中,发生了不可重复读。即事物A查询,事物B修改并提交,事物A读发现修改了。
(3)Repeatable read (可重复读,存在幻读)
例子:老婆查账,打印完账单发现变化
小明老婆银行工作,经常查看小明消费记录,有一次查看当月消费记录为80,此时小明在外胡吃海喝消费1000,并提交事物,随后老婆打印账单发现消费变成1080,,非常诧异以为出现幻觉。
总结:事物A查询,事物B修改,事物A继续查询,结果变了。
(4)Serializable(序列化,性能低)
串行化事物,避免脏读、不可重复读、幻读,但是性能花费太高。
(5)MVCC(Multi-Version Concurrency Control 多版本并发控制 )
在Java concurrent包中,有copyonwrite系列的类,专门用于优化读远大于写的情况。而其优化的手段就是,在进行写操作时,将数据copy一份,不会影响原有数据,然后进行修改,修改完成后原子替换掉旧的数据,而读操作只会读取原有数据。通过这种方式实现写操作不会阻塞读操作,从而优化读效率。而写操作之间是要互斥的,并且每次写操作都会有一次copy,所以只适合读大于写的情况。
MVCC的原理与copyonwrite类似,全称是Multi-Version Concurrent Control,即多版本并发控制。在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。