---
title: update 报错 4377 场景之一-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 update 报错 4377 场景之一相关的常见问题和使用技巧，帮助您快速解决 update 报错 4377 场景之一的难题。
---
切换语言

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

划线反馈

# update 报错 4377 场景之一

更新时间：2024-01-22 01:56

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

## 问题描述

OceanBase 数据库执行 UPDATE 更新语句引发 4377 报错，日志信息如下。

```shell
ERROR [STORAGE] check_old_row_legitimacy (ob_partition_storage.cpp:2204) [105480][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=3] [dc=0] Fatal Error!!! Catch a defensive error!(ret=-4377

```

使用 addr2line 工具打印调用栈信息。

```shell
[root@xxxxx ~]# addr2line -pCfe /home/admin/oceanbase/bin/observer 0xf4ebe0b 0x53069ef 0x55d98c6 0x55d94df 0x55d9168 0xa43e846 0xa2b4d53 0xa2a8d3e 0x517d463 0x5174ddd 0x5171cdd 0x516ea75 0x516e836 0x516ef30 0xe0b1624 0xe0b0b4a 0xe0b00a0 0xd752de2 0xd752f5f 0xe53e41b 0xe53eeb5 0xe540452 0xe53fc0b 0xe696136 0xd752de2 0x50ffe4a 0x51013b9 0x50fe970 0xb6950c0 0xb6d5cbd 0x50eb847 0x50e88ef 0x50e6a6e 0xb9cf451 0x50e5c8f 0xb9ccde1 0x50e18f6 0xb9cd3e7 0xf3cb5f3 0xf3cb44f 0xf66670f

```

输出结果如下。

```shell
 oceanbase::common::lbt() at ??:?
 oceanbase::common::ObLogger::check_error_log(oceanbase::common::ObPLogItem&) at ??:?
 oceanbase::common::ObLogger::log_message_kv(char const*, int, char const*, int, char const*, unsigned long, char const*, char const*, char const*, char const*, char const*, char const*, char const*)::{lambda(oceanbase::common::ObPLogItem*)#1}::operator()(oceanbase::common::ObPLogItem*) const at 0_cxx.cxx:?
 void oceanbase::common::ObLogger::do_async_log_message<oceanbase::common::ObLogger::log_message_kv(char const*, int, char const*, int, char const*, unsigned long, char const*, char const*, char const*, char const*, char const*, char const*, char const*)::{lambda(oceanbase::common::ObPLogItem*)#1}>(char const*, int, char const*, int, char const*, unsigned long, oceanbase::common::ObLogger::log_message_kv(char const*, int, char const*, int, char const*, unsigned long, char const*, char const*, char const*, char const*, char const*, char const*, char const*)::{lambda(oceanbase::common::ObPLogItem*)#1}&) at 0_cxx.cxx:?
 oceanbase::common::ObLogger::log_message_kv(char const*, int, char const*, int, char const*, unsigned long, char const*, char const*, char const*, char const*, char const*, char const*, char const*) at 0_cxx.cxx:?
 void oceanbase::common::OB_PRINT<int, oceanbase::common::ObIArray<unsigned long>, oceanbase::common::ObLogPrintPointerCnt<oceanbase::common::ObNewRow*>, oceanbase::common::ObNewRow, oceanbase::storage::ObDMLBaseParam, oceanbase::storage::ObRowDml>(char const*, int, char const*, int, char const*, unsigned long, char const*, char const*, int const&, char const*, oceanbase::common::ObIArray<unsigned long> const&, char const*, oceanbase::common::ObLogPrintPointerCnt<oceanbase::common::ObNewRow*> const&, char const*, oceanbase::common::ObNewRow const&, char const*, oceanbase::storage::ObDMLBaseParam const&, char const*, oceanbase::storage::ObRowDml const&) at ??:?
 oceanbase::storage::ObPartitionStorage::check_old_row_legitimacy(oceanbase::storage::ObPartitionStorage::ObDMLRunningCtx&, oceanbase::common::ObNewRow const&)::$_4164::operator()(char const*) const at 2_cxx.cxx:?
 oceanbase::storage::ObPartitionStorage::check_old_row_legitimacy(oceanbase::storage::ObPartitionStorage::ObDMLRunningCtx&, oceanbase::common::ObNewRow const&) at ??:?
 oceanbase::storage::ObPartitionStorage::process_old_row(oceanbase::storage::ObPartitionStorage::ObDMLRunningCtx&, bool, oceanbase::common::ObIArray<oceanbase::storage::ObPartitionStorage::ChangeType> const&, oceanbase::storage::ObStoreRow const&) at ??:?
 oceanbase::storage::ObPartitionStorage::update_row(oceanbase::storage::ObPartitionStorage::ObDMLRunningCtx&, oceanbase::common::ObIArray<oceanbase::storage::ObPartitionStorage::ChangeType> const&, oceanbase::common::ObIArray<long> const&, bool, oceanbase::storage::ObPartitionStorage::RowReshape*&, oceanbase::storage::ObPartitionStorage::RowReshape*&, oceanbase::storage::ObStoreRow&, oceanbase::storage::ObStoreRow&, oceanbase::common::ObRowStore*, bool&) at ??:?
 oceanbase::storage::ObPartitionStorage::update_rows(oceanbase::storage::ObStoreCtx const&, oceanbase::storage::ObDMLBaseParam const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObNewRowIterator*, long&) at ??:?
 oceanbase::storage::ObPGStorage::update_rows(oceanbase::storage::ObStoreCtx const&, oceanbase::storage::ObDMLBaseParam const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObNewRowIterator*, long&) at ??:?
 oceanbase::storage::ObPartitionGroup::update_rows(oceanbase::storage::ObStoreCtx const&, oceanbase::storage::ObDMLBaseParam const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObNewRowIterator*, long&) at ??:?
 oceanbase::storage::ObPartitionService::update_rows(oceanbase::transaction::ObTransDesc const&, oceanbase::storage::ObDMLBaseParam const&, oceanbase::common::ObPartitionKey const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObIArray<unsigned long> const&, oceanbase::common::ObNewRowIterator*, long&) at ??:?
 oceanbase::sql::ObTableUpdate::update_rows(oceanbase::sql::ObExecContext&, long&) const at ??:?
 oceanbase::sql::ObTableUpdate::do_table_update(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObTableUpdate::inner_open(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObPhyOperator::open(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObPhyOperator::open(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObMiniTaskExecutor::sync_fetch_local_result(oceanbase::sql::ObExecContext&, oceanbase::sql::ObPhyOperator const&, oceanbase::common::ObScanner&) at ??:?
 oceanbase::sql::ObMiniTaskExecutor::mini_task_local_execute(oceanbase::sql::ObExecContext&, oceanbase::sql::ObMiniTask&, oceanbase::sql::ObMiniTaskResult&) at ??:?
 oceanbase::sql::ObDMLMiniTaskExecutor::mini_task_execute(oceanbase::sql::ObExecContext&, oceanbase::sql::ObMiniJob const&, oceanbase::sql::ObTaskInfo&, oceanbase::sql::ObMiniTaskResult&) at ??:?
 oceanbase::sql::ObDMLMiniTaskExecutor::execute(oceanbase::sql::ObExecContext&, oceanbase::sql::ObMiniJob const&, oceanbase::common::ObIArray<oceanbase::sql::ObTaskInfo*>&, bool, oceanbase::sql::ObMiniTaskResult&) at ??:?
 oceanbase::sql::ObMultiPartUpdate::inner_open(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObPhyOperator::open(oceanbase::sql::ObExecContext&) const at ??:?
 oceanbase::sql::ObExecuteResult::open(oceanbase::sql::ObExecContext&) at ??:?
 oceanbase::sql::ObResultSet::open() at ??:?
 oceanbase::sql::ObResultSet::sync_open() at ??:?
 oceanbase::observer::ObAsyncPlanDriver::response_result(oceanbase::observer::ObMySQLResultSet&) at ??:?
 oceanbase::observer::ObMPQuery::process_with_tmp_context(oceanbase::sql::ObSQLSessionInfo&, bool, bool, bool&, bool&) at ??:?
 oceanbase::observer::ObMPQuery::process_single_stmt(oceanbase::sql::ObMultiStmtItem const&, oceanbase::sql::ObSQLSessionInfo&, bool, bool, bool&, bool&) at ??:?
 oceanbase::observer::ObMPQuery::process() at ??:?
 oceanbase::rpc::frame::ObSqlProcessor::run() at ??:?
 oceanbase::omt::ObWorkerProcessor::process_one(oceanbase::rpc::ObRequest&) at ??:?
 oceanbase::omt::ObWorkerProcessor::process(oceanbase::rpc::ObRequest&) at ??:?
 oceanbase::omt::ObThWorker::process_request(oceanbase::rpc::ObRequest&) at ??:?
 oceanbase::omt::ObThWorker::worker(long&, long&, int&) at ??:?
 non-virtual thunk to oceanbase::omt::ObThWorker::run(long) at ??:?
 std::_Function_handler<void (), oceanbase::lib::UserThread::start()::$_14::operator()(oblib::Thread*) const::{lambda()#1}>::_M_invoke(std::_Any_data const&) at 0_cxx.cxx:?
 eeentry(boost::context::detail::transfer_t) at ??:?
 finish at object_set.cpp:?

```

示例如下。

1. 创建测试表 SAMPLE。

   ```shell
   obclient > CREATE TABLE "SAMPLE" (
   "SAMPLE_ID" NUMBER(*,0) PRIMARY KEY,
   "SAMPLE_BARCODE" VARCHAR2(60),
   "VOLUME" NUMBER(*,2),
   "TOTAL_QUANTITY" NUMBER(*,2),
   "REPORT_PDF" VARCHAR2(200));
   Query OK, 0 rows affected (0.072 sec)

   ```
 2. 创建索引。

   ```shell
   obclient > CREATE INDEX "SAMPLE_BARCODE_INDEX" on "SAMPLE" ("SAMPLE_BARCODE");
   Query OK, 0 rows affected (0.032 sec)

   ```
 3. 创建测试表 STOCK_RETURN_YPLIST。

   ```shell
   obclient > CREATE TABLE "STOCK_RETURN_YPLIST" (
   "STOCK_RETURN_YPLIST_ID" NUMBER(*,0) PRIMARY KEY,
   "SAMPLE_BARCODE" VARCHAR2(50),
   "ACTUAL_TOTAL" NUMBER(*,2),
   "ACTUAL_VOLUME" NUMBER(*,2));
   Query OK, 0 rows affected (0.032 sec)

   ```
 4. 创建自定义函数。

   ```shell
   obclient > CREATE OR REPLACE FUNCTION Subtract(num1 IN NUMBER, num2 IN NUMBER)
   RETURN NUMBER AS
   num3 number;
   begin
   num3 := num1 - num2;
   RETURN num3;
   end;
   /
   Query OK, 0 rows affected (0.030 sec)

   ```
 5. 插入测试数据。

   ```shell
   obclient > insert into sample (SAMPLE_ID, volume, total_quantity, sample_barcode, REPORT_PDF) values(1, 100, 200, 10, 'a.pdf');
   Query OK, 1 row affected (0.011 sec)

   ```

   ```shell
   insert into stock_return_yplist (STOCK_RETURN_YPLIST_ID, actual_volume, actual_total, sample_barcode) values(2, 30, 40, 10);
   Query OK, 1 row affected (0.003 sec)

   ```
 6. 执行更新语句。

```shell
  obclient > UPDATE
    sample s
  SET
    (s.volume, s.total_quantity) = (
      SELECT
        Subtract(s.volume, y.actual_volume) AS volume,
        Subtract(s.total_quantity, y.actual_total)     AS total_quantity
      FROM
        stock_return_yplist y
      WHERE
        y.sample_barcode = s.sample_barcode and y. stock_return_sheet_id = '31507' AND (
          s.re_test_report_date is null or s. re_test_report_date = ''
        )
    )
  WHERE
    EXISTS (
      SELECT
        1
      FROM
        stock_return_yplist y
      WHERE
        y.stock_return_sheet_id = '31507' AND s.sample_barcode = y.sample_barcode AND (
          s.re_test_report_date is null or s.re_test_report_date = ''
        )
    );
  ORA-00600:internal error code, arguments: -4377, fatal internal error in [check_old_row_legitimacy]

```

## 适用版本

OceanBase 数据库 V3.2.x 版本。

## 问题原因

update set 使用子查询对向量进行更新时，`subplan filter` 输出结果列投影处理发生偏移错误，导致一部分列错误覆盖，触发类型检查报错。

## 解决方法

- 升级至问题已修复版本，目前已修复的版本包括 OceanBase 数据库企业版 V3.2.3 BP5（oceanbase-3.2.3.2-105000062022090916）及之后版本。
 - 短期解决方法改写 SQL，更新行。

上一篇

[对虚拟表执行 DML 操作报错](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000267161)

下一篇

[OceanBase 数据库 V3.x 版本 batch update 会偶发报错 ORA-00600: internal error code, arguments: -4016, Internal error 的原因和解决方法](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000001887528) ![有帮助](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) 咨询热线
