MENU

有关数据库事务特性、隔离级别的总结

February 5, 2020 • 数据库

为什么需要事务

在日常开发中会经常用到事务,通常是为了保证一连串的 SQL 语句要么能全部执行,要么就全部都不执行。比如说在商城设计中, 用户 A 进行购物车的结算,从他发起结算到生成订单,中间就涉及到多个数据库操作,:

  1. 去除购物车被结算的商品记录;
  2. 计算支付金额,生成支付记录、订单记录、修改商品的库存;
  3. 支付回调成功,修改支付记录的状态、订单记录的状态;

这还只是成功的操作,如果支付失败还需要进行相应的回滚操作。如果在这一批操作中某个语句没有成功执行,那么数据的一致性就会被破坏,因此我们需要事务来完成一系列的操作。

事务的特性(ACID)

站在业务的角度来说,为了保证数据的一致性和正确性,一个事务需要满足以下 4 个特性:

  1. 原子性(Atomicity)

每一个事务都视作一个最小的工作单元,只有事务中全部的数据库操作都执行了,才认为该事务执行成功。如果其中某一条 SQL 失败了,那么其余的 SQL 都要撤销,恢复到事务执行前的状态。

  1. 一致性(Consistency)

在事务执行的前后,数据库将从一种一致状态转变为另一种一致状态,也就是说数据库在执行事务前后,数据的完整性将不会被破坏。比如说购物车结算例子中,在事务执行完成后,商品的库存量加上订单的商品量等于事务执行前商品的库存量。

  1. 隔离型(Isolation)

要求每个读写事务与其他事务的操作对象是互不影响的。比如在用户 A 购买商品时,不会影响用户 B 购买相同的商品。

  1. 持久性(Durability)

事务一旦提交,其产生的结果是永久性的。

事务的隔离级别

如果两个事务都对同一条记录进行操作,那么最后的结果是以哪一个事务为准了?这就要看此时数据库的事务隔离级别了。

  1. 未提交读(READ UNCOMMITTED)

一个事务所做的操作还未提交,它做的操作可被其他事务看到。

  1. 已提交读(READ COMMITTED)

一个事务做的操作要等到他提交了事务之后才能被其他事务看到

  1. 可重复读(REPEATABLE READ)

一个事务在执行过程中看到的数据,总是和它在启动的时候看到的数据是一样的。

  1. 可串行(SERIALIZABLE)

就像队列一样,每个事务都是排队等候着执行,只有前一个事务提交之后,下一个事务才能进行操作。

事务的并发问题

如果不对数据库进行并发控制,可能会产生异常情况:

  1. 脏读

指的是在事务的执行过程中,读到了其他未提交事务所执行的结果。

  1. 不可重复读

指的是在事务的执行过程中,重复执行了相同的操作,却得到不同的结果。比如说:多次读取一条记录, 发现该记录中某些列值被修改过。

  1. 幻读

指的是在事务的执行过程中,重复查询某一范围内的记录,发现记录的数量不一致。比如说:多次查询某一范围内记录条数,发现条数会发生改变。

另外,对于不同的隔离级别,允许发生的并发副作用也不同:

#脏读不可重复读幻读
未提交读
已提交读
可重复读
串行化