数据库事务小结

面试的时候,总会被问到事务。很多时候知道是怎么回事,但是回答的时候又是那么吞吞吐吐的,反而表达不清楚。仔细想想,表达不清楚那是因为自己还不熟悉。所以将先前的一些资料重新整理了一下。

什么是数据库事务

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

  • 原子性:表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的原子操作执行成功,整个事务才提交;事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态。
  • 一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。如从A账户转钱到B账户,不管成不成功,A账户与B账户的总额是不变的。
  • 隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。也就是说,一个事务直到它被成功提交之后,它的结果对于任何其他的事务才是可见的。
  • 持久性:一个已提交事务的任何结果都必须是永久性的,即“在任何系统奔溃的情况下都能够保存下来”。

数据并发的问题

在多个客户端对数据库进行并发操作的时候,会出现一些并发问题。这些问题可以归纳为5类:3类数据读问题(脏读、不可重复读和幻读)和2类数据更新问题(第一类丢失更新和第二类丢失更新)

脏读(dirty read)

A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。

不可重复读(unrepeatable read)

A事务读取了B事务已经提交的更改数据。

幻读(phantom read)

A事务读取B事务提交的新增数据。这个时候A事务出现幻读问题。幻读一般发生在计算统计的事务当中。

幻读和不可重复读的区别:幻读是指读到了其他已经提交事务的新增数据;不可重复读是指读到了已经提交事务的更改数据(更改或删除)。防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化;防止读取到新增的数据,往往需要添加表级锁——将整个表锁定,防止新增数据。

第一类丢失更新

A事务撤销时,把已经提交的B事务的更新数据覆盖了。

第二类丢失更新

A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失。

数据库锁机制

表锁定和行锁定

按照锁定的对象的不同可以分为表锁定和行锁定。表锁定是对整个表进行锁定。行锁定对表中特定的行进行锁定。

共享锁定和独占锁定

从并发事务锁定的关系上来说,可以分为共享锁定和独占锁定。共享锁定会防止独占锁定,但允许其他的共享锁定。独占锁定既防止其他的独占锁定也防止其他的共享锁定。

事务隔离级别

隔离级别 脏读 不可重复读 幻读 第一类丢失更新 第二类丢失更新
READ UNCOMMITTED(读未提交) 允许 允许 允许 不允许 允许
READ COMMITTED(读已提交) 不允许 允许 允许 不允许 允许
REPEATABLE READ(可重复读) 不允许 不允许 允许 不允许 不允许
SERIALIZABLE(串行化) 不允许 不允许 不允许 不允许 不允许
  • SERIALIZABLE(串行化):可避免脏读、不可重复读、幻读的发生。
  • REPEATABLE READ(可重复读):可避免脏读、不可重复读的发生。
  • READ COMMITTED(读已提交):可避免脏读的发生。
  • READ UNCOMMITTED((读未提交):最低级别,任何情况都无法保证。

事务的隔离级别和数据库的并发是向对立的。READ UNCOMMITTED的隔离级别低,但拥有最高的并发性和吞吐量。SERIALIZABLE的隔离级别高,但并发性低。

默认的隔离级别是REPEATABLE READ(可重复读)