腾讯面试:MySQL事务与MVCC如何实现的隔离级别?( 二 )

  1. 原子性(atomicity): 事务的最小工作单元 , 要么全成功 , 要么全失败 。
  2. 一致性(consistency): 事务开始和结束后 , 数据库的完整性不会被破坏 。
  3. 隔离性(isolation): 不同事务之间互不影响 , 四种隔离级别为RU(读未提交)、RC(读已提交)、RR(可重复读)、SERIALIZABLE (串行化) 。
  4. 持久性(durability): 事务提交后 , 对数据的修改是永久性的 , 即使系统故障也不会丢失 。
事务的隔离级别读未提交(Read UnCommitted/RU)又称为脏读 , 一个事务可以读取到另一个事务未提交的数据 。 这种隔离级别岁最不安全的一种 , 因为未提交的事务是存在回滚的情况 。
读已提交(Read Committed/RC)又称为不可重复读 , 一个事务因为读取到另一个事务已提交的修改数据 , 导致在当前事务的不同时间读取同一条数据获取的结果不一致 。
举个例子 , 在下面的例子中就会发现SessionA在一个事务期间两次查询的数据不一样 。 原因就是在于当前隔离级别为 RC , SessionA的事务可以读取到SessionB提交的最新数据 。
发生时间 SessionA SessionB 1 begin; 2 select * from user where id=1;(张三) 3 update user set name='李四' where id=1;(默认隐式提交事务) 4 select * from user where id=1;(李四) 5 update user set name='王二' where id=1;(默认隐式提交事务) 6 select * from user where id=1;(王二)
可重复读(Repeatable Read/RR)又称为幻读 , 一个事物读可以读取到其他事务提交的数据 , 但是在RR隔离级别下 , 当前读取此条数据只可读取一次 , 在当前事务中 , 不论读取多少次 , 数据任然是第一次读取的值 , 不会因为在第一次读取之后 , 其他事务再修改提交此数据而产生改变 。 因此也成为幻读 , 因为读出来的数据并不一定就是最新的数据 。
举个例子:在SessionA中第一次读取数据时 , 后续其他事务修改提交数据 , 不会再影响到SessionA读取的数据值 。 此为可重复读 。
发生时间 SessionA SessionB 1 begin; 2 select * from user where id=1;(张三) 3 update user set name='李四' where id=1; (默认隐式提交事务) 4 select * from user where id=1;(张三) 5 update user set name='王二' where id=1;(默认隐式提交事务) 6 select * from user where id=1;(张三)
串行化(Serializable)所有的数据库的读或者写操作都为串行执行 , 当前隔离级别下只支持单个请求同时执行 , 所有的操作都需要队列执行 。 所以种隔离级别下所有的数据是最稳定的 , 但是性能也是最差的 。 数据库的锁实现就是这种隔离级别的更小粒度版本 。
发生时间 SessionA SessionB 1 begin; 2 begin; 3 update user set name='李四' where id=1; 4 select * from user where id=1;(等待、wait) 5 commit; 6 select * from user where id=1;(李四)
事务和MVCC原理不同事务同时操作同一条数据产生的问题示例:
发生时间 SessionA SessionB 1 begin; 2 begin; 3 查询余额 = 1000元 4 查询余额 = 1000元 5 存入金额 100元 , 修改余额为 1100元 6 取出现金100元 , 此时修改余额为900元 8 提交事务(余额=1100) 9 提交事务(余额=900)
发生时间 SessionA SessionB 1 begin; 2 begin; 3 查询余额 = 1000元 4 查询余额 = 1000元 5 存入金额 100元 , 修改余额为 1100元 6 取出现金100元 , 此时修改余额为900元 8 提交事务(余额=1100) 9 撤销事务(余额恢复为1000元)
上面的两种情况就是对于一条数据 , 多个事务同时操作可能会产生的问题 , 会出现某个事务的操作被覆盖而导致数据丢失 。
LBCC 解决数据丢失LBCC , 基于锁的并发控制 , Lock Based Concurrency Control 。
使用锁的机制 , 在当前事务需要对数据修改时 , 将当前事务加上锁 , 同一个时间只允许一条事务修改当前数据 , 其他事务必须等待锁释放之后才可以操作 。