这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
事务
多个用户会话中的
事务并发访问相同数据时,会话范围的隔离级别决定了每个事务可访问哪些数据。
事务将保留其隔离级别直至其完成,即使在事务处理期间会话的隔离级别发生更改也是如此。Vertica 内部进程(例如
Tuple Mover 和
刷新操作)以及 DDL 操作始终以 SERIALIZABLE 隔离级别运行以确保一致性。
Vertica 查询解析器支持标准 ANSI SQL-92 隔离级别,如下所示:
事务隔离级别 READ COMMITTED 与 SERIALIZABLE 的区别如下:
您可以为数据库和各个事务设置单独的隔离级别。
实现详细信息
Vertica 支持具有标准 ACID 属性的传统 SQL 事务:
1 - 回退
事务回退通过放弃该事务所做的更改将数据库还原到先前的状态。语句级回退仅放弃已还原的语句所启动的更改。事务级回退放弃该事务所做的所有更改。
使用 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
隔离会建立以下锁:
在事务开始时,SELECT
语句会获取所选内容中已提交数据的备份。事务也会查看在事务内运行的更新操作的结果,然后再提交这些更新。
下图显示了都具有 SERIALIZABLE
隔离级别的并发事务如何处理锁定:
使用 SERIALIZABLE
的应用程序必须准备好在序列化失败后重试事务。此类失败通常是由于死锁导致的。死锁发生时,等待锁的所有事务都会在 5 分钟后自动超时。下图显示了死锁的发生方式以及 Vertica 如何处理死锁:
注意
SERIALIZABLE
隔离不会应用于临时表。这些表不需要锁,因为它们被隔离在各自的事务范围内。
另请参阅 Vertica