事务及其处理机制
什么是事务
事务是指作为单个逻辑工作单元执行的一系列操作,可以理解为一系列SQL语句的集合。
为什么需要事务
使用事务可以满足数据的ACID属性。
-
原子性(Atomicity):
一个事务中的所有操作要么全部完成、要么全部不完成,不会停留在中间的某个操作中。
例如:A对B转账,A账户中的钱减少、B账户中的钱增加这两个操作必须全部成功、或全部失败。不应该出现其中一方成功的状态。
在事务执行过程中如果发生错误会回滚到事务开始前的状态,MySQL会通过日志来保证原子性。
-
一致性(Consistency):
可以理解为一个事务提交之后,数据库的状态能满足原本的约束。
例如:A要支付100元,而A的账户中只有90元,则该事务执行会失败,数据库回滚至支付之前的状态。其中账户的余额就相当于一个约束,支付事务发生前后必须满足该约束。
事务执行时如果破坏了数据库的原本约束则该该事务执行会失败,并回滚到事务开始前的状态,以保证一致性。
-
隔离性(Isolation):
指对并行事务之间是相互隔离的,一个事务的执行不会受到其他事务的干扰。
例如:银行统计所有储户账户里的资金总额的过程中,A往账户里存入100元,则该存钱事务提交前后查询事务读取到的数据不同,会引起矛盾。
MySQL会通过锁机制来保证隔离性。
-
持久性(Durability):
被提交的事务对数据库的修改是永久的,即使中途发生崩溃等情况,在系统恢复后仍会完成被提交的事务对数据库的操作。
MySQL会通过日志来保证持久性。
如何使用事务
-
BEGIN
:开始一个事务 -
ROLLBACK
:事务回滚 -
COMMIT
:提交一个事务
例如:
有一个如下的student表
image如果使用ROLLBACK
则数据库不会被改变,
BEGIN;
INSERT INTO student(name, age, sex)
VALUES
('赵六', '18', '女');
ROLLBACK;
image
如果执行COMMIT
则数据库会被改变:
BEGIN;
INSERT INTO student(name, age, sex)
VALUES
('赵六', '18', '女');
COMMIT;
image
且提交过的事务就无法回滚了,即再执行一次ROLLBACK
数据库也不会回到最初的状态了。
事务的处理机制
事务日志
MySQL通过日志来实现事务的原子性和持久性,主要有回滚日志和重做日志两类。
回滚日志
为了保证事务的原子性,MySQL会通过回滚日志来将数据库恢复到事务开始前的状态。
即事务开始后,MySQL会先将事务进行的所有修改记录到回滚日志中,再执行修改操作。这样在提交之前可以根据回滚日志进行恢复,可以理解为通过一系列的逆向操作来恢复原有的数据。
重做日志
重做日志由两部分组成,一部分是内存中的重做日志缓冲区,另一部分是在磁盘上的重做日志文件。
事务修改数据的流程大致如下:
- 将数据从磁盘读入内存,并更新内存中缓存的数据
- 生成一条重做日志并写入重做日志缓存
- 当事务提交时,MySQL 会将重做日志缓存中的内容刷新到重做日志文件
- 将内存中的数据更新到磁盘上
这样,当数据还未修改完但发生了系统崩溃等故障时,系统恢复后MySQL会跟据重做日志完成之前未完成的操作。
事务的隔离特性
如果事务不保证隔离性的话,在一个事务处理过程中可能会发生如下问题:
- 脏读(Dirty Read):即读取到其他事务还未提交的数据;
- 不可重复读(Non-Repeatable Read):即一个事务范围内多次查询的结果不同,即在该事务执行过程中,其他事务提交了数据,进而干扰了该事务的执行;
- 幻读(Phantom Read):在一个事务查询过程中,其他事务对数据进行了修改,导致查询结果矛盾。
隔离级别
在 SQL 标准中定义了四种数据库的事务的隔离级别:READ UNCOMMITED
、READ COMMITED
、REPEATABLE READ
和 SERIALIZABLE
。不同级别的特性如下:
级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITED | 可能 | 可能 | 可能 |
READ COMMITED | 不可能 | 可能 | 可能 |
REPEATABLE READ | 不可能 | 不可能 | 可能 |
SERIALIZABLE | 不可能 | 不可能 | 不可能 |
一般默认的隔离级别为REPEATABLE READ
。
锁机制
MySQL通过给事务加锁来保证并行事务直接的隔离,锁分为共享锁(Shared)和互斥锁(Exclusive)两类。共享锁(也称为读锁)保证读操作可以并发执行互不影响,互斥锁(也称为写锁)保证写操作时不会有其他事务访问相同数据而造成冲突。
网友评论