转:
略谈事务ACID
数据库事务
访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成;
简言之:
要么都成功,要么都失败。
ACID
数据库事务正确执行的四个基本原则的缩写;
包含:
原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
一个支持事务的数据库(例如:INNODB引擎),必须要具有这四种特性。
以经典的银行转账为例略谈一下
原子性
事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
例:A用户给B用户转账500元
银行 | 执行 | 结果 |
---|---|---|
A用户(1000元) | 1000-500 | 500 |
B用户(500元) | 500+500 | 1000 |
在转账过程中,这两个步骤只能成功或失败,不得出现一个用户资金有变动而另一个用户资金没变动的情况。
一致性
几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
银行 | 执行 | 结果 |
---|---|---|
A用户(1000元) | 1000-500 | 500 |
B用户(500元) | 500+500 | 1000 |
总计(1500元) | 1500 | 1500 |
在整个操作过程中,其两个用户的资金总额是恒定不变的。
隔离性
事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
例:A用户给B用户转账500元,C用户给B用户转账500元
银行 | 执行 | 结果 |
---|---|---|
A用户(1000元) | 1000-500 | 500 |
B用户(500元) | 500+500 | 1000 |
银行 | 执行 | 结果 |
---|---|---|
C用户(1000元) | 1000-500 | 500 |
B用户(500元) | 500+500 | 1000 |
银行 | 最终结果 |
---|---|
A用户 | 500 |
B用户 | 1500 |
C用户 | 500 |
在多用户进行操作的时候,主要是排除其他用户对自身的一个影响。
持久性
对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失。
如在提交一组事务的时候遇到服务器崩溃或者断电,若事务未完成提交,则恢复到原来的状态;若事务已完成提交,则持久化到数据库中;
事务一旦提交,便不可逆。
事务并发问题
数据库是要被广大客户所共享访问的,那么在数据库操作过程中不考虑隔离问题的话很可能诱发一些非常情况。
脏读
一个事务读取到了另一个事务未提交的数据操作结果。
在A给B完成转账的时候,B是1000元,但是在C给B转账的时候,读取到的是A未给B转账前的数据(500元),结果造成了两边数据不对等情况;
这种情况相当危险,因为很可能所有的操作都被回滚。
不可重复读
一个事务对同一行数据重复读取多次,但是却得到结果不同。
第一次读取值:
用户 | 资金 |
---|---|
A | 1000 |
B | 500 |
第二次读取值:A用户有入账情况
用户 | 资金 |
---|---|
A | 2000 |
B | 500 |
第三次读取值:B用户有支出情况
用户 | 资金 |
---|---|
A | 1000 |
B | 200 |
不可重复读不一定是错误,也可能是读取时间的问题所导致;
虚读(幻读)
一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
第一次读取值:
用户 | 资金 |
---|---|
A | 1000 |
B | 500 |
第二次读取值:多了一条记录
用户 | 资金 |
---|---|
A | 2000 |
B | 500 |
D | 1000 |
虚读一般无较大影响,一般为行影响。
事务隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别;在标准SQL规范中,定义了四种事务隔离级别:
读未提交(READ UNCOMMITTED)、读提交 (READ COMMITTED)、
可重复读 (REPEATABLE READ)、串行化 (SERIALIZABLE)。
不同的隔离级别对事务的处理不同,从上往下,隔离强度逐渐增强,性能逐渐变差,其中,可重复读是 MySQL 的默认隔离级别。
隔离级别 | 脏读 | 不可重复读 | 虚读(幻读) |
---|---|---|---|
读未提交 | √ | √ | √ |
读提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
转: