#JAVA破局之路#分布式事务解决方案),分布式事务详解(mysql事务如何实现的

分布式事务也是面试的一个高频知识点 。
1.事务基本概念1.1什么是事务?事务是恢复和并发控制的基本单位 , 事务有四个特性(ACID) , 原子性(Atomicity) , 一致性(Consistency) , 隔离性(Isolation) , 持久性(Durability) 。
1.2事务经典场景假设这样一个场景:
A给B转账100 , 流程步骤如下:
1、A减100
2、B多100 。
如果第一步骤执行后 , 系统崩溃掉了 。 会怎么样呢?
问题:A被减掉了100 , 但B的钱未能加100.此时 , A+B的金钱总额凭空少了100 。 数据不一致了 。
解决思路呢?我们希望步骤1和步骤2能够绑定在一起执行 , 不可分;并且在步骤1和步骤2执行的过程中 , 尽量规避中间状态 。 即谓事务 。 事务在解决上述问题中 , 提出了以下四种特性原子性(Atomicity) , 一致性(Consistency) , 隔离性(Isolation) , 持久性(Durability) 。
1.2.1原子性原子性就是不可拆分的特性 , 要么全部成功然后提交(commit) , 要么全部失败然后回滚(rollback) 。 若开启事务 , 在上述场景就不会出现A少100成功 , B多100失败这种情况 。 利用InnoDB的undologundolog(回滚日志)记录需要回滚的日志信息 , 是实现原子性的关键 , 当事务回滚时能够撤销所有已经成功执行的sql语句
例如:
delete一条数据的时候 , 就会记录这条数据的曾经的信息 , 回滚的时候 , insert这条旧数据
update一条数据的时候 , 就会记录之前的旧值 , 回滚的时候 , 根据旧值执行update操作
insert一条数据的时候 , 就会这条记录的主键 , 回滚的时候 , 根据主键执行delete操作
undolog记录了这些回滚需要的信息 , 当事务执行失败或调用了rollback , 导致事务需要回滚 , 便可以利用undolog中的信息将数据回滚到修改之前的样子 。
1.2.2一致性数据库通过原子性(A)、隔离性(I)、持久性(D)来保证一致性(C) 。 其中一致性是目的 , 原子性、隔离性、持久性是手段 。 因此数据库必须实现AID三大特性才有可能实现一致性 。
1.2.3隔离性如果没有隔离性会发生的4种情况
丢失更新
A事务撤销时 , 把已经提交的B事务的更新数据覆盖了 。 这种错误可能造成很严重的问题 , 通过下面的账户取款转账就可以看出来 , MySQL通过三级封锁协议的第一级解决了丢失更新 , 事务T要修改数据A时必须加X锁 , 直到T结束才释放锁 。
脏读
【#JAVA破局之路#分布式事务解决方案),分布式事务详解(mysql事务如何实现的】脏读主要是读取到了其他事务的数据 , 而其他事务随后发生回滚 。 MySQL通过三级封锁协议的第二级解决了脏读 , 在一级的基础上 , 要求读取数据A时必须加S锁 , 读取完马上释放S锁 。
不可重复读
不可重复读是读取到数据后 , 随后其他事务对数据发生了修改 , 无法再次读取 。 MySQL通过三级封锁协议的第三级解决了不可重复读 。 在二级的基础上 , 要求读取数据A时必须加S锁 , 直到事务结束了才能释放S锁 。
幻读
幻读是读取到数据后 , 随后其他事务对数据发生了新增 , 无法再次读取 。
在InnoDB引擎RepeatableRead的隔离级别下 , MySQL通过Next-KeyLock以及MVCC解决了幻读 , 事务中分为当前读以及快照读 。
MVCC(MultiVersionConcurrencyControl)即多版本并发控制 , 一个行记录数据有多个版本对快照数据 , 这些快照数据在undolog中 。 如果一个事务读取的行正在做DELELE或者UPDATE操作 , 读取操作不会等行上的锁释放 , 而是读取该行的快照版本 。
由于MVCC机制在可重复读(RepeateableRead)和读已提交(ReadCommited)的MVCC表现形式不同在后续文章中将进行详细描述 。
在事务隔离级别为读已提交(ReadCommited)时 , 一个事务能够读到另一个事务已经提交的数据 , 是不满足隔离性的 。 但是当事务隔离级别为可重复读(RepeateableRead)中 , 是满足隔离性的 。