Simple Log Service (SLS) では、Logstore に書き込み済みのデータを変更および削除できます。本トピックでは、行レベルの更新と削除機能を有効にする方法、および OpenAPI または Python SDK を使用して RowID またはクエリによりログデータを変更・削除する方法について説明します。
概要
デフォルトでは、Logstore は追記専用のイミュータブルモデルに従います。データが Logstore に書き込まれた後、インプレースで変更または削除することはできません。
一部のシナリオでは、Logstore 内の既存データを変更または削除する必要があります。
フィールドの遡及修正:元のログが書き込まれた後、注文ステータス、リスクラベル、スコアリング結果などのビジネスフィールドを更新します。
テストデータのクリーンアップ:本番環境の Logstore からテストレコードまたはカナリアレコードを削除します。
単一レコードの修復:ビジネスリプレイまたは照合ワークフロー中に特定のログエントリを修正します。
これらのシナリオに対応するため、SLS は Logstore 単位で 行レベルの更新と削除 機能を提供します。RowID により個別のレコードを変更または削除したり、クエリによりレコードを一括変更または一括削除したりできます。
この機能を使用する前に、以下の点に注意してください。
この機能は 新規作成する Logstore でのみ利用できます。Logstore を作成する際に
enableModifyをtrueに設定してください。既存の Logstore に対してこの機能を有効にすることはできません。一度有効にすると、この機能を無効にすることはできません。Logstore を作成する前に十分に計画してください。
すべての変更および削除操作は 元に戻すことはできません。組み込みのロールバック機能はありません。
リアルタイムコンシューマー (LogHub) と配信タスクは、変更または削除の 通知を受け取りません。クエリベースの読み取りパス (検索、SQL、SPL) のみが最新のデータを返します。
基本概念
RowID
RowID とは、行レベルの更新と削除が有効になっている Logstore に書き込まれた各ログエントリに SLS が割り当てる論理的なレコード識別子です。すべての変更および削除操作は、RowID を使用してターゲットレコードを特定します。
形式:SLS は書き込み時に RowID を生成します。RowID をカスタマイズまたは構築することはできません。不透明な識別子として扱ってください。
安定性:RowID はログレコードのライフサイクル全体を通じて変更されません。レコードを変更した後でも、同じ RowID がそのレコードを指し続けます。
可視性:この機能が有効になっている Logstore からのクエリ結果には、組み込みフィールド
__rowid__が自動的に含まれます。これは予約されたフィールド名であり、インデックス設定では使用できません。
AffectedRows
変更または削除リクエストが成功するたびに AffectedRows が返されます。これは、操作が実際に影響を与えたログレコードの数を示します。この値を使用して、操作が期待どおりに実行されたことを確認してください。
AffectedRows は HTTP レスポンスヘッダー x-log-affectedrows で返されます。Python SDK では、resp.affected_rows を通じて読み取ります。
前提条件
開始する前に、以下の要件を満たしていることを確認してください。
SLS プロジェクト。詳細については、「プロジェクトの作成」をご参照ください。
enableModifyパラメータがtrueに設定された Logstore。本トピックの 機能の有効化 をご参照ください。呼び出し元に付与された
log:UpdateLogStoreLogsおよびlog:DeleteLogStoreLogsの RAM 権限。本トピックの 必要な RAM 権限 をご参照ください。(条件付き) クエリベースの操作を使用する場合、クエリで参照されるフィールドにインデックスが設定されている必要があります。
機能の有効化
行レベルの更新と削除を使用するには、CreateLogStore API を呼び出す際に enableModify パラメータを true に設定します。
enableModifyは新しい Logstore を作成する際にのみ設定できます。既存の Logstore に対してこの機能を有効にすることはできません。enableModifyをtrueに設定した後、無効にすることはできません。この機能は OpenAPI または SDK を通じてのみ有効にできます。SLS コンソールはこの機能をサポートしていません。
OpenAPI による有効化
CreateLogStore API を呼び出し、リクエストボディで enableModify を true に設定します。
POST /logstores HTTP/1.1
Host: <project>.<endpoint>
Content-Type: application/json
{
"logstoreName": "my-logstore",
"ttl": 30,
"shardCount": 1,
"enableModify": true
}
Logstore を作成した後、GetLogStore API を呼び出して確認します。レスポンスボディに "enableModify": true が含まれていれば、機能が有効になっています。
Python SDK による有効化
from aliyun.log import LogClient
# 環境変数から AccessKey 認証情報を取得します。
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,
)
データの変更と削除
SLS は、ログデータを変更および削除するための 2 つの方法を提供しています。
方法 |
シナリオ |
リクエストあたりの最大行数 |
RowID による操作 |
ターゲットレコードの正確な RowID がわかっており、そのレコードを正確に変更または削除したい場合。 |
1 |
クエリによる操作 |
クエリ条件に一致するすべてのレコードを一括変更または一括削除したい場合。 |
10,000 |
方法 1: RowID による変更と削除
特定のレコードの 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"Affected rows: {resp.affected_rows}")
単一レコードの削除
resp = client.delete_logs_v2(
project="my-project",
logstore="my-logstore",
rowid=rowid,
)
print(f"Affected rows: {resp.affected_rows}")
同じレコードを複数回削除してもべき等です。操作はエラーを返しませんが、
affected_rowsは0を返します。同期削除には
delete_logs_v2を使用してください。従来のdelete_logsメソッドは非同期の論理削除を実行しますが、enableModifyが有効になっている Logstore ではサポートされていません。
方法 2: クエリによる変更と削除
クエリ条件に一致するレコードを一括変更または一括削除する場合に、この方法を使用します。SLS はサーバー側でクエリを実行し、一致するすべてのレコードに対して変更または削除を適用します。
この操作は元に戻すことはできません。
操作が部分的に失敗した場合、既に変更または削除された行は ロールバックされません。レスポンスは実際に影響を受けた行数のみを返します。
実行する前に、検索または SQL を使用してクエリ条件に一致するレコードをプレビューし、対象範囲を確認してください。
クエリベースの一括操作はリソースを大量に消費します。リクエストあたり 10,000 行の制限内に収まるよう、時間範囲を絞り込むか、クエリ条件を絞り込んでください。
クエリで参照されるフィールドにはインデックスが設定されている必要があります。設定されていない場合、クエリは結果を返しません。
クエリによる削除
resp = client.delete_logs_v2(
project="my-project",
logstore="my-logstore",
from_time=1716537600,
to_time=1716624000,
query='level: DEBUG',
)
print(f"Deleted rows: {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"',
update_fields={"status": "REFUNDED", "refund_at": "2026-05-25T10:00:00Z"},
)
print(f"Modified rows: {resp.affected_rows}")
同じリクエストで
rowidとqueryの両方を渡した場合、rowidが優先され、queryパラメータは無視されます。クエリベースの操作では、データがクエリ可能である必要があります。データインジェストからクエリ可能になるまで、数秒の遅延が発生する場合があります。
結果の確認
変更または削除操作を実行した後、結果を確認し、操作が期待どおりに成功したことを確かめます。
-
AffectedRows の確認:各リクエストはレスポンス (HTTP ヘッダー
x-log-affectedrowsまたは Python SDK のresp.affected_rows) でAffectedRowsを返します。この値を期待されるレコード数と比較してください。AffectedRows > 0で期待と一致する場合: 操作は成功しました。AffectedRows = 0の場合:条件に一致するレコードがないか、レコードは既に削除されています。クエリまたは RowID を再確認してください。AffectedRowsが期待よりも少ない場合: 部分的な失敗が発生した可能性があります。残りのレコードに対して操作を再実行してください。
-
フォローアップクエリの実行:一括操作の場合、操作後に検索または SQL クエリを実行して、データが期待される状態を反映していることを確認してください。これは
resp.affected_rowsが期待よりも少ない場合に特に重要です。
データ整合性
変更および削除操作は同期的に有効になります。リクエストが成功した後、以降のクエリ (検索、SQL、SPL) は更新された結果を返します。
以下の動作に注意してください。
-
リアルタイム消費は影響を受けません:LogHub コンシューマーと配信タスク (OSS や MaxCompute への配信など) は、元の書き込みストリームで動作します。変更や削除を反映しません。クエリベースの読み取りパスのみが最新のデータを返します。
-
クエリベースの操作はアトミックではありません:サーバーは一致する各レコードを個別に処理します。部分的な失敗が発生した場合、既に処理されたレコードはロールバックされません。レスポンスは実際に影響を受けた行数を返します。
必要な RAM 権限
変更または削除 API を呼び出す Resource Access Management (RAM) ユーザーまたはロールには、以下の権限が必要です。
アクション |
説明 |
|
RowID またはクエリによるログデータの変更。 |
|
RowID またはクエリによるログデータの削除。 |
リソース ARN の形式:
acs:log:<region>:<account-id>:project/<project-name>/logstore/<logstore-name>
変更および削除操作、特にクエリベースの一括削除には、専用の RAM ユーザーまたはロールを作成することを推奨します。これらの操作を監査するには ActionTrail を使用してください。
制限事項
項目 |
説明 |
新規 Logstore のみ |
Logstore を作成する際に |
無効化不可 |
この機能を有効にした後、無効にすることはできません。 |
クエリベースの操作あたりの最大行数 |
リクエストあたり 10,000 行。クエリが 10,000 件を超えるレコードに一致する場合、リクエストは拒否されます。時間範囲を絞り込むか、クエリ条件を絞り込んでください。 |
インデックス要件 |
クエリ条件として使用されるフィールドにはインデックスが設定されている必要があります。RowID による操作では、ビジネスフィールドのインデックスは不要です。 |
インデックスの再構築不可 |
この機能を有効にした後、Logstore はインデックスの再構築をサポートしません。 |
論理削除不可 |
この機能を有効にした後、非同期の論理削除はサポートされません。本トピックで説明されている同期削除インターフェース ( |
|
|
リアルタイムコンシューマーへの通知なし |
LogHub コンシューマーと配信タスク (OSS や MaxCompute への配信など) は、変更や削除の通知を受け取りません。クエリベースの読み取りパス (検索、SQL、SPL) のみが最新のデータを返します。 |
課金
変更操作:各変更操作により、更新されたデータに対する追加のインデックスストレージとインデックストラフィックの料金が発生します。
削除操作:削除操作では追加料金は発生しません。
よくある質問
既存の Logstore に対してこの機能を有効にできますか?
いいえ。この機能は、Logstore 作成時にのみ利用可能な基盤となるストレージ形式に依存しています。この機能を使用するには、enableModify=true で新しい Logstore を作成し、データ変換または SDK を通じて履歴データを新しい Logstore に移行してください。
変更および削除操作はリアルタイムコンシューマーに影響しますか?
いいえ。LogHub コンシューマーと配信タスク (OSS や MaxCompute への配信など) は、元の書き込みストリームで動作し、変更や削除を反映しません。クエリベースの読み取りパス (検索、SQL、SPL) のみが最新のデータを返します。
変更と削除は即座に反映されますか?
はい。リクエストが成功した後、新しいクエリは更新されたデータを返します。レスポンスの AffectedRows 値は、実際に変更または削除されたレコードの数を示します。
誤った変更または削除をロールバックできますか?
いいえ。組み込みのロールバック機能はありません。変更または削除操作を実行する前に、検索または SQL を使用してクエリ条件に一致するレコードをプレビューしてください。これらの操作には、制限された権限を持つ専用の RAM ユーザーを使用し、監査のために ActionTrail を有効にすることを推奨します。
削除により即座にストレージ領域が解放されますか?
削除は論理操作です。基盤となるストレージは、Logstore の Time to Live (TTL) が期限切れになるか、バックグラウンドのコンパクションタスクが実行されるまで保持されます。ただし、すべてのクエリパスは削除されたレコードをフィルタリングするため、削除されたデータはユーザーには表示されません。