---
title: 函数索引 Session 变量变换导致 SQL 报 -4377-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 函数索引 Session 变量变换导致 SQL 报 -4377相关的常见问题和使用技巧，帮助您快速解决 函数索引 Session 变量变换导致 SQL 报 -4377的难题。
---
切换语言

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

划线反馈

# 函数索引 Session 变量变换导致 SQL 报 -4377

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

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

## 问题描述

OceanBase 数据库中创建函数索引后，若函数索引表达式的结果依赖于系统变量，修改系统变量后再执行 update/delete 操作时可能报 -4377。

## 问题现象

创建函数索引后，若函数索引表达式的结果依赖于系统变量，修改系统变量后再执行 update/delete 操作时可能报 -4377。原因是索引表中的数据是按照系统变量的旧值计算的，系统变量更新后，根据索引表达式计算出的值若与索引表中保存的值不同，在检查时报错。OceanBase V4.0 版本之前的分支创建虚拟生成列，以及所有分支创建虚拟生成列上的索引都有同样的问题。

示例如下。

1. 设置当前租户会话使用的时区。

   ```shell
   obclient > ALTER SESSION SET time_zone='+08:00';
   Query OK, 0 rows affected (0.000 sec)

   ```
 2. 创建表。

   ```shell
   obclient > CREATE TABLE t1(c1 timestamp, c2 varchar(10));
   Query OK, 0 rows affected (0.032 sec)

   ```
 3. 创建索引键为 `SYS_EXTRACT_UTC(c1)` 的函数索引。

   ```shell
   obclient > CREATE INDEX i1 on t1(SYS_EXTRACT_UTC(c1));
   Query OK, 0 rows affected (0.431 sec)

   ```
 4. 设置当前租户会话日期时间格式。

   ```shell
   obclient > ALTER SESSION SET NLS_TIMESTAMP_FORMAT ='YYYY-MM-DD HH24:MI:SS.FF';
   Query OK, 1 row affected (0.005 sec)

   ```
 5. 插入数据。

   ```shell
   obclient > INSERT INTO t1 VALUES('2020-01-02 01:01:01','abc');
   Query OK, 1 row affected (0.005 sec)

   ```

   ```shell
   obclient > INSERT INTO t1 VALUES('2020-01-01 01:01:01','aaa');
   Query OK, 1 row affected (0.001 sec)

   ```
 6. 执行查询语句。

   ```shell
   obclient > SELECT c1,c2,SYS_EXTRACT_UTC(c1) FROM t1;

   ```

   输出内容如下。

   ```shell
   +----------------------------+------+----------------------------+
   | C1                         | C2   | SYS_EXTRACT_UTC(C1)        |
   +----------------------------+------+----------------------------+
   | 2020-01-02 01:01:01.000000 | abc  | 2020-01-01 15:01:01.000000 |
   | 2020-01-01 01:01:01.000000 | aaa  | 2019-12-31 15:01:01.000000 |
   +----------------------------+------+----------------------------+

   ```

   `SYS_EXTRACT_UTC` 系统函数的结果依赖于 `time_zone`，因此修改 `time_zone` 后结果变化，但是索引表中的数据是按照 time_zone='+08:00' 计算的。
 7. 设置修改当前租户会话使用的时区。

   ```shell
   ALTER SESSION SET time_zone='+00:00';

   ```
 8. 再次执行步骤 6 中的查询语句。

   ```

   输出内容如下。

   ```shell
   +----------------------------+------+----------------------------+
   | C1                         | C2   | SYS_EXTRACT_UTC(C1)        |
   +----------------------------+------+----------------------------+
   | 2020-01-02 01:01:01.000000 | abc  | 2020-01-02 01:01:01.000000 |
   | 2020-01-01 01:01:01.000000 | aaa  | 2020-01-01 01:01:01.000000 |
   +----------------------------+------+----------------------------+

   ```
 9. 执行 update 语句，更新索引表数据时报错。

   ```shell
   obclient > UPDATE t1 SET c2 = 'ddd' WHERE c2 = 'aaa';
   ORA-00600: internal error code, arguments: -4377, fatal internal error in [check_old_row_legitimacy]

   ```
 10. 执行查询语句，使用索 I1 时结果错误，预期是一行，实际执行结果是空集。

    ```shell
    obclient > SELECT c1,c2,SYS_EXTRACT_UTC(c1) FROM t1 WHERE SYS_EXTRACT_UTC(c1) = '2020-01-01 17:01:01.000000';
    Empty set (0.01 sec)

    ```
 11. 展示步骤 10 中查询语句的执行计划。

    ```shell
    obclinet > EXPLAIN SELECT c1,c2,SYS_EXTRACT_UTC(c1) FROM t1 WHERE SYS_EXTRACT_UTC(c1) = '2020-01-01 17:01:01.000000';

    ```

    输出内容如下。

    ```shell
    +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Query Plan                                                                                                                                                                                                                                                                                                                                                                                                               |
    +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | =====================================
    |ID|OPERATOR  |NAME  |EST. ROWS|COST|
    -------------------------------------
    |0 |TABLE SCAN|T1(I1)|1        |92  |
    =====================================

    Outputs & filters:
    -------------------------------------
    0 - output([T1.C1], [T1.C2], [SYS_EXTRACT_UTC(cast(T1.C1, TIMESTAMP_WITH_TIME_ZONE(-1, -1)))]), filter(nil),
          access([T1.C1], [T1.C2]), partitions(p0)
    |
    +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

    ```

## 问题风险及影响

该问题是用户行为引起，与常规 4377 问题不同。在原生 MySQL 数据库中，未对此场景做特殊处理，触发时不报错且执行结果错误。Oracle 数据库也仅通过添加 to_char 等内置表达式处理了部分场景。

在 OceanBase 数据库中，该问题的影响是修改系统变量后，更新表中数据会报 -4377；执行查询语句时，若使用该索引，查询结果错误。

## 影响的版本

OceanBase 数据库企业版 V2.x、V3.x、V4.x 版本，以及社区版 V3.1.x 版本。

#### 注意

OceanBase 数据库在 V3.2.3 BP10 (oceanbase-3.2.3.3-110000092023091219) 、V3.2.4 BP6 (oceanbase-3.2.4.6-106000052023102710) 、V4.1.0 BP4 (oceanbase-4.1.0.2-104000032023092119) 、V4.2.0 Beta（oceanbase-ce-4.2.0.0-100000152023080109）及之后版本做了修复。但是仅调整报错信息以便于排查，修复后检测到函数索引/生成列在入参未改变，但是结果与旧值不同时，报 5500 错误。触发后，若确认是系统变量改变或系统函数行为不确定导致报错，则与老版本的处理一致，删除索引后重建。

## 解决办法及规避方式

### 解决办法

- 对于创建函数索引或生成列索引后出现该问题的场景，在修改系统变量后，需要删除并重新创建索引。
 - 对于虚拟生成列上无索引，修改系统变量后报 -4377 的场景，可以登录系统租户下手动触发合并，下刷数据，执行如下命令。

  ```shell
  obclient > ALTER SYSTEM MINOR FREEZE;

  ```
 - OceanBase 数据库在 V3.2.3 BP10 (oceanbase-3.2.3.3-110000092023091219) 、V3.2.4 BP6 (oceanbase-3.2.4.6-106000052023102710) 、V4.1.0 BP4 (oceanbase-4.1.0.2-104000032023092119) 、V4.2.0 Beta (oceanbase-ce-4.2.0.0-100000152023080109) 及之后的版本修复了该问题。但是仅调整报错信息以便于排查，修复后检测到函数索引/生成列在入参未改变，但是结果与旧值不同时，报 5500 错误。触发后，若确认是系统变量改变或系统函数行为不确定导致报错，则与老版本的处理一致，删除索引后重建。

### 规避方式

避免将行为不确定的系统函数用于函数索引或生成列的定义。

上一篇

[OceanBase 数据库 Oracle 模式下 nchar 使用 to_number 函数报 Internal error](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000233906)

下一篇

[Oracle 模式下调用函数报错 ORA-00600: internal error code, arguments: -4007, Not supported feature or function](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000284433) ![有帮助](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) 咨询热线
