加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Oracle事务隔离

发布时间:2020-12-12 16:26:25 所属栏目:百科 来源:网络整理
导读:我有一个SaveApp()方法,它将停用现有记录并插入一个新记录. void SaveApp(int appID){ begin transaction; update; insert; commit transaction;} 假设在数据库表SalesApp中,我有2条appID等于123的记录; 记录1,appID 123,不活动 记录2,活跃 如果我同时在两个
我有一个SaveApp()方法,它将停用现有记录并插入一个新记录.
void SaveApp(int appID)
{
   begin transaction;
   update;
   insert;
   commit transaction;
}

假设在数据库表SalesApp中,我有2条appID等于123的记录;

>记录1,appID 123,不活动
>记录2,活跃

如果我同时在两个线程中调用此方法SaveApp(),第一个事务(让我们称之为T1)将更新现有的两个记录,而第二个事务(让我们称之为T2)等待.

T1完成后,此表中将有三条记录.但是,不知何故T2不知道新插入的记录,T2中的更新查询只更新前两个记录,并插入第四个记录.

在这两个方法调用之后,在数据库中,我们现在将有4条记录,第3条和第4条都是活动的,这是错误的.

>记录1,不活动
>记录3,活跃
>记录4,活跃

你知道任何解决方案都可以解决这个问题吗?我尝试使用隔离级别序列化,但不起作用.

谢谢!

您是否有另一个表,每个AppId占一行,通过唯一或主键约束强制执行?如果是这样,请在父表上使用select for update来序列化每个AppId的访问权限.

创建表:

session_1> create table parent (AppId number primary key);

Table created.

session_1> create table child (AppId number not null references Parent(AppId)
  2,status varchar2(1) not null check (status in ('A','I'))
  3,InsertedAt date not null)
  4  /

Table created.

插入起始值:

session_1> insert into Parent values (123);

1 row created.

session_1> insert into child values (123,'I',sysdate);

1 row created.

session_1> insert into child values (123,'A',sysdate);

1 row created.

session_1> commit;

Commit complete.

开始第一笔交易:

session_1> select AppId from Parent where AppId = 123 for update;

     APPID
----------
       123

session_1> update Child set Status = 'I' where AppId = 123 and Status = 'A';

1 row updated.

session_1> insert into child values (123,sysdate);

1 row created.

在提交之前,在第二个会话中,确保我们只看到第一行:

session_2> select * from Child;

     APPID S INSERTEDAT
---------- - -------------------
       123 I 2010-08-16 18:07:17
       123 A 2010-08-16 18:07:23

开始第二笔交易:

session_2> select AppId from Parent where AppId = 123 for update;

会话2现在被阻止,等待会话1.并且不会继续.
提交会话1将取消阻止会话

session_1> commit;

Commit complete.

第2节我们现在看到:

APPID
----------
       123

完成第二笔交易:

session_2> update Child set Status = 'I' where AppId = 123 and Status = 'A';

1 row updated.

session_2> insert into child values (123,sysdate);

1 row created.

session_2> commit;

Commit complete.

session_2> select * from Child;

     APPID S INSERTEDAT
---------- - -------------------
       123 I 2010-08-16 18:07:17
       123 I 2010-08-16 18:07:23
       123 I 2010-08-16 18:08:08
       123 A 2010-08-16 18:13:51

编辑技术来自Thomas Kyte的专家Oracle数据库架构第二版,第23-24页. http://www.amazon.com/Expert-Oracle-Database-Architecture-Programming/dp/1430229462/ref=sr_1_2?ie=UTF8&s=books&qid=1282061675&sr=8-2

编辑2我还建议实施Patrick Merchand对此问题的答案,以获得一个约束,该约束强制执行A??ppId只能有一个活动记录的规则.因此,最终解决方案将包含两个部分,即如何以获得所需内容的方式进行更新的答案,以及Patrick确保表符合保护数据完整性的要求.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读