数据库事务概览

事务种类

  • 隐式事务

    如单条 sql 语句的执行

  • 显式事务

    如多条 sql 语句的执行,一般谈论数据库事务时,指的是数据库的显式事务

事务特性

数据库事务具有 ACID 这4个特性

  • A —— Atomicity /ˌætəˈmɪsəti/

    原子性。所有 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,然后采取隔离级别之外的措施来避免“幻读”的问题。

你可能感兴趣的:(数据库/云计算/大数据)