这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

事务

多个用户会话中的 事务并发访问相同数据时,会话范围的隔离级别决定了每个事务可访问哪些数据。

事务将保留其隔离级别直至其完成,即使在事务处理期间会话的隔离级别发生更改也是如此。Vertica 内部进程(例如 Tuple Mover刷新操作)以及 DDL 操作始终以 SERIALIZABLE 隔离级别运行以确保一致性。

Vertica 查询解析器支持标准 ANSI SQL-92 隔离级别,如下所示:

  • READ COMMITTED(默认值)

  • READ UNCOMMITTED:自动解释为 READ COMMITTED。

  • REPEATABLE READ:自动解释为 SERIALIZABLE

  • SERIALIZABLE

事务隔离级别 READ COMMITTED 与 SERIALIZABLE 的区别如下:

您可以为数据库和各个事务设置单独的隔离级别

实现详细信息

Vertica 支持具有标准 ACID 属性的传统 SQL 事务:

  • ANSI SQL 92 风格隐式事务。您无需运行 BEGIN 或 START TRANSACTION 命令。

  • 没有重做/撤消日志或两阶段提交。

  • COPY 命令会自动提交自身及所有当前事务(加载临时表时除外)。一般来说,在使用 COPY 之前提交或回退当前事务是一种很好的做法。此步骤对 DDL 语句来说是可选的,因为此类语句会自动提交。

1 - 回退

事务回退通过放弃该事务所做的更改将数据库还原到先前的状态。语句级回退仅放弃已还原的语句所启动的更改。事务级回退放弃该事务所做的所有更改。

使用 ROLLBACK 语句,您可以明确回退到事务内的给定保存点,或者放弃整个事务。在以下两种情况下,Vertica 还可以启动自动回退:

  • 单个语句返回 ERROR 消息。这种情况下,Vertica 会回退该语句。

  • DDL 错误、系统故障、死锁和资源约束返回 ROLLBACK 消息。这种情况下,Vertica 会回退整个事务。

明确回退和自动回退始终会释放该事务持有的任何锁定。

2 - 保存点

保存点是事务内的一个特殊标记,允许在回退该保存点之后执行命令。事务恢复到该保存点之前的状态。

Vertica 支持以下两种类型的保存点:

  • 隐式保存点是在事务内成功执行每个命令之后自动建立的。此保存点用于回退下一个语句(如果该语句返回一个错误)。事务会保留一个隐式保存点,该保存点会通过每个成功的语句向前滚动。隐式保存点只能用于 Vertica,不能被直接引用。

  • 给定保存点是您通过 SAVEPOINT 语句在事务内设置的带标签的标记。随后可以通过 RELEASE SAVEPOINT(销毁保存点)和 ROLLBACK TO SAVEPOINT(回退在该保存点之后执行的所有操作)在同一事务中引用某个给定保存点。给定保存点在嵌套事务中尤为有用:可根据需要整体回退以某个保存点开始的嵌套事务。

3 - READ COMMITTED 隔离

使用隔离级别 READ COMMITTED 时,一个 SELECT 查询会获取在事务开始时已提交的数据的备份。在当前事务期间内执行的后续查询也会查看已在同一个事务内执行的未提交更新的结果。

使用 DML 语句时,您的查询会获取写入锁,以防止其他 READ COMMITTED 事务修改相同的数据。但是,需要注意的是,SELECT 语句不会获取锁,因此并发事务可以获得对相同所选内容的读取和写入访问权限。

READ COMMITTED 是默认隔离级别。对大多数查询来说,此隔离级别可在数据库一致性和并发性之间取得平衡。但是,此隔离级别允许在一个事务正在访问数据期间,另一个事务仍可更改这些数据。此类更改会产生 不可重复的读取虚拟读取。您的应用程序可能有着复杂的查询和更新要求,需要获得更一致的数据库视图。如果是这样,请改用 SERIALIZABLE 隔离

下图说明了 READ COMMITTED 隔离如何控制并发事务读取和写入相同数据:

READ COMMITTED 隔离会在事务结束之前保持独占写入锁,如下图所示:

另请参阅

4 - SERIALIZABLE 隔离

SERIALIZABLE 是最严格的 SQL 事务隔离级别。尽管此隔离级别允许事务并发运行,但在它的影响下,事务实际上会按序列顺序运行。事务会为读取和写入操作获取锁。因此,一个事务内的连续 SELECT 命令始终会产生相同的结果。由于 SERIALIZABLE 隔离提供了一致的数据视图,它对要求复杂查询和更新的应用程序十分有用。但是,可序列化隔离会降低并发性。例如,它会在批量加载期间禁止执行查询操作。

SERIALIZABLE 隔离会建立以下锁:

  • 表级别读取锁:Vertica 会在所选表上获取表级别读取锁,并在事务结束时释放这些锁。此行为可防止在一个事务读取行期间,另一个事务修改行。

  • 表级别写入锁:Vertica 会在更新时获取表级别写入锁,并在事务结束时释放这些锁。此行为可防止在一个事务对行的更改尚未提交时,另一个事务读取这些行更改。

在事务开始时,SELECT 语句会获取所选内容中已提交数据的备份。事务也会查看在事务内运行的更新操作的结果,然后再提交这些更新。

下图显示了都具有 SERIALIZABLE 隔离级别的并发事务如何处理锁定:

使用 SERIALIZABLE 的应用程序必须准备好在序列化失败后重试事务。此类失败通常是由于死锁导致的。死锁发生时,等待锁的所有事务都会在 5 分钟后自动超时。下图显示了死锁的发生方式以及 Vertica 如何处理死锁:

另请参阅 Vertica