什么是ACID?
- 在传统的关系型数据库(RDBMS)中,ACID是四个重要的特性:
-
原子性(Atomicity)
一个事务要么全部执行,要么全部不执行。
-
一致性(Consistentcy)
事务开始与结束,不能破坏关系数据的完整性及业务的逻辑一致性。
-
隔离性(Isolation)
多个事务之间是相互隔离的。
-
持久性(Duration)
一旦事务完成,数据的修改是持久地存储在数据库中(例如储存在硬盘中),事务的完成状态是不会再改变。
什么是事务的隔离级别?
事务ACID特性,其中I代表隔离性(Isolation)。
隔离性,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他的用户事务干扰,多个并发事务之间要相互隔离。
一个事务怎么干扰其他事务
- 例子:
假设有InnoDB表:
t(id PK, name)
表中记录:
1、shenjian
2、zhangsan
3、lisi
case 1
1、事务A,先执行,处于未提交的状态:
insert into t values(4, wangwu);
2、事务B,后执行,也未提价:
select * from t;
如果事务B能够读取到(4,wangwu)这条数据,事务A就对事务B产生了影响,这个影响叫做脏读
,
脏读
:读取到了未提交的事务操作的记录
case 2
1、事务A,先执行:
select * from where id=1;
》结果集为:1,shenjian
2、事务B,后执行,并且提交:
update t set name=XXOO where id=1;
commit;
3、事务A,再次执行相同的查询:
select * from t where id=1;
》结果集为:1,XXOO
这次是已提交的事务B对事务A产生了影响,这个影响叫做不可重复读
,
不可重复读
:一个事务内相同的查询,得到不同的结果
case 3
1、事务A,先执行:
select * from t where id>3;
》结果集:NULL
2、事务B,后执行,并且提交:
insert into t values(4,wangwu);
commit;
3、事务A,首次查询了id>3的结果为NULL,于是想插入一条为4的记录:
insert into t values(4, xxoo);
结果集为:
Error : duplicate key!
当事务A在去插入数据的时候,就会报错,id=4的PK值冲突,这次是已经提交事务B对事务A产生了影响,这个影响叫做幻读
InnoDB 数据库事务隔离级别
1、Serializable
串行化,一个事务一个事务的执行
- 这种事务的隔离级别下,所有的SELECT语句都会被隐式的转换为select…..in share mode;
- 如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。
- 官方解释:To force a plain SELECT to block if other transactions have modified the selected rows;
- 这是一致性最好的,但是并发性最差的隔离级别。
2、Read uncommitted
读取未提交,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值.
- 这种事务隔离级别下,SELECT语句不加锁。
- 官方解释:SELECT statements are performed in nolocking fashion;
- 此时,可能读取到不一致的数据,即脏读。这是并发最高,一致性最差的隔离级别。
在互联网中大数据量,高并发量的场景下,几乎不会使用上面—隔离级别
3、Repeatable read
这是InnoDB的默认隔离级别
可重复读,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响
普通的select使用快照读(snapshot read),这是一种不加锁的一致性读(Consistent Nonlocking Read),底层使用MVCC来实现
-
加锁的select(select ... in share mode / select ... for update), update, delete等语句,它们的锁,依赖于它们是否在唯一索引(unique index)上使用了唯一的查询条件(unique search condition),或者范围查询条件(range-type search condition):
-
在唯一索引上使用唯一的查询条件,会使用
记录锁(record lock)
,而不会封锁记录之间的间隔,即不会使用间隙锁(gap lock)与临键锁(next-key lock) -
范围查询条件,会使用
间隙锁与临键锁
,锁住索引记录之间的范围,避免范围间插入记录,以避免产生幻影行记录,以及避免不可重复的读
-
在唯一索引上使用唯一的查询条件,会使用
4、Read committed
这是互联网的最常用的隔离级别
读取已提交,其他事务提交了对数据的修改后,本事务就能读取到修改后的数据值.
- 普通读是快照读;
- 加锁的select, update, delete等语句,除了在外键约束检查(foreign-key constraint checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁;
总结
- 并发事务之间相互干扰,可能导致事务出现
读脏,不可重复度,幻读
等问题 - InnoDB实现了SQL92标准中的四种隔离级别
(1)读未提交:select不加锁,可能出现读脏;
(2)读提交(RC):普通select快照读,锁select /update /delete 会使用记录锁,可能出现不可重复读;
(3)可重复读(RR):普通select快照读,锁select /update /delete 根据查询条件情况,会选择记录锁,或者间隙锁/临键锁,以防止读取到幻影记录;
(4)串行化:select隐式转化为select ... in share mode,会被update与delete互斥;
- InnoDB默认的隔离级别是RR,用得最多的隔离级别是RC