【问题标题】:Partition table get locked for concurrent DML operations in Oracle分区表在 Oracle 中因并发 DML 操作而被锁定
【发布时间】:2017-05-03 00:56:39
【问题描述】:

我在 Oracle 11g 中创建了一个分区表,并尝试使用 Java 批处理作业中的多线程插入记录。 假设我有 10 个线程,并且每个线程都想同时插入/更新 100 万条记录,或者在没有线程的情况下批量插入一段时间,在这两种情况下,我们的表都被 oracle 锁定为同一个会话。如果我们有 10 个线程,那么我们为 1 个同一个表的 10 个会话获得 20 条记录。只有分区或带有子分区表的分区才会发生这种情况。

下面是建表查询

CREATE TABLE "SEG_TEST_SINGLE_PARTITION"
(
"POR_CD"    CHAR(2 CHAR) NOT NULL ENABLE,
"PROD_MNTH" CHAR(6 CHAR) NOT NULL ENABLE,
"INS_DTTM" TIMESTAMP (6)
 )
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE
  (
   BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
  )
  TABLESPACE "a" PARTITION BY LIST
  (
  "POR_CD"
  )
  (
PARTITION "PWKLY_ORDR_POR01" VALUES
(
  '01'
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 8388608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_POR02" VALUES
(
  '02'
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_POR03" VALUES
(
  '03'
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_POR06" VALUES
(
  '06'
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_POR15" VALUES
(
  '15'
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_POR20" VALUES
(
  '20'
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a" ,
PARTITION "PWKLY_ORDR_PORDF" VALUES
(
  DEFAULT
)
SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "a"

) ;

通过下面的查询,我检查了表锁

select    a.INST_ID,a.XIDUSN,a.XIDSLOT,a.XIDSQN,a.OBJECT_ID,b.OBJECT_NAME,a.SESSION_ID,a.ORACLE_USERNAME,a.OS_USER_NAME,a.PROCESS,LOCKED_MODE from
GV$LOCKED_OBJECT a,dba_objects b where a.object_id=b.object_id and     ORACLE_USERNAME like '%ASP01%' order by 8;  


    "INST_ID"   "XIDUSN"    "XIDSLOT"   "XIDSQN"    "OBJECT_ID" "OBJECT_NAME"   "SESSION_ID"    "ORACLE_USERNAME"   "OS_USER_NAME"  "PROCESS"   "LOCKED_MODE"
        3         58          16         424487       3235818   "PLAN_TABLE$"      2447             "ASP1"             "z013"         "15140"        3

所以到目前为止我没有锁定上面创建的表,现在我将运行插入查询而不提交,并将检查来自 sql 开发人员(或任何地方)的锁定 agian

Insert into SEG_TEST_SINGLE_PARTITION (POR_CD,PROD_MNTH,INS_DTTM) values ('02','201607',to_timestamp('15-DEC-16 11.15.09.000000000 PM','DD-MON-RR HH.MI.SS.FF AM'));
1 row inserted

锁定查询

select a.INST_ID,a.XIDUSN,a.XIDSLOT,a.XIDSQN,a.OBJECT_ID,b.OBJECT_NAME,a.SESSION_ID,a.ORACLE_USERNAME,a.OS_USER_NAME,a.PROCESS,LOCKED_MODE from
GV$LOCKED_OBJECT a,dba_objects b where a.object_id=b.object_id and ORACLE_USERNAME like '%ASP01%' order by 8;  

以分区表(SEG_TEST_SINGLE_PARTITON) 作为对象名称的结果

 "INST_ID"  "XIDUSN"    "XIDSLOT"   "XIDSQN"    "OBJECT_ID"     "OBJECT_NAME"                   "SESSION_ID"    "ORACLE_USERNAME"   "OS_USER_NAME"  "PROCESS"   "LOCKED_MODE"
    3       58          16       424487         3235818     "PLAN_TABLE$"                       2447        "ASP01"                 "z013"       "15140"            3
    3       139         5        56366          3929061     "SEG_TEST_SINGLE_PARTITION"         3339        "ASP01"                 "z013"       "31624"            3
    3       139         5        56366          3929063     "SEG_TEST_SINGLE_PARTITION"         3339        "ASP01"                 "z013"       "31624"            3

现在,我们想知道为什么我们会两次使用相同的 session_id(3339) 为单个表获取 tablelock,这会在通过 java 多线程或 Bulk insert 插入时导致长时间延迟,并且有时会因数据大小而挂起?

【问题讨论】:

    标签: oracle partitioning


    【解决方案1】:

    我们在项目中遇到了类似的问题。我们增加了INITRANS。 我不太确定,但一位高级技术 Arch 告诉我,oracle 12c 存在错误。此外,MAXTRANS 已被弃用。 https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses007.htm

    所以我们手动增加所有分区的INITRANS 值,然后moved 分区,以便设置适用。

    我们理解的问题是数据块上发生的并发更新超出了我们的INITRANS 设置所允许的范围。

    我不确定准确的语法,但它类似于:

    ALTER TABLE SEG_TEST_SINGLE_PARTITION MOVE PARTITION PWKLY_ORDR_POR02 INITRANS 10;
    
    ALTER TABLE SEG_TEST_SINGLE_PARTITION MODIFY PARTITION PWKLY_ORDR_POR02 REBUILD INDEX;
    

    【讨论】:

    • 另请参阅此orafaq.com/forum/t/197448 与我试图讲述的类似解释。
    • 嗨 Rouge,我尝试增加 initrans,但它对我不起作用,并且仍然面临等待很长时间的相同 session_id 锁定。感谢您的宝贵回复。
    猜你喜欢
    • 1970-01-01
    • 2019-10-25
    • 2017-04-03
    • 2013-07-27
    • 1970-01-01
    • 2017-04-25
    • 2016-10-31
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多