- (Atomicity ) 原子性: 事务是最小的执行单位,不允许分割。原子性确保动作要么全部完成,要么完全不起作用
即要么转账成功,要么转账失败,是不存在中间的状态!
如果无法保证原子性就会出现数据不一致的情形,A账户减去50元,而B账户增加50元操作失败。系统将无故丢失50元 - (Consistency)一致性: 事务将数据库从一种状态转变为下一种一致的状态。在事务的前后,数据库的完整性约束没有被破坏
这个状态是满足预定的约束就叫做合法的状态,通俗一点来说,这状态是由你自己来定义的。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的
如果无法保证一致性会怎么样?
例一:A账户有200元,转账300元出去,此时A账户余额为-100元。你自然就发现了此时数据是不一致的,为什么呢?因为你定义了一个状态,余额这列必须大于0。
例二:A账户200元,转账50元给B账户,A账户的钱扣了,但是B账户因为各种意外,余额并没有增加。你也知道此时数据是不一致的,为什么呢?因为你定义了一个状态,要求A+B的余额必须不变。 - (Isolation)隔离性: 并发访问数据库时,一个事务不被其他事务所干扰
如果不保证隔离性,A扣款两次,而B只加款一次,凭空消失了50元,依然出现了数据不一致的情形
- (Durability)持久性: 一个事务被提交之后。对数据库中数据的改变是持久的,即使数据库发生故障。
1.Mysql怎么保证一致性的?
(1)从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性。数据库必须要实现AID三大特性,才有可能实现一致性。
(2)从应用层面,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据!
2.Mysql怎么保证原子性的?
利用Innodb的undo log:
(undo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句,他需要记录你要回滚的相应日志信息。)
例如
(1)当你delete一条数据的时候,就需要记录这条数据的信息,回滚的时候,insert这条旧数据
(2)当你update一条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执行update操作
(3)当年insert一条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执行delete操作
undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
3.Mysql怎么保证持久性的?
利用Innodb的redo log:
Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。如果此时突然宕机,内存中的数据就会丢失。
使用redo log,当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo log和binlog内容决定回滚数据还是提交数据。
好处:
将redo log进行刷盘比对数据页刷盘效率高:
redo log体积小,刷盘快。一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。
4.Mysql怎么保证隔离性的?
利用的是锁和MVCC机制:
至于MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据,这些快照数据在undo log中。
如果一个事务读取的行正在做DELELE或者UPDATE操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。
MVCC机制在可重复读(Repeateable Read)和读已提交(Read Commited)的MVCC表现形式不同
在事务隔离级别为读已提交(Read Commited)时,一个事务能够读到另一个事务已经提交的数据,是不满足隔离性的。但是当事务隔离级别为可重复读(Repeateable Read)中,是满足隔离性的。
总结:
隔离性主要是针对读操作的。在不同事务之间,读操作隔离。比如另一个事务对数据修改后,会不会影响当前事务的读操作,要不要读到更新后的数据。
一致性,主要强调的是数据的更新是不是“正确”,即,是不是符合我们的预期,这个和读操作应该是要分开看待的,这里应该只强调写操作。