对于Oracle中的并发DML操作,分区表被锁定

时间:2016-12-17 10:47:11

标签: oracle partitioning

我在Oracle 11g中创建了一个分区表,并尝试使用Java批处理作业中的多线程插入记录。 让我们说,如果我有10个线程,&每个人都希望同时插入/更新100万条记录或者在没有线程的情况下批量插入一些时间,在这两种情况下我们的表都被oracle锁定了同一个会话。如果我们有10个线程,那么我们为同一个表创建了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

所以到目前为止我没有锁定上面创建的表,现在我将运行Insert query而不提交,并将从sql developer(或从任何地方)检查锁定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)将单个表的表锁定两次,这会导致插入java多线程或批量插入时出现长时间延迟,有时根据数据大小挂起?

1 个答案:

答案 0 :(得分:0)

我们的项目遇到了类似的问题。我们增加了INITRANS。 我不太确定,但高级技术拱门告诉我,oracle 12c有一个错误。此外,不推荐使用MAXTRANShttps://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;