Oracle-如何防止多个进程更新同一行?

时间:2018-08-16 17:13:09

标签: database oracle data-loss

在Oracle中,有没有一种方法可以让数据库行在读取另一个进程的同时被“锁定”?我遇到的一个问题是,有时如果两个进程尝试访问同一数据库行并同时对其进行更新,则其中的更新之一可能会丢失。

这是发生的事情的基本时间图。

Process #1              Process #2
------------------      ------------------
Read from Database
Some processing...      Read from database
Some processing...      Some processing...
Update database         Some processing...
                        Update database

在上面的示例中,进程#1的更新丢失,因为进程#2在进程#2完成更新之前从数据库中读取。

我已经修改了代码(在C ++中,但是我不确定这个问题是否真的很重要),以最大程度地减少读取数据库和写入数据库之间的处理量(例如,从数据库读取)。数据库在最可能的时间进行,仅执行所需的确切数量的处理,然后立即进行更新),这有助于缓解此问题,但仍不能保证它是防弹修复。

我可以修改代码,以使进程2仅告诉进程1更新数据库的内容,并让进程1处理与数据库的所有交互,但是不幸的是,在我的情况下,我有数十个进程和数据库表正在处理,因此我不确定这样的更改是否可行。

数据库中是否可以做任何事情来防止此问题的发生?

2 个答案:

答案 0 :(得分:1)

您可以使用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

窗口1:

readlines()

窗口2:

SQL> SET TRANSACTION ISOLATION
  2  LEVEL SERIALIZABLE;

Transaction set.

窗口1:

SQL> SET TRANSACTION ISOLATION
  2  LEVEL SERIALIZABLE;

Transaction set.

窗口2:

SQL> select * from test;

no rows selected

SQL> insert into test values (1);

1 row created.

SQL> commit;

Commit complete.

即使您在窗口1中插入了一行并提交了它,在窗口2中也看不到它。隔离级别可序列化是有风险的,因为它可能导致很多不良的锁定。

答案 1 :(得分:1)

您可以在查询中使用FOR UPDATE子句。

有关此子句的更多详细信息,请参见以下链接:https://www.techonthenet.com/oracle/cursors/for_update.php

还要在问题下方检查此问题,以获取一些使用FOR UPDATE的示例代码。

链接: How to use Oracle DB sequences without losing the next sequence number in case of roll-back