MySQL数据库事务有四大特性,简称为ACID,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),共同确保了数据库事务的正常执行,保证了事务的一致性和可靠性。
一、原子性(Atomicity)
原子性 是指事务的语句为一个整体 ,要么全部执行成功 ,要么全部不执行 (存在命令执行出错,数据全部回滚到事务开始执行前的状态),进而保证数据的一致性和可靠性。
**例子:**银行需要办理用户A向用户B转账1万元的业务,需要A扣款1万元,B增加1万元,当A扣款成功后,B入账1万元出现问题,此时需要回滚数据,将A和B的数据恢复至转账服务前的情况。
**实现机制:**Undo Log(撤销日志)机制------Undo Log用于记录事务执行前的数据状态,以及事务执行过程中对数据所做的修改,以便在需要时能够恢复到之前的版本。
二、一致性(Consistency)
一致性 是指确保事务的执行不会破坏数据库的有效状态 。事务执行前后,数据库中的数据必须满足所有的预定义约束和业务规则(如外键约束、唯一性约束)。
**例子:**还是上面的转账服务,一致性确保了转账操作完成后,总余额没有改变,而且两个账户的余额都符合预期的变化。如果在事务过程中发生任何问题(如网络中断、系统崩溃等),事务将回滚,数据库将恢复到事务开始前的状态,以保持一致性。
实现机制:
- Redo Log(重做日志)机制:Redo Log 主要用来记录事务对数据库所做的物理修改,确保这些修改能够持久化到磁盘。即使在系统故障(如断电)的情况下,通过重放 Redo Log 文件中的记录,数据库系统也能够恢复未完成的事务,以确保这些修改能够在系统故障后得到恢复。
- 约束:约束是在表定义中指定的规则,用于限制可以存储在表中的数据。MySQL支持多种类型的约束,如主键、外键、非空、默认值。
- 触发器:触发器是一种存储过程,它在特定事件(如INSERT、UPDATE或DELETE操作)发生时自动执行复杂逻辑或业务规则,进一步增强数据的一致性和完整性。
三、隔离性(Isolation)
隔离性是指确保并发执行的事务之间相互独立,互不影响,就像每个事务单独执行一样。
**例子:**如果有两个并发的事务试图同时修改同一行数据,隔离性确保一个事务的操作不会影响另一个事务的结果,直到第一个事务提交。
实现机制:
- 事务隔离等级: 事务隔离级别定义了事务之间数据可见性的程度。MySQL支持四种标准的事务隔离级别,它们按顺序从低到高分别是:
- 读未提交 (Read Uncommitted):最低的隔离级别,允许事务读取其他未提交事务的数据。这种级别可能会导致脏读、不可重复读和幻读。
- 读已提交 (Read Committed):事务只能读取其他已提交事务的数据。这种级别避免了脏读,但仍然可能出现不可重复读和幻读。
- 可重复读 (Repeatable Read):这是MySQL默认的隔离级别。在该级别下,事务在整个执行期间可以看到一致的数据视图,即事务开始时的数据状态。这避免了脏读和不可重复读,但仍然可能出现幻读。
- 串行化 (Serializable):最高的隔离级别,通过强制事务串行执行来避免所有并发问题,包括脏读、不可重复读和幻读。这种级别可能会影响性能,因为它会引入更多的锁。
- 锁机制: 锁机制用于控制并发事务对数据的访问,确保事务的隔离性。
- 共享锁 (S Locks):允许多个事务读取数据,但阻止其他事务修改数据。
- 排他锁 (X Locks):允许事务读取和修改数据,阻止其他事务读取或修改同一数据。
- MVCC多版本并发控制 : 允许事务在不同的时间点看到数据的不同版本,从而解决读取和写入之间的冲突问题。
- MVCC 在每个数据行上维护一个版本号,允许事务读取与其开始时的数据版本相匹配的行版本。这样,事务可以读取数据而不阻塞其他事务的更新操作。
- MVCC 在可重复读隔离级别下特别有用,因为它允许事务在没有显式锁的情况下读取数据。
补充(脏读、不可重复读和幻读):
- 脏读:指的是一个事务读取到了另一个事务未提交的数据。如果第二个事务后来回滚了,那么第一个事务读取的数据就是无效的,这就产生了脏读的问题------发生在事务读取了另一个事务未提交的数据。
- 不可重复读:指的是在一个事务内多次读取同一行数据时,数据可能会发生变化。这种情况发生在事务隔离级别低于"可重复读"时------发生在事务内多次读取同一行数据时数据发生变化。
- 幻读:指的是在一个事务内多次读取同一范围的数据时,数据集可能会发生变化。例如,新的行可能会被插入到数据集中,或者某些行可能会被删除------发生在事务内多次读取同一范围的数据时数据集发生变化。
四、持久性(Durability)
持久性是指确保一旦事务提交,永久保存数据,即使系统发生故障也不会丢失。
**例子:**一旦转账事务提交,即使数据库服务器随后崩溃,转账的数据也将保留在数据库中。
实现机制:
- **Redo Log(重做日志):**Redo Log 记录了事务对数据库所做的物理修改,即使在系统故障后也能确保数据的持久性------当事务提交时,MySQL 首先将事务的修改记录写入 Redo Log 缓冲区,Redo Log 缓冲区的内容会被周期性地刷新到磁盘上,或者在 Redo Log 缓冲区满时触发刷新,如果系统出现故障,MySQL 在重启时会重放 Redo Log 中的记录,以恢复未完成的事务。
- **Binlog(二进制日志):**Binlog 记录了事务执行的逻辑操作,可用于数据恢复、复制和备份------当事务提交时,MySQL 会将事务的逻辑操作记录写入 Binlog,Binlog 会立即写入磁盘,确保数据的持久性,在某些情况下,MySQL 可以使用 Binlog 来恢复数据,特别是在 Redo Log 不足或损坏的情况下。