---
title: OBKV 使用带 CURRENT_STRAMP 属性的列作为 TTL 过期列导致节点宕机-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于OBKV 使用带 CURRENT_STRAMP 属性的列作为 TTL 过期列导致节点宕机相关的常见问题和使用技巧，帮助您快速解决OBKV 使用带 CURRENT_STRAMP 属性的列作为 TTL 过期列导致节点宕机的难题。
---
切换语言

- 简体中文
- English

划线反馈

# OBKV 使用带 CURRENT_STRAMP 属性的列作为 TTL 过期列导致节点宕机

更新时间：2026-06-04 09:56

适用版本： V4.2.x 内容类型：Troubleshoot  

## 问题现象

- 表定义要求：表定义中 TTL 过期列带有 `current_timestamp` 属性。

     - 例如下面的表定义中 c3 列带有 `current_timestamp` 列定义属性，并且作为了 TTL 过期列（TTL(c3 + INTERVAL 2 second)）。

      ```sql
      create table if not exists test_ttl(
      c1 int(12) primary key,
      c2 int(12),
      c3 timestamp default current_timestamp,
      TTL(c3 + INTERVAL 2 second);

      ```
 - 操作：使用 OBKV 客户端的 `client.InsertOrUpdate` 接口进行数据更新。

     - 例子中，第一次 InsertOrUpdate 执行的是写入操作，不会触发 core dump。
     - 例子中，第二次 InsertOrUpdate 执行的是更新操作，在更新操作中会检查旧行是否过期，检查过期过程中触发 core dump。

      ```sql
       // 1. 第一次数据库中没有数据，InsertOrUpdate 执行的是插入操作
      rowKey := []*table.Column{table.NewColumn("c1", int32(0))}
      mutateColumns := []*table.Column{table.NewColumn("c2", int32(0))}
      affectRows, err := cli.InsertOrUpdate(
        context.TODO(),
        tableName,
        rowKey,
        mutateColumns,
      )
      assert.Equal(t, nil, err)
      assert.EqualValues(t, 1, affectRows)

      // 2. 第二次数据库中已经有相同 rowkey，InsertOrUpdate 执行的是更新操作操作
      ctx, _ := context.WithTimeout(context.Background(), 1000*time.Second) // 10s
      rowKey = []*table.Column{table.NewColumn("c1", int32(0))}
      mutateColumns = []*table.Column{table.NewColumn("c2", int32(1))}
      affectRows, err = cli.InsertOrUpdate(
        ctx,
        tableName,
        rowKey,
        mutateColumns,
      )
      assert.Equal(t, nil, err)
      assert.EqualValues(t, 1, affectRows)

      ```
 - 表现：节点宕机，业务中断，业务端访问数据库超时。

## 关键诊断信息

### 触发条件

表定义中 TTL 过期列带有 current_timestamp 属性，使用 OBKV 客户端的 client.InsertOrUpdate 接口进行数据更新。

## 问题原因

- 直接原因：server 访问非法内存，导致节点宕机。
 - 根本原因：在 TTL 算子中，检查过期时，由于时间列旧值没有正确刷到对应的表达式上，导致访问表达式的 datum 时 core dump。 以下面的表模型为例，执行 InsertOrUpdate。

  ```

  ![image](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/bug/4.2.1-bp1/ED8B3C45-9BF8-42c0-A73E-920299D1CDF8.png)

1. 服务端生成的表达式

      - c1 c2 都是普通的列引用表达式 `col_ref_expr`。
      - c3 是计算表达式 now() 表达式，计算结果需要做列转换，所以最上层是列转换表达式。
      - 还有一个过期表达式，过期表达式是 `(c3 + INTERVAL 2 second) < now()`，是一个小于表达式。

            - 左表达式的定义是 `c3 + INTERVAL 2 second`，是一个加法表达式，加法结果需要转换为 `datatime`，所以还有一个列转换表达式。
            - c3 对应的是上面图中标黄的列转换表达式。
 2. 在 TTL 算子执行写入后，发现冲突后会进行过期检查，检查旧行是否过期，过期则删掉旧行，写入新行。

   a. 扫描存储旧行，填充到 old row 中，也就是填充到 `c1:col_ref_expr c2:col_ref_expr c3:col_conv_expr` 中。

   b. 过期表达式进行计算 eval，即执行小于表达式，获取小于表达式结果 `get_bool()`，`true` 则过期，否则不过期。
 3. 问题的原因是在刷旧值的时候，并没有刷到 `c3:col_conv_expr` 中，而是刷到了 `c3:col_conv_expr` 下面的 `col_ref_expr`，导致 `col_conv_expr` 是空的。

## 问题的风险及影响

节点会频繁宕机，业务中断。

## 影响租户

影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。

## 影响版本

OceanBase 数据库 V4.2.1 GA（oceanbase-4.2.1.0-100000182023092722）及之后版本。

## 解决方法

- 升级到问题已修复版本，目前已修复的版本包含 OceanBase 数据库 V4.2.1 BP1(oceanbase-4.2.1.1-101000062023103122) 及之后版本。
 - 如果问题已经发生，可以执行如下命令把 TTL 定义删除进行恢复。

  ```shell
  -- 删除 DDL 定义 SQL 语法
  obclient> ALTER TABLE $table_name REMOVE TTL;

  ```

## 规避方式

不要将带有 `current_timestamp` 列定义属性的列作为 TTL 过期列。

Previous

[使用 ODC 调试带有 CursorForLoop 语句的存储过程时，OBServer 进程可能 core dump](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000075121)

Next

[OBServer core 在 ObSSTableMultiVersionRowMultiGetter::inner_get_next_row](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000441628) ![有帮助](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) 咨询热线
