Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 创建数据库 » 使用事务和隔离级别 » 隔离级别和一致性

 

快照隔离

多个用户同时读取和写入相同数据时,可能发生阻塞和死锁。快照隔离旨在通过维护数据的不同版本提高并发性和一致性。在事务中使用快照隔离时,数据库服务器会返回数据的已提交版本,以响应任何读请求。它在进行此操作时不获取读锁定,因此不会对正在写入数据的用户造成干扰。

快照是数据库中已提交的一组数据。使用快照隔离时,事务中的所有查询都会使用同一组数据。数据库表不会获取任何锁,因此其它事务可以无阻塞地访问并修改数据。SQL Anywhere 支持以下三种快照隔离级别,允许您控制何时使用快照:

  • 快照   从事务读取、插入、更新或删除第一行时开始,使用已提交数据的快照。

  • 语句快照   从语句读取第一行开始,使用已提交数据的快照。事务内的每个语句看到的都是不同时间的数据快照。

  • 只读语句快照   对于只读语句,从读取第一行时开始,使用已提交数据的快照。事务内的每个只读语句看到的都是不同时间的数据快照。对于插入、更新和删除语句,使用由 updatable_statement_isolation 选项指定的隔离级别(可以是 0(缺省值)、1、2 或 3)。

您还可以使用 BEGIN SNAPSHOT 语句,指定何时启动事务的快照。请参见BEGIN SNAPSHOT 语句

快照隔离在许多情况下都很有用,例如:

  • 执行大量读取操作和很少更新操作的应用程序   快照事务仅为那些修改数据库的语句获取写锁定。如果事务主要执行读取操作,则快照事务不会获取可能干扰其他用户的事务的读锁定。

  • 其他用户需要访问数据时执行长时间运行的事务的应用程序   快照事务不获取读锁定,因此快照事务发生时,其他用户可以读取和更新数据。

  • 必须从数据库读取一致的数据集的应用程序   快照显示特定时间点的已提交数据集,因此您可以使用快照隔离来查看在整个事务中未更改的一致数据,即使其他用户在您的事务运行时对数据进行更改。

快照隔离仅影响所有用户共享的基表和全局临时表。对其它表类型的读取操作决不会看到数据的旧版本,且从不启动快照。仅当将 isolation_level 选项设置为快照,且更新启动一个事务时,对其它表类型的更新才启动快照。

当存在使用 WITH HOLD 子句打开的使用语句或事务快照的游标时,以下语句无法执行。

当使用 WITH HOLD 子句打开游标时,可看到在快照启动时所提交的所有行的快照。还可看到从在其内打开游标的事务启动以来,由当前连接完成的所有修改。

仅当未执行快速截断时允许执行 TRUNCATE TABLE,因为在此情况下,单独的 DELETE 操作随后会被记录在事务日志中。请参见TRUNCATE 语句

此外,如果从非快照事务中执行这些语句中的任何语句,则已运行的快照事务在随后尝试使用表时,会返回一条错误,指示模式已更改。

如果视图在事务的快照开始后进行刷新,则实例化视图匹配将避免使用该视图。

所有编程接口都支持快照隔离级别。可以使用 SET OPTION 语句设置隔离级别。有关使用快照隔离的信息,请参见:

行版本

为数据库启用快照隔离后,每次更新行时,数据库服务器会将原始行的副本添加到存储在临时文件内的版本中。原始行版本条目会一直存储,直到可能需要访问原始行值的所有活动的快照事务完成。使用快照隔离的事务只能看到已提交的值,因此,如果在快照事务开始之前未提交或回退对行的更新,则快照事务需要能够访问原始行值。这就允许使用快照隔离的事务在查看数据时,不会在基础表上放置任何锁。

VersionStorePages 数据库属性返回当前用于版本存储的临时文件中的页数。要获得此值,请执行以下查询:

SELECT DB_PROPERTY ( 'VersionStorePages' );

当不再需要旧行版本条目时,会将它们删除。旧版本的 BLOB 会一直存储在原始表(不是临时表)中,直到不再需要它们,旧行版本的索引条目也会一直存储在原始索引中,直到不再需要它们。

可以使用 sa_disk_free_space 系统过程检索临时文件中可用空间的大小。请参见sa_disk_free_space 系统过程

如果触发了更新行值的触发器,则那些行的原始值也会存储在临时文件中。

将应用程序设计成使用更短的事务和更短的快照,会减少临时文件的空间需求。

如果您担心临时文件的增大,则可建立一个 GrowTemp 系统事件,指定临时文件达到特定大小时要采取的操作。请参见了解系统事件

了解快照事务

快照事务在更新时获取写锁定,而使用快照的事务或语句永远不会获取读锁定。因此,读取程序从不阻塞写入程序,写入程序也从不阻塞读取程序,但尝试更新相同的行时,写入程序之间可能会互相阻塞。

请注意,就快照隔离而言,事务不以 BEGIN TRANSACTION 语句开始,而是以事务中的第一个读取、插入、更新或删除操作开始,具体取决于用于事务的快照隔离级别。以下示例说明快照隔离事务何时开始:

SET OPTION PUBLIC.allow_snapshot_isolation = 'On';
         SET TEMPORARY OPTION isolation_level = 'snapshot';
   SELECT * FROM Products; --transaction begins and the statement only 
                           --sees changes that are already committed
   INSERT INTO Products 
         SELECT ID + 30, Name, Description,
         'Extra large', Color, 50, UnitPrice, NULL
         FROM Products
         WHERE Name = 'Tee Shirt';
COMMIT; --transaction ends

启用快照隔离
快照隔离示例
更新冲突和快照隔离