Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以使用哪种侵入性最小的锁定机制来防止在Oracle表中插入行?_Oracle_Stored Procedures_Locking - Fatal编程技术网

我可以使用哪种侵入性最小的锁定机制来防止在Oracle表中插入行?

我可以使用哪种侵入性最小的锁定机制来防止在Oracle表中插入行?,oracle,stored-procedures,locking,Oracle,Stored Procedures,Locking,我定义了一个父/子关系,不幸的是,它不能通过外键维护。父项和子项存储在同一个表中。父/子关系由“ITEM_ID”列标识。子项_ID由其父项_ID组成,然后是我们可以有效地认为是该父项中子项的唯一标识符 我正在实现一个PL/SQL过程来删除此项表中的记录。程序的第一部分检查是否存在任何儿童;如果是,则会引发应用程序错误(模拟外键) 我想知道在我的delete过程中的游标被填充并锁定为“FOR UPDATE”和父记录被实际删除之间,如何防止子记录被另一个进程插入 在此过程中是否需要锁定整个表 或者我

我定义了一个父/子关系,不幸的是,它不能通过外键维护。父项和子项存储在同一个表中。父/子关系由“ITEM_ID”列标识。子项_ID由其父项_ID组成,然后是我们可以有效地认为是该父项中子项的唯一标识符

我正在实现一个PL/SQL过程来删除此项表中的记录。程序的第一部分检查是否存在任何儿童;如果是,则会引发应用程序错误(模拟外键)

我想知道在我的delete过程中的游标被填充并锁定为“FOR UPDATE”和父记录被实际删除之间,如何防止子记录被另一个进程插入

在此过程中是否需要锁定整个表

或者我应该更改插入过程以选择父记录“进行更新”吗

更新:我创建上述示例只是为了描述一般情况,但为了证明外键/约束问题的合理性,我将在下面给出我的实际/更复杂的结构:

远程数据库中有几个表:公司、大楼、楼层。在我们的组织中,楼层属于建筑物,建筑物属于公司

我正在使用的应用程序将角色与员工关联。将员工(员工ID)与角色(角色ID)关联的表也有一个“位置”列。location列对应于一个远程数据库表的ID,我们根据Role表中的Type列确定它属于哪个表

例如,以下是我表格中的几条记录:

Role = Janitor
Type = BUILDING
Location = COMPANY1-BUILDING1
Parent Role = Manager


Role = Manager
Type = COMPANY
Location = COMPANY1
Parent Role = CEO
正如您所猜测的,楼层标识符在远程数据库表中具有公司大楼楼层的格式


门卫绑定到建筑层,因此其位置列是建筑标识符(实际上是公司标识符,后跟建筑表中的建筑标识符)。

您需要在插入子项时锁定父记录,以便其他用户在提交之前无法删除父项


我很好奇,为什么你说这不能通过外键约束来实现?

让删除过程对父记录进行普通锁定不会阻止插入子记录。锁定整个表将严重序列化应用程序


因此,强制插入过程选择。。。对于父记录的更新,锁定父记录的删除过程是您唯一的选择。这种实现的主要问题是很容易绕过事件。换句话说,每个与表交互的进程都必须发出这些额外的锁

如APC所述,数据模型似乎存在问题。对此类继承人数据建模的正确方法是:

key_field            [data_type] primary key
parent_key_field     [data_type] null foreign key references key_field
这里的序列化问题是为什么应该使用外键映射这些关系

也就是说,如果使用SELECT FOR UPDATE在表中打开光标,它应该以独占方式锁定要删除的行。您不能阻止某人在“外键”中“引用”该表,因为ITEM_ID只是另一个值

可能有效的方法是嵌入以下内容:

procedure delete_me (p_item_key)
as
  l_child_count number;
begin
  -- verify the value being deleted exists and has no children as you already do

  delete from tbl a
   where not exists (select null
                       from tbl b
                      where b.item_id = a.item_id)
  if sql%rowcount = 0 then
    -- your delete failed; raise an error.
  end if;
end;

强化APC关于改变每一个过程的评论,这里是一个复杂的问题

防止子记录被删除 由另一个进程插入 光标在“我的删除”中的时间 程序已填充并锁定“用于” 更新”,以及 父记录实际上已被删除

请记住,当您尝试锁定父记录时,子记录可能已插入(但未提交)。除非插入子记录的过程也在父记录上使用独占锁(防止删除操作获得锁),否则它将无法工作。由于一次只能有一个事务在一行上具有独占锁,因此这将序列化插入


您面临的问题是,通过序列化父项下的插入,还是在删除事务期间锁定整个表,您对应用程序的影响会更大。如果您的删除很少且事务很快,我会选择表锁作为最简单的实现。

像Tony一样,我很想知道为什么您不能强制执行外键约束?有关更多详细信息,请参阅我的问题更新。问题是数据的位置和公司维度是如何合并的(以关键值为导向)键入。实际关系应该映射到角色“在”位置工作和角色“为”公司工作的位置,其中一个或两个关系可能被要求是强制性的。或者员工“在”位置工作,而不管员工“履行”角色。>>我很好奇,为什么你说外键约束不能实现这一点?我想这对我的应用程序来说是可行的。我有一个插入新记录的函数和一个删除记录的函数。