批量插入分区表和表级锁定

Flo*_*ita 7 sql oracle locking bulkinsert

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

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

下面举例说明它.

让我们成为一张桌子:

 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;
Run Code Online (Sandbox Code Playgroud)

第一节:

insert into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
Run Code Online (Sandbox Code Playgroud)

第二节:

alter table fg_test truncate partition p1;
--table truncated
Run Code Online (Sandbox Code Playgroud)

第一节:

rollback;
insert /*+append */ into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
Run Code Online (Sandbox Code Playgroud)

第二节:

alter table fg_test truncate partition p1;
--this throws ORA-00054: resource busy and acquire with NOWAIT specified 
--or timeout expired
Run Code Online (Sandbox Code Playgroud)

关于Diret-Path InsertDoc在这个主题上是非常突然的,只是说:

在直接路径INSERT期间,数据库获取表(或分区表的所有分区)上的独占锁.因此,用户无法对表执行任何并发插入,更新或删除操作,并且不允许并发索引创建和构建操作.

如何直接路径INSERT作品并不能解释为什么需要对所有分区的锁.为什么传统插件不能锁定不受影响的分区?(我的直觉是锁是在块级完成的)

Jon*_*ler 6

你的前提稍有不妥.如果使用分区扩展子句,则直接路径插入不会锁定整个表.

第一节:

insert /*+append */ into fg_test partition (p2)
select * from fg_test where col >=1000;
Run Code Online (Sandbox Code Playgroud)

第二节:

alter table fg_test truncate partition p1;
--table truncated
Run Code Online (Sandbox Code Playgroud)

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


编写锁定整个表的功能更容易.并且运行速度更快,因为无需跟踪更新的分区.

通常不需要更细粒度的锁.大多数使用直接路径写入的系统或进程一次只更新一个大表.如果确实需要更细粒度的锁,则可以使用分区扩展子句.它不太方便,因为一次只能引用一个分区.但它有99.9%的时间足够好.