---
title: 使用 PDML 且涉及多表时导致正确性问题-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于使用 PDML 且涉及多表时导致正确性问题相关的常见问题和使用技巧，帮助您快速解决使用 PDML 且涉及多表时导致正确性问题的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# 使用 PDML 且涉及多表时导致正确性问题

更新时间：2026-05-28 02:06

适用版本： V3.1.x、V3.2.x 内容类型：Troubleshoot  

## 问题现象

在 OceanBase 数据库 V3.1.2 BP6 以下版本中，使用涉及多表的 PDML 时，会出现正确性相关问题。在 OceanBase 数据库 V3.1.2 BP5 及其 Hotfix 版本中，由于 DML 防御检查的存在，使用 PDML 校验出正确性问题会报错 -4377；而在 OceanBase 数据库 V3.1.2 BP5 以下版本（> V2.2.77）中可能会执行成功，但存在正确性问题。

### 测试示例

1. 准备复现测试表与数据。

   ```shell
   CREATE TABLE "ABA1" (
   "BAZ002" NUMBER(16) NOT NULL ENABLE,
   "AAZ001" NUMBER(16) NOT NULL ENABLE,
   "BAB001" NUMBER(16) NOT NULL ENABLE,
   "AAB001" NUMBER(16) NOT NULL ENABLE,
   CONSTRAINT "ABA1_PK_HN" PRIMARY KEY ("AAZ001", "AAB001")
   ) COMPRESS FOR ARCHIVE REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
   partition by hash("AAB001") partitions 2;

   ```

   ```shell

   CREATE TABLE "AC04" (
   "AAZ189" NUMBER(20) NOT NULL ENABLE,
   "AAC001" NUMBER(20) NOT NULL ENABLE,
   "AAB001" NUMBER(20) NOT NULL ENABLE,
   "AAE140" VARCHAR2(3) NOT NULL ENABLE,
   "AAE001" NUMBER(4) NOT NULL ENABLE,
   "AAE750" NUMBER(4) NOT NULL ENABLE,
   CONSTRAINT "AC04_OBPK_1617707763333473" PRIMARY KEY ("AAZ189", "AAC001")
   ) COMPRESS FOR ARCHIVE REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE ENABLE ROW MOVEMENT TABLET_SIZE = 134217728 PCTFREE = 0
   partition by hash("AAC001") PARTITIONS 2;
   create index IDX_AC04_AAE001 on ac04(AAE001, AAZ189, AAC001) local;
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324057 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324069 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324067 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324039 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324041 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324061 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324087 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324049 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000032419830125 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324035 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000038658419181 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324077 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324047 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000006004269873 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324063 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324037 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324053 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324051 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000015000060398 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324043 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324083 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324081 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000000001716012 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324045 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324065 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324031 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324089 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324085 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324075 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324055 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324073 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324079 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324033 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324071 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000002000324059 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000038620089300 );
   INSERT INTO ABA1 (BAZ002, AAZ001, BAB001, AAB001) VALUES (1,1,1,4000031756831682 );
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4000006004243942 , 46100000001588907423 , 4000000001957811, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4100044676606955 , 46100000001593369987 , 4100044833010726, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4100044014124913 , 46100000001594020812 , 4100044705217120, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4000002000304088 , 46005200000137364000 , 4000004000846453, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4100045967101824 , 46100000001590348600 , 4100046000997886, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4000006004269873 , 46100000001593192182 , 4100041614112376, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4000006004269873 , 46100000001587674702 , 4000000002324697, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4100043094635292 , 46100000001592440235 , 4100045197270471, '310', 2022, 22);
   INSERT INTO AC04 (aab001,AAZ189,AAC001,AAE140,AAE001,AAE750) VALUES (4000002000324041 , 46100000001593723083 , 4000036722430825, '310', 2022, 22);

   ```
 2. 测试 PDML 的 SQL 语句。

   ```shell
   update /*+ leading(ABA1) PQ_DISTRIBUTE(@"UPD$1" ("TEST.AC04"@"UPD$1" ) BROADCAST NONE)  enable_parallel_dml parallel(2)*/ ac04 set AAE750 = 3 where aae001 = 2022    and aae140 = '310'       AND aab001 not in ( select aab001 from aba1);

   ```

### 在 OceanBase 数据库 V3.1.2 BP6 以下版本执行计划

下图为该 PDML 的执行计划，算子 2 3 之间没有分配 EXCHANGE 算子，AC04 表待更新数据的 partition id 由 ABA1 表计算出来（即由 4 5 6 7 算子吐出来），这是不符合预期的。

![image01](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/20250820correctness-issue-caused-by-pdml-437701.png)

#### OceanBase 数据库 V3.1.2 BP4 Hotfix（oceanbase-3.1.2-20211019145543）版本执行结果

9 行数据经 update 后变成 13 行，不符合预期，存在正确性问题。

![image02](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/20250820correctness-issue-caused-by-pdml-437702.png)

#### OceanBase 数据库 V3.1.2 BP5（oceanbase-3.1.2-20211209200749）版本执行结果

报 -4377 DML 防御错误。

![image03](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/20250820correctness-issue-caused-by-pdml-437703.png)

### OceanBase 数据库 3.1.2 BP6 及以上版本执行计划

算子 2 5 间分配了 EXCHANGE 算子，确保生成正确的 partition id。

![image04](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/20250820correctness-issue-caused-by-pdml-437704.png)

## 关键诊断信息

### 触发条件

使用 PDML 且涉及多表。

## 问题原因

- 在 OceanBase 数据库 V3.1.x BP6 以下版本中，不推荐使用涉及多张表的 PDML（如：update t1 set c1 = xx where xxx in (select ... from t2) ; 涉及到了t1、t2 两张表），单表 PDML 不受影响（如：update t1 set c1 = c2;）。
 - 在 OceanBase 数据库 V3.1.x 版本中使用 PDML 时，OceanBase 会先根据过滤条件获取相关操作数据的 PARTITION ID 信息，之后依据此 PARTITION ID 信息去存储层中进行相关 DML 操作。
 - 在问题版本中，若涉及多张表的 PDML 执行计划中的 DML 算子和 TABLE SCAN 算子间形成了 PARTITION WISE，在没有分配 EXCHANGE 算子的情况下，可能会分配出与数据不匹配的错误 PARTITION ID，如果拿着错误的 PARTITION ID 去执行 DML 就会引发正确性问题。该问题在 OceanBase 数据库 V3.1.2 BP6 版本通过分配 EXCHANGE 算子修复。

     - 在 OceanBase 数据库 < V3.1.2 BP5 版本，OceanBase 会直接拿着分配的 PARTITION ID 去进行 DML，即使该 PARTITION ID 是错误的，也可能会执行成功（有正确性问题）。
 - 在 OceanBase 数据库 V3.1.2 BP5 及 Hotfix 版本后，DML 在向存储层写数据时，会先根据 DML 防御机制拿着 rowkey 与 PARTITION ID 信息去坐 old row 校验，此时如果拿到的 PARTITION ID 信息是错误的（与 rowkey 不匹配），则会出现存储层读不出 old row 的错误（debug 模式编译下的 OceanBase，日志中打印：`old row in storage is not exists(rowkey=..., ret=-4377)`），OceanBase 报错 -4377。

  报错信息如下:

  ```shell
  WARN  [SQL.DTL] process_base (ob_dtl_channel_loop.cpp:232) [116982][2526][xxxxx-xxxxx] [lt=6] [dc=0] message loop is interrupted(code={code:-4377, info:{msg:"tid:73549,from:"xx.xx.xx.xx:port",TASK ABORT QC"}}, ret=-4377)

  ```

## 问题的风险及影响

在问题版本上使用 PDML 且涉及多表时，会有正确性问题，因此不推荐使用涉及多张表的 PDML ，单表 PDML 则不受影响。

## 影响租户

影响 OceanBase 数据库中的 Oracle 租户和 MySQL 租户，对于 SYS 租户无影响。

## 影响的版本

OceanBase 数据库企业版 V3.1.2 GA（oceanbase-3.1.2-20210618150922）及之后版本。

## 解决方法

- 升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V3.1.2 BP6 (oceanbase-3.1.2-20211230114204) 及之后版本。
 - 在 OceanBase 数据库 V3.1.x BP6 以下版本中，不推荐使用涉及多张表的 PDML（如：update t1 set c1 = xx where xxx in (select ... from t2) ; 涉及到了 t1、t2 两张表），单表 PDML 不受影响（如：update t1 set c1 = c2;）。

## 规避方式

在 OceanBase 数据库 V3.1.x BP6 以下版本中，不推荐使用涉及多张表的 PDML（如：update t1 set c1 = xx where xxx in (select ... from t2) ; 涉及到了 t1、t2 两张表），单表 PDML 不受影响（如：update t1 set c1 = c2;）。

上一篇

[改写导致 where subquery pullup 后 part hint 丢失的正确性问题](https://www.oceanbase.com/knowledge-base/oceanbase-database-20000036898)

下一篇

[DML 语句报错 -6244 out of transaction threshold](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000209998) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
