数据库插入机制

时间:2012-02-12 19:00:27

标签: sql oracle oracle10g

关于不同数据库中的插入机制,我有一个问题。假设一个表具有自动生成的单列主键(如标识列),插入新记录时整个表是否会被锁定?如果插入花费太多时间,其他交易是否还要等待更多?

3 个答案:

答案 0 :(得分:3)

插入不会锁定表格。在您提交之前,插入的记录对其他会话不可见。

答案 1 :(得分:3)

您的问题与您插入具有任何唯一约束的表格的任何情况相关。如果没有索引,并且在表中插入一行,则您希望数据库需要锁定整个表 - 否则可能会在多用户系统中插入重复项。

但是,Oracle始终使用索引来限制唯一约束。这意味着列的数据始终排序,并且可以快速轻松地确定是否已存在冲突行。为了防止尝试同时插入相同值的多个会话,Oracle将仅锁定该值的索引中的块 - 这样,您将不会争用整个表,仅针对特定值'插入。由于索引查找通常非常快,因此只需要在非常短的时间内保持锁定。

(但是现在,你可能会问,如果一个会话插入一个值但是没有立即提交怎么办?如果另一个会话试图插入相同的值怎么办?答案是,第二个会话将等待。这是因为它将在同一索引块上请求锁定,但由于第一个会话尚未提交,该块仍将被锁定。它必须等待,因为它无法知道第一个会话是提交还是回滚。)

答案 2 :(得分:3)

默认情况下,Oracle使用行级锁。

这些锁仅针对编写器阻塞(更新,删除,插入等)。这意味着当表格大量更新,删除等时,select将一直有效。

例如,设为tableA(col1编号,col2编号),其中包含此数据:

col1  |  col2
1     |  10
2     |  20
3     |  30

如果用户John在time1处发布:

update tableA set col2=11 where col1=1;

将锁定row1。

time2用户标记处发出

update tableA set col2=22 where col1=2;

更新将起作用,因为第2行未锁定。

现在该表在数据库中查找:

col1  |  col2
1     |  11   --locked by john
2     |  22   --locked by mark  
3     |  30

对于Mark表是(他没有看到未经修改的变化)

col1  |  col2
1     |  10   
2     |  22   
3     |  30

对于John表是:(他没有看到未经修改的变化)

col1  |  col2
1     |  11   
2     |  20   
3     |  30

如果标记尝试time3

update tableA set col2=12 where col1=1;

当John发出time4时,他的会话将一直持续到commit。(回滚也会解锁行,但更改将会丢失)

表是(在db中,在时间4):

col1  |  col2
1     |  11   
2     |  22   --locked by mark  
3     |  30

Immediatley,在John的提交之后,row1被解锁并且标记的更新将完成这项工作:

col1  |  col2
1     |  12   --locked by mark  
2     |  22   --locked by mark  
3     |  30

让我们在time5标记一个rollbak:

col1  |  col2
1     |  11   
2     |  20   
3     |  30

插入案例更简单,因为插入的行被锁定,但其他用户也看不到它们,因为它们未被提交。当用户提交时,他也会释放锁,因此,其他用户可以查看这些行,更新它们或删除它们。

编辑:正如Jeffrey Kemp解释的那样,当你有PK(它在Oracle中使用唯一索引实现)时,如果用户试图插入相同的值(那么,我们会有重复),锁定将在索引中发生。第二个会话将被阻止,直到第一个会话结束,因为它尝试在同一个地方写入。如果第一个会话提交,第二个会抛出主键违反异常,将无法更改数据库。如果第一个会话执行回滚,则第二个会话将成功(如果没有出现其他问题)。

(注意:在用户John的解释中,我指的是用户John开始的会话。)