并发问题

要理解并发的危险性,您必须从多个程序的方面考虑,每一程序以它自己的速度执行。 假设您的程序通过下列游标正在访存行:
EXEC SQL DECLARE sto_curse CURSOR FOR
          SELECT * FROM stock
          WHERE manu_code = 'ANZ';
将每一行从数据库服务器传送到程序都花费时间。在传送期间和传送之间,其他程序可执行其他数据块操作。大约在您的程序访存由那个查询产生的行的同一时刻,另一用户的程序可能执行下列更新:
EXEC SQL UPDATE stock
          SET unit_price = 1.15 * unit_price
          WHERE manu_code = 'ANZ';
换句话说,两个程序都在通读同一个表,一个正在访存某些行,而另一个正在更改相同的行。可能出现下列情况:
  1. 在您的程序访存它的第一行之前,其他程序完成了它的更新。

    您的程序仅向您显示更新了的行。

  2. 在其他程序有机会更新它之前,您的程序访存了每行。

    您的程序仅向您显示原始的行。

  3. 在您的程序访存某些原始的行之后,其他程序赶上并继续更新您的程序还要读取的一些行;然后,它执行 COMMIT WORK 语句。

    您的程序可能返回的既有原始的行,也有更新了的行。

  4. 与第 3 种情况一样,除了在更新表之后,另一程序发出 ROLLBACK WORK 语句之外。

    您的程序可向您显示的既有原始的行,也有在数据库中不再存在的更新了的行。

前两种可能性是无害的。在第 1 种可能的情况中,在您的查询开始之前完成了更新。更新是在一毫秒之前结束的,还是一周前结束的,并无差异。

在第 2 种可能的情况中,实际上,您的查询在更新开始之前完成。其他程序可能紧跟在您的程序之后只处理了一行,或它可能直到明晚才开始;这没有关系。

然而,后两种可能的情况对于某些应用程序的设计可至关重要。在第 3 种可能的情况下,查询返回的既有更新了的数据,也有原始数据。在某些应用程序中,那种结果可能是有害的。在其他程序中,诸如计算所有价格的平均值,根本无关紧要。

由于取消了它们的事务,如果程序返回一些在表中不可再找到的数据行,则第 4 种可能的情况是灾难性的。

当您的程序使用游标来更新或删除最后访存的数据时,需要引起另外的关注。下列的事件序列产生错误的结果:
  • 您的程序访存该行。
  • 另一程序更新或删除该行。
  • 您的程序更新或删除 WHERE CURRENT OF cursor_name

要控制诸如此类的事件,请使用数据库服务器的锁定和隔离级别特性。