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

SQL Anywhere 12.0.1 » SQL Anywhere 服务器 - SQL 的用法 » 事务和隔离级别 » 隔离级别教程 » 教程:了解非可重复读取

 

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

 ♦ 创建非可重复读取
  1. 启动 Interactive SQL。

  2. 在 [连接] 窗口中,以销售经理的身份连接到 SQL Anywhere 示例数据库:

    1. 在 [操作] 下拉列表中单击 [使用 ODBC 数据源连接]。

    2. 单击 [ODBC 数据源名称],然后在下方的字段中键入 SQL Anywhere 12 Demo

    3. 如有必要,可单击 [高级] 以显示 [高级选项] 选项卡。

    4. 单击 [高级选项] 选项卡,在 [ConnectionName] 字段中键入 Sales Manager

    5. 单击 [连接]。

  3. 再启动一个 Interactive SQL 的实例。

  4. 在 [连接] 窗口中,以会计的身份连接到 SQL Anywhere 示例数据库:

    1. 在 [操作] 下拉列表中单击 [使用 ODBC 数据源连接]。

    2. 单击 [ODBC 数据源名称],然后在下方的字段中键入 SQL Anywhere 12 Demo

    3. 如有必要,可单击 [高级] 以显示 [高级选项] 选项卡。

    4. 单击 [高级选项] 选项卡,在 [ConnectionName] 字段中键入 Accountant

    5. 单击 [连接]。

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

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

    SET TEMPORARY OPTION isolation_level = 1;
  7. 会计决定列出太阳帽的价格。作为会计,执行以下语句:

    SELECT ID, Name, UnitPrice FROM 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
    ... ... ...
  8. 销售经理决定为塑料太阳帽定一个新的销售价格。作为销售经理,执行以下语句:

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

    SELECT ID, Name, UnitPrice
    FROM 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 语句,情况则有所不同。该数据库可供多个用户同时使用,而且完全允许某人在会计执行事务之前或之后更改值。结果中的变化仅仅因为发生在执行其事务的过程中才不一致。这种情况将导致调度不可序列化。

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

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

    UPDATE Products
    SET UnitPrice = 7.00
    WHERE ID = 501;

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

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

    ROLLBACK;

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

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

    COMMIT;
 锁的类型和不同的隔离级别
 事务阻塞
 另请参见