修改与删除日志数据

更新时间:
复制为 MD 格式

日志服务支持对已写入 LogStore 的数据执行按行修改(Update)和按行删除(Delete)操作,适用于业务字段回填修正、测试数据清理和单条记录修复等场景。

功能概述

LogStore 默认采用只追加写入(Append-Only)模式,数据写入后不可就地修改。在以下场景中,需要对已写入的数据进行修改或删除:

  • 业务字段回填修正:订单状态、风控标签、规则评分等字段需要事后回填或更正。

  • 测试和灰度数据清理:清除测试阶段或灰度发布阶段产生的无用数据。

  • 单条记录修复:业务回放场景中对特定记录进行定点修复。

日志服务提供两种调用方式来执行修改与删除操作:按 RowID(逻辑记录 ID)精确操作单条日志,或按查询语句批量操作符合条件的日志。

重要

修改和删除操作均不可回滚。执行前请确认操作范围,避免误操作。实时消费(日志中枢 LogHub)和投递任务不感知修改和删除操作,仅查询类读路径能看到最新结果。

前提条件

  • 已创建日志服务 Project。

  • 已在创建 LogStore 时将 enableModify 参数设置为 true。具体操作请参见本文开通方式章节。

  • 如果使用按查询语句修改或删除的方式,查询条件中涉及的字段必须已创建索引。

基础概念

RowID(逻辑记录 ID)

RowID 是日志服务为支持修改与删除功能而引入的逻辑记录标识。每条写入到已开启修改与删除功能的 Logstore 的日志都会被分配一个唯一的 RowID,修改和删除操作均以 RowID 作为记录定位依据。

  • 格式:RowID 由日志服务在写入时自动生成,不支持自定义。调用方仅需将其作为记录标识传递,无需解析或拼接。

  • 稳定性:RowID 在记录的整个生命周期内保持不变。日志被修改后,RowID 仍然指向同一条逻辑记录,后续的查询、再次修改或删除均使用同一个 RowID。

  • 可见性:开启修改与删除功能的 Logstore 在查询结果中会自动返回内置字段 __rowid____rowid__ 为保留字段名,不可用于索引配置。

AffectedRows(影响行数)

每次修改或删除请求成功执行后,响应中会返回 AffectedRows(影响行数),表示本次操作实际生效的日志条数。

  • HTTP 接口AffectedRows 位于 HTTP 响应 Header x-log-affectedrows

  • 各语言SDK:通常通过 affected_rows / getAffectedRows() 字段直接读取。

  • 返回值为 0:表示未命中任何记录。对同一条记录重复执行删除操作是幂等的,不会报错,但 affected_rows 返回 0。

开通方式

在创建 LogStore 时将 enableModify 参数设置为 true 即可开通修改与删除功能。

重要

注意以下限制:

  • 仅支持在创建 LogStore 时设置该参数,已有 LogStore 无法开启。对于历史数据,可通过简单复制LogStore(新版)将数据加工至enableModifytrueLogStore后处理。

  • 该参数一旦设置为 true,不可关闭。

  • 目前仅支持通过 OpenAPI 和 SDK 开启,暂不支持在控制台开启。

通过 OpenAPI 开启

调用 CreateLogStore 接口,在请求 Body 中将 enableModify 字段设置为 true

POST /logstores HTTP/1.1
Host: <project>.<endpoint>
Content-Type: application/json

{
  "logstoreName": "my-logstore",
  "ttl": 30,
  "shardCount": 1,
  "enableModify": true
}

创建完成后,可通过 GetLogStore 接口验证:返回体中包含 "enableModify": true 即表示开启成功。

通过 SDK 开启

以 python 为例:

from aliyun.log import LogClient

# 从环境变量获取凭证,避免硬编码
client = LogClient(endpoint, access_key_id, access_key)

client.create_logstore(
    project_name="my-project",
    logstore_name="my-logstore",
    ttl=30,
    shard_count=1,
    enable_modify=True,  # 开启修改与删除功能
)

使用方式

修改与删除功能提供两种调用方式:

方式

适用场景

单次最大影响行数

按 RowID 操作

已知具体记录的 RowID,精确修改或删除单条日志

1 行

按查询语句操作

基于查询条件批量修改或删除符合条件的日志

1 万行

方式一:按 RowID 修改或删除

适用于已从查询结果中获取到 RowID 的场景,对指定记录执行精确的修改或删除操作。

修改单条日志

调用 update_logs 方法,传入目标记录的 RowID 和需要修改的字段。修改操作仅需指定待修改的字段,未指定的字段保持原值不变。

from aliyun.log import LogClient, LogItem

client = LogClient(endpoint, access_key_id, access_key)

# 仅指定需要修改的字段,未指定的字段保持原值不变
new_item = LogItem(
    contents=[("status", "REFUNDED")],
)

resp = client.update_logs(
    project="my-project",
    logstore="my-logstore",
    rowid=rowid,
    log_item=new_item,
)
print(f"影响行数: {resp.affected_rows}")  # 预期值为 1

删除单条日志

resp = client.delete_logs_v2(
    project="my-project",
    logstore="my-logstore",
    rowid=rowid,
)
print(f"影响行数: {resp.affected_rows}")  # 预期值为 1
说明
  • 对同一条记录重复执行删除操作是幂等的,不会报错,但 affected_rows 返回 0。

  • 此处使用 delete_logs_v2(同步删除)。delete_logs 为旧版异步软删除接口,开启 enableModify 的 LogStore 不再支持异步软删除。

方式二:按查询语句修改或删除

警告

批量修改和删除操作不可回滚。请注意以下风险:

  • 操作不可逆,已成功修改或删除的记录无法恢复。

  • 操作过程中如果出现部分失败,已成功执行的部分不会回滚。响应中的 AffectedRows 返回实际生效的行数。

  • 执行前,建议先通过 Search 或 SQL 查询校验命中范围和条数,确认操作条件无误后再执行。

按查询语句操作时,日志服务在服务端完成查询和修改或删除的两阶段执行,适用于按条件批量操作的场景。

重要

查询条件中涉及的字段必须已创建索引。按查询语句操作依赖日志的索引可见性,新写入的数据可能存在秒级延迟后才可被查询条件命中。

按查询语句删除

resp = client.delete_logs_v2(
    project="my-project",
    logstore="my-logstore",
    from_time=1716537600,
    to_time=1716624000,
    query='level: DEBUG',
)
print(f"已删除 {resp.affected_rows} 条日志")

按查询语句修改

按查询语句修改时,需要同时指定查询条件和字段更新内容。所有命中行将执行相同的字段修改。

resp = client.update_logs(
    project="my-project",
    logstore="my-logstore",
    from_time=1716537600,
    to_time=1716624000,
    query='order_id: 12345 and status: "PENDING"',
    row_id="",
    log_item={"status": "REFUNDED", "refund_at": "2026-05-25T10:00:00Z"},
)
print(f"已修改 {resp.affected_rows} 条日志")
说明
  • 如果 update_logsdelete_logs_v2 接口同时传入 rowidquery 参数,rowid 优先级更高,query 会被忽略。

  • 按查询语句批量操作属于高代价操作,建议缩小时间范围或细化查询条件后分批执行。单次最大命中行数为 1 万行,超过时请求会被拒绝。

验证操作结果

修改或删除请求成功执行后,通过以下方式确认操作结果:

  • 单条操作(按 RowID):检查响应中的 AffectedRows。值为 1 表示操作成功;值为 0 表示未找到目标记录(记录可能已被删除或 RowID 不存在)。

  • 批量操作(按查询语句)

    1. 检查响应中的 AffectedRows,确认实际影响行数与预期一致。

    2. 使用相同的查询条件再次执行 Search 或 SQL 查询,确认命中结果已更新或已被删除。

说明

修改和删除操作是同步生效的。请求成功返回后,后续的查询(Search、SQL、SPL)即可看到最新结果,无需等待。

数据一致性说明

  • 同步生效:修改和删除操作是同步的。请求成功返回后,后续的查询(Search、SQL、SPL)即可看到最新结果。

  • 实时消费不受影响:实时消费(日志中枢 LogHub)和日志服务投递任务(如投递至 OSS、MaxCompute 等)基于原始写入流,不感知后续的修改或删除操作。仅查询类读路径能看到最新结果。

  • 索引可见延迟:按查询语句操作依赖日志的索引可见性。新写入的数据可能存在秒级延迟后才可被查询条件命中。对刚写入的数据执行按查询操作时,请确认查询已能返回预期结果。

所需 RAM 权限

调用修改或删除接口的 RAM 用户或角色需要授予以下 Action:

Action

说明

log:UpdateLogStoreLogs

修改日志数据(按 RowID 或按查询语句)

log:DeleteLogStoreLogs

删除日志数据(按 RowID 或按查询语句)

资源 ARN 格式:acs:log:<region>:<account-id>:project/<project-name>/logstore/<logstore-name>

说明

建议为修改和删除操作(特别是按查询语句批量删除)单独创建 RAM 用户或角色,并配合操作审计使用。

使用限制

限制项

说明

仅支持新建 LogStore

必须在创建 LogStore 时设置 enableModifytrue。已有 Logstore 无法开启。

不可关闭

一旦开启,无法再关闭。

单次按查询操作最大命中行数

默认 1 万行。超过时请求被拒绝,请缩小时间范围或细化查询条件后分批执行。

索引字段要求

按查询语句操作时,查询条件中涉及的字段需已建立索引。按 RowID 操作不依赖业务字段索引。

不支持重建索引

开启修改与删除功能后,不支持重建索引。

不支持软删除

开启后,不支持异步软删除。请使用本文介绍的同步删除接口。

__rowid__ 为保留字段

不可将 __rowid__ 用作索引字段名或自定义字段名。

实时消费和投递任务不感知修改和删除

实时消费(日志中枢 LogHub)和投递任务(如投递至 OSS、MaxCompute)基于原始写入流,不感知后续的修改或删除操作。仅查询类读路径(Search、SQL、SPL)能看到最新结果。

计费说明

  • 修改操作会对修改的数据产生额外的索引存储空间和索引流量费用。

  • 删除操作不会产生额外计费。

常见问题

已有的 Logstore 能否开启修改与删除功能?

不能。该功能依赖底层存储格式,仅在新创建的 Logstore 上生效。如需使用,请新建一个开启 enableModifytrue 的 Logstore,并通过数据加工或 SDK 将历史数据迁移至新 Logstore。

修改或删除操作会影响实时消费吗?

不会。实时消费(日志中枢 LogHub)和投递任务基于原始写入流,不感知后续的修改或删除操作。仅查询(Search、SQL、SPL)等读路径能看到最新结果。

修改或删除操作是否立即可见?

是。请求成功返回后,后续查询请求即可看到最新结果。AffectedRows 返回的是实际生效的行数。

能否回滚一次误操作的修改或删除?

不能。修改和删除操作不可回滚。建议在执行前通过 Search 或 SQL 校验命中范围,并合理使用 RAM 权限管控修改和删除操作。对于高危批量操作,建议配置操作审计。

删除操作是否会立即释放存储空间?

删除是逻辑删除。日志在 Logstore TTL 到期前仍保留底层存储,但所有读路径会过滤掉已删除的记录。存储空间会随 TTL 到期或后台合并任务逐步释放。