日志服务支持对已写入 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 响应 Headerx-log-affectedrows。各语言SDK:通常通过
affected_rows/getAffectedRows()字段直接读取。返回值为 0:表示未命中任何记录。对同一条记录重复执行删除操作是幂等的,不会报错,但
affected_rows返回 0。
开通方式
在创建 LogStore 时将 enableModify 参数设置为 true 即可开通修改与删除功能。
注意以下限制:
仅支持在创建 LogStore 时设置该参数,已有 LogStore 无法开启。对于历史数据,可通过简单复制LogStore(新版)将数据加工至
enableModify为true的LogStore后处理。该参数一旦设置为
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_logs或delete_logs_v2接口同时传入rowid和query参数,rowid优先级更高,query会被忽略。按查询语句批量操作属于高代价操作,建议缩小时间范围或细化查询条件后分批执行。单次最大命中行数为 1 万行,超过时请求会被拒绝。
验证操作结果
修改或删除请求成功执行后,通过以下方式确认操作结果:
单条操作(按 RowID):检查响应中的
AffectedRows。值为 1 表示操作成功;值为 0 表示未找到目标记录(记录可能已被删除或 RowID 不存在)。批量操作(按查询语句):
检查响应中的
AffectedRows,确认实际影响行数与预期一致。使用相同的查询条件再次执行 Search 或 SQL 查询,确认命中结果已更新或已被删除。
修改和删除操作是同步生效的。请求成功返回后,后续的查询(Search、SQL、SPL)即可看到最新结果,无需等待。
数据一致性说明
同步生效:修改和删除操作是同步的。请求成功返回后,后续的查询(Search、SQL、SPL)即可看到最新结果。
实时消费不受影响:实时消费(日志中枢 LogHub)和日志服务投递任务(如投递至 OSS、MaxCompute 等)基于原始写入流,不感知后续的修改或删除操作。仅查询类读路径能看到最新结果。
索引可见延迟:按查询语句操作依赖日志的索引可见性。新写入的数据可能存在秒级延迟后才可被查询条件命中。对刚写入的数据执行按查询操作时,请确认查询已能返回预期结果。
所需 RAM 权限
调用修改或删除接口的 RAM 用户或角色需要授予以下 Action:
Action | 说明 |
| 修改日志数据(按 RowID 或按查询语句) |
| 删除日志数据(按 RowID 或按查询语句) |
资源 ARN 格式:acs:log:<region>:<account-id>:project/<project-name>/logstore/<logstore-name>
建议为修改和删除操作(特别是按查询语句批量删除)单独创建 RAM 用户或角色,并配合操作审计使用。
使用限制
限制项 | 说明 |
仅支持新建 LogStore | 必须在创建 LogStore 时设置 |
不可关闭 | 一旦开启,无法再关闭。 |
单次按查询操作最大命中行数 | 默认 1 万行。超过时请求被拒绝,请缩小时间范围或细化查询条件后分批执行。 |
索引字段要求 | 按查询语句操作时,查询条件中涉及的字段需已建立索引。按 RowID 操作不依赖业务字段索引。 |
不支持重建索引 | 开启修改与删除功能后,不支持重建索引。 |
不支持软删除 | 开启后,不支持异步软删除。请使用本文介绍的同步删除接口。 |
| 不可将 |
实时消费和投递任务不感知修改和删除 | 实时消费(日志中枢 LogHub)和投递任务(如投递至 OSS、MaxCompute)基于原始写入流,不感知后续的修改或删除操作。仅查询类读路径(Search、SQL、SPL)能看到最新结果。 |
计费说明
修改操作会对修改的数据产生额外的索引存储空间和索引流量费用。
删除操作不会产生额外计费。
常见问题
已有的 Logstore 能否开启修改与删除功能?
不能。该功能依赖底层存储格式,仅在新创建的 Logstore 上生效。如需使用,请新建一个开启 enableModify 为 true 的 Logstore,并通过数据加工或 SDK 将历史数据迁移至新 Logstore。
修改或删除操作会影响实时消费吗?
不会。实时消费(日志中枢 LogHub)和投递任务基于原始写入流,不感知后续的修改或删除操作。仅查询(Search、SQL、SPL)等读路径能看到最新结果。
修改或删除操作是否立即可见?
是。请求成功返回后,后续查询请求即可看到最新结果。AffectedRows 返回的是实际生效的行数。
能否回滚一次误操作的修改或删除?
不能。修改和删除操作不可回滚。建议在执行前通过 Search 或 SQL 校验命中范围,并合理使用 RAM 权限管控修改和删除操作。对于高危批量操作,建议配置操作审计。
删除操作是否会立即释放存储空间?
删除是逻辑删除。日志在 Logstore TTL 到期前仍保留底层存储,但所有读路径会过滤掉已删除的记录。存储空间会随 TTL 到期或后台合并任务逐步释放。