Simple Log Service は、Logstore に書き込まれたデータの行レベルでの更新と削除をサポートしています。Logstore の作成時にこの機能を有効にすることで、OpenAPI または Python SDK を使用して、RowID またはクエリによるログデータの変更と削除が可能になります。
概要
デフォルトでは、Logstore は追記専用の不変モデルに従います。データが Logstore に書き込まれた後は、その場で変更または削除することはできません。
一部のシナリオでは、Logstore 内の既存データを変更または削除する必要があります。
-
フィールドの事後修正:元のログが書き込まれた後に、注文ステータス、リスクラベル、スコアリング結果などのビジネスフィールドを更新します。
-
テストデータのクリーンアップ:本番環境の Logstore からテストレコードまたはカナリアレコードを削除します。
-
単一レコードの修復:ビジネスのリプレイまたは照合ワークフロー中に特定のログエントリを修正します。
Simple Log Service は、Logstore 単位で 行レベルの更新と削除 機能を提供します。RowID による個別レコードの変更・削除、またはクエリによるレコードの一括変更・削除が可能です。
この機能を使用する前に、以下の点に注意してください。
-
この機能は 新規の Logstore でのみ利用できます。Logstore の作成時に
enableModifyをtrueに設定してください。既存の Logstore に対してこの機能を有効にすることはできません。 -
一度有効にすると、この機能を無効にすることはできません。Logstore を作成する前に、十分に計画してください。
-
すべての変更および削除操作は 元に戻すことができません。組み込みのロールバック機能はありません。
-
リアルタイムコンシューマー (LogHub) および配信タスクには、変更または削除が 通知されません。クエリベースの読み取りパス (Search、SQL、SPL) のみが最新のデータを返します。
基本概念
RowID
RowID は、行レベルの更新と削除が有効になっている Logstore 内の各ログエントリに Simple Log Service が割り当てる論理識別子です。すべての変更および削除操作は、RowID を使用して対象レコードを特定します。
-
形式:RowID は書き込み時に生成され、カスタマイズすることはできません。不透明な識別子として扱ってください。
-
安定性:RowID は、レコードが変更された後でも、ログレコードのライフサイクル全体を通じて変わりません。
-
可視性:クエリ結果には、組み込みの
__rowid__フィールドが自動的に含まれます。このフィールド名は予約されており、インデックス設定で使用することはできません。
AffectedRows
変更または削除リクエストが成功するたびに、 AffectedRows (実際に影響を受けたログレコード数) が返されます。この値を使用して、操作が期待どおりに実行されたことを確認してください。
AffectedRows は、HTTP レスポンスボディの x-log-affectedrows で返されます。Python SDK では、 resp.affected_rows を通じて読み取ることができます。
前提条件
以下の要件が満たされていることを確認してください。
-
Simple Log Service プロジェクトが作成されていること。詳細については、「プロジェクトの作成」をご参照ください。
-
enableModifyパラメータがtrueに設定された Logstore が作成されていること。本トピックの「機能の有効化」をご参照ください。 -
呼び出し元に
log:UpdateLogStoreLogsおよびlog:DeleteLogStoreLogsの RAM 権限が付与されていること。本トピックの「必要な RAM 権限」をご参照ください。 -
(条件付き) クエリベースの操作を使用する場合、クエリで参照されるフィールドにインデックスが設定されている必要があります。
機能の有効化
行レベルの更新と削除を使用するには、CreateLogStore API を呼び出す際に enableModify パラメータを true に設定します。
-
enableModifyは、新規の Logstore を作成するときにのみ設定できます。既存の Logstore に対してこの機能を有効にすることはできません。 -
enableModifyをtrueに設定した後は、無効にすることはできません。 -
この機能は、OpenAPI または SDK を通じてのみ有効にできます。Simple Log Service コンソールではこの機能をサポートしていません。
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,
)
データの変更と削除
ログデータの変更と削除には、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: クエリによる変更と削除
クエリ条件に一致するレコードを一括で変更または削除するには、この方法を使用します。クエリはサーバー側で実行され、一致するすべてのレコードに対して変更または削除が適用されます。
この操作は元に戻すことができません。
-
操作が部分的に失敗した場合でも、すでに変更または削除された行は ロールバックされません。レスポンスには、実際に影響を受けた行数のみが返されます。
-
実行する前に、Search または 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 の確認:各リクエストは、レスポンスで
AffectedRowsを返します (HTTP レスポンスボディのx-log-affectedrowsまたは Python SDK のresp.affected_rows)。この値を期待されるレコード数と比較してください。-
AffectedRows > 0で期待値と一致する場合:操作が成功しました。 -
AffectedRows = 0の場合:条件に一致するレコードがないか、レコードがすでに削除されています。クエリまたは RowID を再確認してください。 -
AffectedRowsが期待値より少ない場合:部分的な失敗が発生した可能性があります。残りのレコードに対して操作を再実行してください。
-
-
フォローアップクエリの実行:一括操作の場合、操作後に Search または SQL クエリを実行して、データが期待どおりの状態になっていることを確認してください。これは、
AffectedRowsが期待値より少ない場合に特に重要です。
データ整合性
変更および削除操作は同期的に反映されます。リクエストが成功した後、後続のクエリ (Search、SQL、SPL) は更新された結果を返します。
以下の動作に注意してください。
-
リアルタイム消費は影響を受けません:LogHub コンシューマーおよび配信タスク (OSS または MaxCompute への配信など) は、元の書き込みストリームで動作します。これらは変更または削除を反映しません。クエリベースの読み取りパスのみが最新のデータを返します。
-
クエリベースの操作はアトミックではありません:サーバーは一致する各レコードを個別に処理します。部分的な失敗が発生した場合、すでに処理されたレコードはロールバックされません。レスポンスには、実際に影響を受けた行数が返されます。
必要な RAM 権限
変更または削除 API を呼び出す 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 への配信など) には、変更または削除が通知されません。クエリベースの読み取りパス (Search、SQL、SPL) のみが最新のデータを返します。 |
課金
-
変更操作:変更操作は現在課金されません。将来的には、変更されたデータによって生成されるストレージ容量に基づいて課金されます。
-
削除操作:削除操作には追加料金は発生しません。
よくある質問
既存の Logstore に対してこの機能を有効にできますか?
いいえ。この機能には、Logstore 作成時にのみ利用可能なストレージ形式が必要です。 enableModify=true で新規の Logstore を作成し、データ変換または SDK を通じて過去のデータを移行してください。
変更および削除操作はリアルタイムコンシューマーに影響しますか?
いいえ。LogHub コンシューマーおよび配信タスクは元の書き込みストリームで動作し、変更または削除を反映しません。クエリベースの読み取りパス (Search、SQL、SPL) のみが最新のデータを返します。
変更と削除はすぐに反映されますか?
はい。リクエストが成功した後、後続のクエリは更新されたデータを返します。レスポンスの AffectedRows 値は、実際に変更または削除されたレコード数を示します。
誤った変更または削除をロールバックできますか?
いいえ。組み込みのロールバック機能はありません。変更または削除操作を実行する前に、Search または SQL で一致するレコードをプレビューしてください。制限された権限を持つ専用の RAM ユーザーを使用し、監査のために ActionTrail を有効にすることを推奨します。
削除するとすぐにストレージ容量が解放されますか?
削除は論理的な操作です。基盤となるストレージは、Logstore の TTL が期限切れになるか、バックグラウンドでコンパクションが実行されるまで保持されます。すべてのクエリパスは削除されたレコードをフィルタリングするため、削除されたデータはユーザーには表示されません。