Sql 大容量插入到分区表和表级锁中

Sql 大容量插入到分区表和表级锁中,sql,oracle,locking,bulkinsert,Sql,Oracle,Locking,Bulkinsert,我想知道为什么大容量插入(使用直接路径)会锁定整个表的核心原因(引擎执行的段、块、锁的机制),因此如果我插入一个分区,我就不能截断另一个不受插入影响(显然)的分区 传统的insert(没有append提示)允许截断一些未受影响的分区(注意,我提到的是未提交的事务) 下面是一个例子来说明它 让我们做一张桌子: CREATE TABLE FG_TEST (COL NUMBER ) PARTITION BY RANGE (COL) (PARTITION "P1" VALUES L

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

传统的insert(没有append提示)允许截断一些未受影响的分区(注意,我提到的是未提交的事务)

下面是一个例子来说明它

让我们做一张桌子:

 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;
rollback;
insert /*+append */ into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
insert /*+append */ into fg_test partition (p2)
select * from fg_test where col >=1000;
第2次会议:

alter table fg_test truncate partition p1;
--table truncated
alter table fg_test truncate partition p1;
--this throws ORA-00054: resource busy and acquire with NOWAIT specified 
--or timeout expired
alter table fg_test truncate partition p1;
--table truncated
第1场会议:

insert into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
rollback;
insert /*+append */ into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
insert /*+append */ into fg_test partition (p2)
select * from fg_test where col >=1000;
第2次会议:

alter table fg_test truncate partition p1;
--table truncated
alter table fg_test truncate partition p1;
--this throws ORA-00054: resource busy and acquire with NOWAIT specified 
--or timeout expired
alter table fg_test truncate partition p1;
--table truncated
在这个问题上,他非常唐突,只是说:

在直接路径插入过程中,数据库在 表(或分区表的所有分区上)。因此, 用户不能同时执行任何插入、更新或删除操作 表上的操作,以及并发索引创建和生成 不允许操作

没有解释为什么所有分区都需要锁。
为什么传统的插入不能锁定未受影响的分区?(我的直觉是锁是在块级别完成的)

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

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


也许这只是一个设计决策(例如,不希望庞大的直接负载可能被一个较小的未限制事务阻塞,从而锁定所有分区…

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

第1场会议:

insert into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
rollback;
insert /*+append */ into table fg_test select * from fg_test where col >=1000;
--1 rows inserted;
insert /*+append */ into fg_test partition (p2)
select * from fg_test where col >=1000;
第2次会议:

alter table fg_test truncate partition p1;
--table truncated
alter table fg_test truncate partition p1;
--this throws ORA-00054: resource busy and acquire with NOWAIT specified 
--or timeout expired
alter table fg_test truncate partition p1;
--table truncated
新的问题是:当不使用分区扩展子句时,为什么传统路径插入和直接路径插入具有不同的锁定机制?这一澄清使问题变得更容易,但在没有内部知识的情况下,下面的答案仍然只是猜测


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


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

行级别的传统插入锁,表定义也受到共享锁的保护,以防止被修改。Oracle中没有任何块级锁,都是行、子分区或表级锁。@JonHeller因此,如果我使用分区扩展将直接路径插入到表中,则该分区仍将在该会话中被锁定,直到发出
COMMIT
。对吗?我甚至不确定“分区锁定”是否是一件事,请原谅我的无知。