Oracle 12c - 我们可以在将数据插入表而不是整个表时锁定分区吗?

时间:2017-10-24 17:25:44

标签: sql oracle parallel-processing informatica

需要从Informatica并行运行2个作业,以便将数据并行插入Oracle中的同一个表。

一个进程将插入一个分区,其他进程将插入另一个分区。

默认情况下oracle如何做?它是否锁定整个Oracle表,以便没有2个并行进程可以从Informatica插入数据,或者它只能锁定一个表的分区而另一个进程可以并行运行并插入另一个分区?

感谢。

2 个答案:

答案 0 :(得分:1)

@OldProgrammer提供了极好的参考。插入Oracle时无需担心表锁。 Oracle默认执行的唯一锁定是插入,更新或删除的行,以及在DML操作正在进行时阻止DDL操作的锁定。

答案 1 :(得分:1)

使用普通的旧插入,两个语句不会相互阻塞。

  1. Oracle使用行级锁定,不会随机将它们升级为表锁。由于INSERT按定义创建新行,因此无法相互阻塞。
  2. 该规则有一些奇怪的例外。例如,如果表具有更改其他行的触发器,或者两个INSERT尝试使用相同的主键值。但这两种情况都极不可能,并且可能是一个你不想要运行的意外错误。位图索引不是为并发DML设计的,也可能导致常规插入阻塞。

    使用直接路径写入或并行插入,答案更复杂。

    并行处理和直接路径写入使事情变得更加复杂。

    1. 如果INSERT操作使用并行性或直接路径写入,则即使添加一行也会锁定整个表并阻止其他会话更改任何内容。例如,如果它生成insert /*+ parallel(8) */ ...之类的语句,它们将阻止任何其他DML运行。这是因为直接路径写入直接修改数据文件以获得最佳性能,而典型的并发控制不起作用。
    2. 但Informatica可能不会使用Oracle的并行处理,而是为本地并行处理创建多个并发线程。如果是这种情况,则两个进程不会相互阻塞。
    3. 但Informatica也可能不使用Oracle并行处理,但 使用直接路径写入。例如,如果它生成insert /*+ append */ ...之类的语句,它们将阻止任何其他DML运行,即使该DML正在修改不同的分区。这可能是因为Oracle无法轻易预测哪个分区会提前修改,而且只需将它们全部锁定就更容易了。
    4. 但是如果明确指定了分区,则只要它们修改不同的分区,就可以并行运行两个并行或直接路径写入
    5. 以下是一个快速演示。首先,使用分区表创建一个简单的测试模式。

      create table test1(a number)
      partition by list(a)
      (
          partition p1 values (1),
          partition p2 values (2)
      ) nologging;
      

      证明一个会话中的直接路径写入将阻止另一个会话中的任何类型的插入:

      --Session 1: Run this statement but don't commit.  It should finish in less than a second.
      insert /*+ append */ into test1 select 1 from dual;
      
      --Session 2: Run this statement but it will never finish, even though it
      --           inserts into a different partition.
      insert into test1 select 2 from dual;
      

      证明只要明确命名分区,一个会话中的直接路径写入不会阻止另一个会话:

      --Session 1: Run this statement but don't commit.  It should run in less than a second.
      insert /*+ append */ into test1 partition (p1) select 1 from dual;
      
      --Session 2: This statement will run immediately.
      insert into test1 partition (p2) select 2 from dual;
      

      现在是什么?

      根据Informatica的配置方式,上述任何一种情况都是可能的。首先检查Informatica设置。

      查看生成的SQL以查看Informatica正在运行的内容。使用select * from gv$sql where sql_fulltext like '...等查询。

      查看这些SQL语句的解释计划,以查看查询是否也按照您希望的方式运行。使用select * from table(dbms_xplan.display_cursor(sql_id => '...之类的查询来查找计划。查看操作列; LOAD AS SELECT表示正在使用直接路径,LOAD TABLE CONVENTIONAL表示不使用直接路径。您还可以检查PARALLELPX以查看是否使用了Oracle并行处理。

      不幸的是,有许多原因可能会要求直接路径或并行性但未使用。请参阅我令人沮丧的长列表,列出缺乏并行性的可能原因here,并查看this list缺少直接路径写入的原因。