在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处理与数据库的所有交互,但是不幸的是,在我的情况下,我有数十个进程和数据库表正在处理,因此我不确定这样的更改是否可行。
数据库中是否可以做任何事情来防止此问题的发生?
答案 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