原子性 A
整个数据库事务都是不可分割的工作单位,只有使事务中的所有数据库操作都执行成功,事务才算成功
一致性 C
一致性是指事务使数据库从一种状态转移到下一种一致性状态,事务的执行之前和执行之后都必须处于一致性状态
隔离性 I
事务隔离性要求每个事务的读写对象对其他事务的操作对象能相互分离,即在提交之前对其他事务都不可见
持久性 D
InnoDB如何实现ACID事务一旦提交结果就是永久性的,即使数据库发生宕机等故障也能将数据恢复。
原子性
InnoDB利用undo log(回滚日志)来实现事务的原子性,当事务回滚时能够撤销所有已经成功执行的SQL语句。undo log中记录了数据被修改前的信息以及新增和被删除的数据信息。
比如:
当删除一条数据的时候,就需要记录这条数据的信息,回滚的时候,新增这调信息当新增一条数据的时候,需要记录这条数据的主键,回滚的时候,依据主键删除信息当修改一条数据时,需要记录该数据的旧值,回滚的时候执行修改操作
持久性
InnoDB利用了redo log(重做日志)来实现事务的持久性
当有一条记录更新时,InnoDB会先把记录写到redo log里面,并更新内存,InnoDB会在适当的时候将其刷入磁盘。当数据库宕机重启时,会将redo log中的内容恢复到数据库中,再根据undo log和bin log内容决定回滚数据还是提交数据。
隔离性
MySQL通过锁和MVCC机制来实现隔离性
隔离级别
读未提交 允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。读不会加任何锁。而写会加排他锁,并到事务结束之后释放。
读提交 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。会通过MVCC获取当前数据的最新快照,不加任何锁,也无视任何锁
可重复读 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。一次事务中只在第一次****select时生成版本,后续的查询都是在这个版本上进行,从而实现了可重复读。
串行化 针对同一数据的所有读写都变成互斥的。
脏读: 当一个事务正在访问数据并且对该数据 读取到未提交的数据
**不可重复读:**在第一个事务两次读取数据之间,由于第二个事务的修改导致第一个事务两次读取的数据不同。
**幻读:**幻读与不可重复读类似,第一个事务读取了几行数据,接着另一个事务插入了些数据,在随后的查询中第一个事务会发现多了一些原本并不存在的记录,就好像发生了幻觉一样,所以称为幻读
不可重复读和幻读的区别
不可重复读的重点是修改,比如多次读取一条记录发现其中的某些列的值被修改,幻读的重点在于新增或删除,比如多次读取一条记录发现记录增多或减少了。
MVCC
MVCC是指多版本并发控制,MVCC是在并发访问数据库时,通过对数据进行多版本控制来避免因写锁而导致的读操作的阻塞,从而很好的优化并发阻塞问题。
通过undo log和一致性视图来实现,通过undo log来保存多版本的数据,通过一致性视图来保存当前活跃的事务列表。
比如一个值 1 被顺序的改为2、3、4
不同时刻启动的事务会有不同的视图,在视图 A、B、C 中 记录的值可以分别为 1,2,3,即一条记录在系统中可以存在多个版本,这就是多版本并发控制。
长事务危害
长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间
一致性
从数据库层面 数据库通过原子性、隔离性、持久性,来保证一致性。即原子性、隔离性、持久性均为为了实现一致性的手段,而一致性才是最终的目的从应用层面,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据



