事务隔离级别 (ODBC)

事务隔离级别 是事务隔离成功程度的度量值。 具体而言,事务隔离级别由存在或缺少以下现象定义:

  • 脏读取 当事务读取尚未提交的数据时,将发生 脏读取 。 例如,假设事务 1 更新行。 事务 2 在事务 1 提交更新之前读取已更新的行。 如果事务 1 回滚更改,则事务 2 读取的数据将被视为从未存在过。

  • 不可重复读取 当事务读取同一行两次但每次获取不同的数据时,会发生 不可重复的读取 。 例如,假设事务 1 读取行。 事务 2 更新或删除该行并提交更新或删除。 如果事务 1 重新读取该行,它将检索不同的行值或发现该行已被删除。

  • 幽灵幻影是与搜索条件匹配但最初看不到的行。 例如,假设事务 1 读取一组符合某些搜索条件的行。 事务 2 生成与事务 1 的搜索条件匹配的新行(通过更新或插入)。 如果事务 1 重新执行读取行的语句,它将获取不同的一组行。

根据这些现象定义四个事务隔离级别(由 SQL-92 定义)。 下表中,“X”标记可能发生的每个现象。

事务隔离级别 脏读取 不可重复读取 幽灵
未提交读 X X X
已提交读 -- X X
可重复读 -- -- X
可序列化 -- -- --

下表描述了 DBMS 可能实现事务隔离级别的简单方法。

重要

大多数 DBMS 使用比这些方案更复杂的方案来提高并发性。 这些示例仅用于说明目的。 特别是,ODBC 不规定特定 DBMS 如何相互隔离事务。

事务隔离 可能的实现
未提交读 事务相互之间没有隔离。 如果 DBMS 支持其他事务隔离级别,它将忽略用于实现这些级别的任何机制。 因此,它们不会对其他事务产生负面影响,在“读取未提交”级别运行的事务通常是只读的。
已提交读 事务会等待,直到被其他事务写锁定的行被解锁;这可以防止它读取任何“脏”数据。

事务持有读取锁(如果它只读取行)或写入锁(如果它更新或删除当前行),以防止其他事务更新或删除它。 事务在离开当前行时释放读取锁。 它保留写入锁,直到提交或回滚。
可重复读 事务会等待,直到所有其他事务锁定的行被写锁解除;这可以防止读取任何不正确的数据。

事务在返回给应用程序的所有行上持有读取锁,并在插入、更新或删除的所有行上持有写入锁。 例如,如果事务包含 SQL 语句 SELECT * FROM Orders,则在应用程序提取行时,事务会对这些行进行读取锁定。 如果事务包含 SQL 语句 DELETE FROM Orders WHERE Status = 'CLOSED',则事务会在删除行时写锁定这些行。

由于其他事务无法更新或删除这些行,因此当前事务可避免任何不可重复的读取。 事务在提交或回滚时释放其锁。
可序列化 事务会等待,直到其他事务写锁定的行被解锁;这可以防止它读取任何“脏”数据。

事务在其影响的行范围上保留读取锁(如果仅读取行)或写入锁(如果可以更新或删除行)。 例如,如果事务包含 SQL 语句 SELECT * FROM Orders,则范围是整个 Orders 表;事务读取锁定表,不允许将任何新行插入其中。 如果事务包括 SQL 语句 DELETE FROM Orders WHERE Status = 'CLOSED',则范围是状态为“CLOSED”的所有行;事务写入锁定 Orders 表中状态为“已关闭”的所有行,不允许插入或更新任何行,使生成的行的状态为“CLOSED”。

由于其他事务无法更新或删除区域中的行,因此当前事务可避免任何不可恢复的读取。 由于其他事务无法在该范围内插入任何行,当前事务因此避免了任何幻影。 事务在提交或回滚时释放其锁。

请务必注意,事务隔离级别不会影响事务查看自身更改的能力:事务始终可以看到它们所做的任何更改。 例如,事务可能包含两个 UPDATE 语句,第一个语句将所有员工的薪酬提高 10%,第二个语句将任何雇员的薪酬设置为该金额的上限。 这仅作为单个事务成功,因为第二个 UPDATE 语句可以看到第一个事务的结果。