【问题标题】:Bulk insert into partitioned table and table level lock批量插入分区表和表级锁
【发布时间】:2013-05-04 20:23:51
【问题描述】:

我想知道为什么批量插入(使用直接路径)锁定整个表的核心原因(引擎所做的段、块、锁的机制),所以如果我插入到分区中,我不能截断另一个不受插入影响(显然)的分区。

传统的插入(没有附加提示)允许截断一些不受影响的分区。(注意我说的是非提交事务。)

下面是一个例子来说明它。

让我们成为一张桌子:

 CREATE TABLE FG_TEST 
   (COL NUMBER ) 
  PARTITION BY RANGE (COL) 
 (PARTITION "P1"  VALUES LESS THAN (1000), 
  PARTITION "P2"  VALUES LESS THAN (2000));

Insert into table fg_test values (1);
insert into table fg_test values (1000);
commit;

第 1 节:

insert into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;

第 2 节:

alter table fg_test truncate partition p1;
--table truncated

第 1 节:

rollback;
insert /*+append */ into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;

第 2 节:

alter table fg_test truncate partition p1;
--this throws ORA-00054: resource busy and acquire with NOWAIT specified 
--or timeout expired

Doc on Diret-Path Insert 在这个问题上非常突然,只是说:

在直接路径插入期间,数据库获得排他锁 表(或分区表的所有分区)。因此, 用户不能执行任何并发插入、更新或删除 对表的操作,以及并发索引的创建和构建 不允许操作。

How Direct-Path INSERT Works 没有解释为什么所有分区都需要锁。 为什么传统的插入不会锁定不受影响的分区? (我的直觉是锁是在块级完成的)

【问题讨论】:

  • 行级别的常规插入锁,表定义也受共享锁保护以防止其被修改。 Oracle 中没有任何块级锁,都是行、(子)分区或表级别的。

标签: sql oracle locking bulkinsert


【解决方案1】:

我在 asktom.oracle.com 上找到了以下答案:

Ask Tom: Inserts with APPEND Hint

Tom 解释了许多内部工作原理,但为什么Oracle 锁定整个表而不仅仅是受影响的分区的原因仍然不清楚。

也许这只是一个设计决策(例如,不希望庞大的直接负载可能被一个未提交的小型事务阻塞并因此锁定所有分区......)

【讨论】:

    【解决方案2】:

    你的前提有点错误。如果使用分区扩展子句,直接路径插入不会锁定整个表。

    第 1 节:

    insert /*+append */ into fg_test partition (p2)
    select * from fg_test where col >=1000;
    

    第 2 节:

    alter table fg_test truncate partition p1;
    --table truncated
    

    新问题是:当不使用分区扩展子句时,为什么传统插入和直接路径插入有不同的锁定机制?这种澄清使问题变得更容易,但在没有内部知识的情况下答案下面仍然只是一个猜测。


    编写锁定整个表格的功能更容易。而且它运行得更快,因为不需要跟踪更新了哪些分区。

    通常不需要更细粒度的锁。大多数使用直接路径写入的系统或进程一次只更新一个大表。如果确实需要更细粒度的锁,可以使用分区扩展子句。这不太方便,因为一次只能引用一个分区。但这在 99.9% 的情况下已经足够了。

    【讨论】:

    • @JonHeller 因此,如果我使用直接路径插入到使用分区扩展的表中,则该分区仍将被锁定在该会话中,直到发出 COMMIT。那是对的吗?我什至不确定“分区锁定”是否是一回事,请原谅我的无知。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 2012-06-21
    • 2019-07-29
    相关资源
    最近更新 更多