PDML 不能和rebuild partition index同时运行
情况如下,delete parallel dml 由于语句中含有两个not in,发现表扫描一遍之后未结束,还需要filter 第二遍。 四小时后取消,在os层kill掉所有的spid.
这时需要rebuild 此表的index,在rebuild的时并未发现rollback(SMON rollback了七个小时)block rebuild index的效率。在rebuild index的时候,继续PDML尝试删除data,发现报错是 某个PX进程报错,原因是rebuild partition 时维护某个partition时不能删除此partition下的data。
Parallel DML Holds TM Lock In Exclusive Mode (Mode=6) (Doc ID 2433906.1)
Symptoms
- Session doing Parallel DML statements holds TM enqueue in exclusive mode (lmode=6).
- No any DMLs allowed against the same table(s) from any other session while the PDML transaction is active.
Changes
Using Parallel DML.
Cause
The issue reproduces in 12.2 and in latest versions (18.1) as well.
This is an expected behavior when parallel DMLs are executed as it is a restriction for PDMLs.
Solution
NOTE: In the images and/or the document content below, the user information and data used represents fictitious data from the Oracle sample schema(s) or Public Documentation delivered with an Oracle database product. Any similarity to actual persons, living or dead, is purely coincidental and not intended in any manner.
Refer Transaction Restrictions for Parallel DML as below:
To execute a DML operation in parallel, the parallel execution coordinator acquires parallel execution servers, and each parallel execution server executes a portion of the work under its own parallel process transaction.
Note the following conditions:
(i) Each parallel execution server creates a different parallel process transaction.
(ii) If you use rollback segments instead of Automatic Undo Management, you may want to reduce contention on the rollback segments by limiting the number of parallel process transactions residing in the same rollback segment. See Oracle Database SQL Language Reference for more information.
The coordinator also has its own coordinator transaction, which can have its own rollback segment. To ensure user-level transactional atomicity, the coordinator uses a two-phase commit protocol to commit the changes performed by the parallel process transactions.
Because of the coordinator and parallel workers transaction involved, DMLs cannot be executed from other session when a parallel DML transaction is active and not committed.
A session that is enabled for parallel DML would also put transactions in the session in a special mode: If any DML statement in a transaction modifies a table in parallel, no subsequent serial or parallel query or DML statement can access the same table again in that transaction. The results of parallel modifications cannot be seen during the transaction.
Serial or parallel statements that attempt to access a table that has been modified in parallel within the same transaction are rejected with an error message.
Refer: https://docs.oracle.com/database/121/VLDBG/GUID-53B78D2C-FA4C-4CA1-AF28-91D5AE142859.htm
Example:
Session 1
SQL> alter session force parallel dml parallel 2;
Session altered.
SQL> delete from test where A=1;
2 rows deleted.
SQL> select /*+ parallel(4) */ * from test;
select /*+ parallel(4) */ * from test
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
SQL> select * from test;
select * from test
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
Note: Even we cannot run the serial/parallel query against the same table in the same session followed by a PDML(which is active) that throws the above error.
Session 2
SQL> delete from test where A=2;
==Hangs==
Refer the v$lock output when a DML is executed from another session while PDML is still active in session 1:
SQL> select * from v$lock where type in ('TM','TX');
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID
---------------- ---------------- ---------- -- ----------
00007F848F9B8498 00007F848F9B84C0 19 TM 93837 0 0 3 9 0 0 <=
00007F848F9B8498 00007F848F9B84C0 20 TM 93837 0 6 0 20 1 0
00007F848F9B8498 00007F848F9B84C0 115 TM 93837 0 1 0 20 0 0
00007F848F9B8498 00007F848F9B84C0 42 TM 93837 0 1 0 20 0 0
000000006EB81498 000000006EB814D0 42 TX 196630 3197 6 0 20 0 0
000000006EB8C590 000000006EB8C5C8 115 TX 655370 2469 6 0 20 0 0
00007F848F9B8498 00007F848F9B84C0 42 TM 93837 1 4 0 20 0 0
00007F848F9B8498 00007F848F9B84C0 115 TM 93837 1 4 0 20 0 0
000000006EBB0718 000000006EBB0750 20 TX 458783 2445 6 0 20 0 0
SQL> select pid,pname,PROGRAM from v$process where addr=(select paddr from v$session where sid=20);
PID PNAME PROGRAM
---------- ----- ------------------------------------------------
50 oracle@<program_name> (TNS V1-V3) => user session (Session 1)
SQL> select pid,pname,PROGRAM from v$process where addr=(select paddr from v$session where sid=19);
PID PNAME PROGRAM
---------- ----- ------------------------------------------------
48 oracle@<program_name> (TNS V1-V3) => user session (Session 2) hangs
SQL> select pid,pname,PROGRAM from v$process where addr=(select paddr from v$session where sid=115);
PID PNAME PROGRAM
---------- ----- ------------------------------------------------
36 P000 oracle@<program_name> (P000) => PX worker process
SQL> select pid,pname,PROGRAM from v$process where addr=(select paddr from v$session where sid=42);
PID PNAME PROGRAM
---------- ----- ------------------------------------------------
37 P001 oracle@<program_name> (P001) => PX worker process
In the above output there are 4 SIDs generated for only 2 sessions involved in the PDML foreground sessions, i.e 20 & 19 where 20 in the session 1 and 19 is the session 2 as above. SIDs 42 and 115 are PX worker processes that holds the PDML transactions and thus holding TM lock in S mode(lmode=4). There is also a TM lock for the session 42/115 held in null mode (lmode=1). When other session (SID=19) executes the DML statement against the same table, it will request for TM in row-X mode which wont be acquired unless the PDML transaction is committed.
Please note that application of Patch 23249235, Patch 19682891, Patch 22825855 change the waiter requesting TM from X mode to row-X mode. But since this is a PDML, even row-X cannot be acquired for the object as the null mode (mode=1) for TM on the object and so row-X cannot be acquired being incompatible. This is done mainly to maintain the ACID property of RDBMS and hence a restriction is placed for Parallel DMLs.