1.概念
- Atomicity [ˌætəˈmɪsəti] 原子性
- Consistency [kənˈsɪstənsi] 一致性
- Isolation [ˌaɪsəˈleɪʃn] 隔离性
- Durability [dərəˈbɪlɪti] 持久性
ACID
:事务的四大特性
1.1. 原子性
事务
作为处理中不可分割的最小单元
。
一个事务
执行结果只有两种:
- 成功
提交
- 失败
回滚
不存在执行一部分的情况,这便是事务的原子性
。
1.2. 一致性
数据库总是从一个一致性状态转换到另一个一致性状态。
我们可以理解,一个事务
完整的执行完毕,便是从原来的一致性
状态转换到另一个一致性
状态。如果中间执行失败,则不会进行提交
(commit),由此可以保证数据库的一致性
。
1.3. 隔离性
一个事务
所做的修改在最终提交
之前,对其他事务
是不可见的。
假设事务1
执行SQL-1
时,对数据库的某条数据的字段作了Update
操作,执行完毕后,事务2
的SQL-1
刚好去Select
这条数据,此时查询出来的结果并不是事务1
的SQL-1
更新完后的结果,因为事务1
的SQL-1
虽然执行完毕,但是并没有commit
,因此执行结果对事务2
并不可见,这便是事务
的隔离性
。
1.4. 持久性
一旦事务
提交,则所做的修改操作就会永久保存到数据库中。
这点就比较好理解,我们的事务
执行完毕,那么数据便会持久化
,无论是系统崩溃还是其他情况,数据都不会发生丢失。
每种数据库都有不同的持久性保证策略,但都不可能100%的保证持久性,因此还是做好备份!
2. 事务的隔离级别
事务
的隔离性
比较复杂,对应四种隔离级别
(级别由低到高,性能由高到低):
未提交读
(READ UNCOMMITTED)提交读
(READ COMMITTED)可重复读
(REPATABLE READ)可串行化
(SERIALIZABLE)
2.1. 未提交读
在该级别中,事务
中的修改操作,即便没有进行commit
操作,只要执行完毕,对于其他事务
就是可见的
。
如上文隔离性
中介绍,在该级别下,事务1
中的SQL-1
修改操作执行完毕,事务2
中的SQL-1
去查询,查询的结果是修改完毕后的结果,即便此时事务1
没有进行提交
!
设想,假设事务2
的SQL-1
查询完事务1
的SQL-1
修改后的结果,而此时事务1
执行SQL-2
发生了错误,导致事务
发生了回滚
,事务1
的SQL-1
修改操作被回滚
,而事务2
的SQL-1
使用的数据仍然是修改完的数据,这就是脏读
。
该级别一般不会使用。
2.2. 提交读
这个级别即使我们上文隔离性中列举的例子:一个事务只能看见已经提交的事务做的修改
。
假设事务2
中的两条SQL
均为查询同一条数据,SQL-1
发生在事务1
提交之前,SQL-2
发生在事务1
提交之后,因为事务1
的修改操作再未提交之前对于事务2
是不可见的,这就导致两次查询的结果不一致
,因此这个级别也被称为不可重复读
。
大多数数据库的默认级别。
2.3. 可重复读
该级别是在提交读
的基础上,保证事务之间的相对独立性,即在事务2
中SQL-2
的查询结果依旧是事务1
修改之前的,即便事务1
已经提交
,这样保证了在同一事务中,多次读的结果是一致的
。
但这种结果一致性
是针对修改
操作(修改已存在数据的字段),如果事务1
的SQL-1
执行的是插入
或者删除
操作,而事务2
的查询
为范围性查找,这时会发现,两次结果的行数并不一致(可以查询出来插入
或者删除
而引起行的变化),不一致的行被称为幻行
。这便是幻读
问题。
MySQL
的默认
隔离级别,同时MySQL
的InnoDB
存储引擎是已经解决幻读
问题的(多版本并发控制)。
2.4. 可串行化
最高的隔离级别。该级别会在读取行上添加锁,强制事务串行化执行来避免出现幻读问题。
3. MySQL的事务
3.1. 修改自动提交
我们在MySQL
中执行SQL时可以发现,我们不用显式的去进行commit
操作,这是因为MySQL
默认采用的是自动提交
(AutoCommit
)模式。在该模式下,所有的查询都被当作一个事务
来进行提交
。
在mysql
库中执行下面SQL可以查看当前连接是否开启了自动提交
SHOW VARIABLES LIKE 'AUTOCOMMIT';
通过下面命令可以修改当前连接
禁用自动提交
SET AUTOCOMMIT = 0;
但是需要注意的是,即便关闭了自动提交
,有时候也会触发自动提交
- 非事务型表,例如使用
MyISAM
引擎的表(MySQL 5.5
之前的默认存储引擎),因为这类表本身就没有提交
和回滚
,所以无论执行什么SQL,都等同于自动提交
。 - 特殊命令。例如一些
DDL
,由于更改了数据表结构而引起大量的数据发生更改时会触发自动提交
。但不同的版本触发自动提交
的语句都不同,需要根据版本来进行确定。
3.2. 设置隔离级别
MySQL
的默认隔离级别
为可重复读
(REPATABLE READ
)
可以通过下面命令修改当前会话
的事务隔离级别
(整个数据库的隔离级别
需要修改配置文件)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;