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

SAP Sybase SQL Anywhere 16.0 (中文) » SQL Anywhere 服务器 - SQL 用法 » 事务和隔离级别 » 隔离级别教程 » 教程:了解非可重复读取

 

第 1 课:创建非可重复读取

创建非可重复读取,即会计尝试读取一个正在由销售经理进行修改的行,因此在同一事务中得到了两个不同的结果。

前提条件

本课假定您拥有在教程教程:了解非可重复读取开头的特权部分中列出的角色和特权。

 任务
  1. 执行以下语句,将会计的连接隔离级别设置为 1:

    SET TEMPORARY OPTION isolation_level = 1;
  2. 在销售经理的窗口中执行以下语句,将隔离级别设置为 1:

    SET TEMPORARY OPTION isolation_level = 1;
  3. 会计执行以下语句,列出太阳帽的价格:

    SELECT ID, Name, UnitPrice 
    FROM GROUPO.Products;
    ID Name UnitPrice
    300 Tee Shirt 9.00
    301 Tee Shirt 14.00
    302 Tee Shirt 14.00
    400 Baseball Cap 9.00
    401 Baseball Cap 10.00
    500 Visor 7.00
    501 Visor 7.00
    ... ... ...
  4. 销售经理执行以下语句,为塑料太阳帽定一个新的销售价格:

    SELECT ID, Name, UnitPrice FROM GROUPO.Products
    WHERE Name = 'Visor';
    UPDATE GROUPO.Products
    SET UnitPrice = 5.95 WHERE ID = 501;
    COMMIT;
    SELECT ID, Name, UnitPrice FROM GROUPO.Products
    WHERE Name = 'Visor';
    ID Name UnitPrice
    500 Visor 7.00
    501 Visor 5.95
  5. 比较 [Sales Manager] 窗口中太阳帽的价格和 [Accountant] 窗口中相同太阳帽的价格。会计再次执行 SELECT 语句,并查看销售经理的新销售价格:

    SELECT ID, Name, UnitPrice
    FROM GROUPO.Products;
    ID Name UnitPrice
    300 Tee Shirt 9.00
    301 Tee Shirt 14.00
    302 Tee Shirt 14.00
    400 Baseball Cap 9.00
    401 Baseball Cap 10.00
    500 Visor 7.00
    501 Visor 5.95
    ... ... ...

    这种不一致被称作非可重复读取,因为在同一事务 中再次执行相同的 SELECT 命令后,会计不会得到相同的结果。

    当然,如果会计已经完成了该事务,例如,在再次使用 SELECT 之前发出了 COMMIT 或 ROLLBACK 语句,情况则有所不同。该数据库可供多个用户同时使用,而且完全允许某人在会计执行事务之前或之后更改值。结果中的变化仅仅因为发生在执行其事务的过程中才不一致。这种情况将导致调度不可序列化。

  6. 会计注意到了这种情况,并决定从现在开始不希望看到价格发生更改。隔离级别 2 消除了非可重复读取。作为会计,执行以下语句:

    SET TEMPORARY OPTION isolation_level = 2;
    SELECT ID, Name, UnitPrice
    FROM GROUPO.Products;
  7. 销售经理决定最好将塑料太阳帽的销售推迟到下个星期,这样,她就不必为预计明天会收到的一个大订单报那个较低的价格。销售经理尝试执行以下语句。该语句开始执行,然后窗口会呈现冻结状态。

    UPDATE GROUPO.Products
    SET UnitPrice = 7.00
    WHERE ID = 501;

    数据库服务器在隔离级别 2 上必须确保可重复读取。由于会计正在使用隔离级别 2,因此数据库服务器在会计读取的 Products 表的每一行上都放置一个读锁定。当销售经理尝试将价格更改回原来的值时,她的事务必须在 Products 表中包含塑料太阳帽的那一行上获取一个写锁定。由于写锁定是独占的,因此她的事务必须等到会计的事务释放其读锁定后才能继续执行。

  8. 会计查看完价格后,由于他不希望无意中更改了数据库,因此使用 ROLLBACK 语句完成他的事务。

    ROLLBACK;

    数据库服务器执行该语句后,销售经理的事务完成。

    ID Name UnitPrice
    500 Visor 7.00
    501 Visor 7.00
  9. 销售经理现在就可以完成事务了。她希望提交她所做的更改,恢复到原来的价格:

    COMMIT;

结果

会计在同一事务中收到不同的结果,因此,他启用快照隔离级别 2 来避免非可重复读取。但是,会计对数据库进行的更改会阻止销售经理对数据库进行任何更改。

将会计的隔离级别从级别 1 升级到级别 2 后,数据库服务器将在以前未获取任何锁定的位置上使用读锁定。从这时开始,数据库服务器将在符合会计的选择条件的每一行上为他的事务获取一个读锁定。

在上面的教程中,销售经理的窗口在执行 UPDATE 语句时被冻结。数据库服务器开始执行她的语句,之后发现会计的事务已在销售经理需要更改的行上获取了一个读锁定。这时,数据库服务器只是暂停该 UPDATE 命令的执行。在会计使用 ROLLBACK 完成了他的事务之后,数据库服务器自动释放了他的锁定。发现不再有任何阻碍后,数据库服务器会执行完销售经理的 UPDATE 命令。

 另请参见