事务种类
- 隐式事务
如单条 sql 语句的执行
- 显式事务
如多条 sql 语句的执行,一般谈论数据库事务时,指的是数据库的显式事务
事务特性
数据库事务具有 ACID 这4个特性
-
A —— Atomic /əˈtɒmɪk/
原子性。所有 sql 作为一个原子工作单元执行,要么全部执行,要么全部不执行。这里应该是借用了化学学科的术语概念:原子虽然在物理状态中可以继续细分(原子由原子核和核外电子组成),但原子在化学反应中是不可再分。
-
C —— Consistent /kənˈsɪstənt/
一致性。事务完成后,所有数据的状态都是一致的,比如我转账给你100,那么我的账户减去了100,你的账户则必定加上了100。
-
I —— Isolation /ˌaɪsəˈleɪʃn/
隔离性。每个事务做的操作必须与其它事务隔离,即便有多个事务并发执行。一个事务处理时的中间状态对其它事务是不可见的。
-
D —— Duration /duˈreɪʃn/
持久性。事务完成后,相关的对数据库数据的修改被持久化存储。
数据不一致问题
多个并发执行的事务,如果操作时涉及同一条记录数据,可能会发生问题,即并发操作可能导致数据的不一致问题,这些问题包含以下3种情形:
-
脏读(Dirty Read)
读取未提交数据
执行时间 事务A 事务B 1 事务开启 2 事务开启 修改一条记录record(假使原来数据是纯粹干净的,被改了,就不纯粹了,脏了) 3 读取事务B修改的那条记录(事务B之后的事务回滚,导致了此时产生脏读) 4 事务回滚 5 再次读取事务B修改的那条记录 6 事务提交 -
不可重复读(Non Repeatable Read)
前后多次读取,数据内容不一致
执行时间 事务A 事务B 1 事务开启 2 读取一条记录record 事务开启 3 修改事务A读取的那条记录 4 事务提交 5 再次读取这条记录record(此时发现这条记录跟在同一个事务内之前读取的不一致了,不能重复读) 6 事务提交 -
幻读(Phantom Read)
Phantom /ˈfæntəm/ ,前后多次读取,数据记录总数不一致
执行时间 事务A 事务B 1 事务开启 2 查询记录总数count 3 事务开启 4 增加或删除一些记录 5 事务提交 6 再次查询记录总数count(此时count比原来的大了或小了,记录总数变了,幻读) 7 事务提交
隔离级别
为了避免(不是解决)上述可能出现的数据不一致问题,数据库系统提供了隔离级别(Isolation Level)这一机制。
SQL标准定义了4种隔离级别:
1. Read Uncommitted (可以读取未提交数据)
2. Read Committed(可以读取已提交数据)
3. Repeatable Read(可重复读)
4. Serializable(可串行化)
各种隔离级别分别对应可能出现的数据不一致的情况(Y标志可能出现):
隔离级别(Isolation Level ) | 脏读(Dirty Read) | 不可重复读(Non Repeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
Read Uncommitted | Y | Y | Y |
Read Committed | - | Y | Y |
Repeatable Read | - | - | Y |
Serializable | - | - | - |
隔离级别双刃剑
Read Uncommitted、Read Committed、Repeatable Read、Serializable 这4种隔离级别,按隔离级别严格程度划分,Read Uncommitted隔离级别最低,Serializable隔离级别最严,隔离级别越严格,安全性越高,越能保证数据的一致性,但对并发性能的影响也越大,所谓“鱼与熊掌不可兼得”吧。例如,对于Serializable隔离级别,由于事务是串行执行,即所有事务按照次序依次执行,所以效率会大大下降,应用程序的性能会急剧降低。实际项目使用时需要权衡“利弊”,比如MySQL中的InnoDB引擎,其为了兼顾安全与性能,默认的隔离级别就是Repeatable Read,然后采取隔离级别之外的措施来避免“幻读”的问题。
来源:CSDN
作者:极乐谷2
链接:https://blog.csdn.net/u012815136/article/details/104547740