オブジェクトのバージョン管理と保持期間
現在の版、残っている旧版、削除マーカーを追跡し、見えなくなったことと保存データが消えたことを分けて説明します。
説明
オブジェクトストレージでは、keyがオブジェクトの名前を表します。世代管理を有効にすると、同じkeyへの上書きで新しいversionが作られ、古い内容も残ります。通常の削除では内容をすべて消す代わりに、削除マーカーが現在の版になる場合があります。
世代管理を有効にしたreports/total.txtへ、total=100とtotal=120を順に保存します。削除後の取得と版指定の取得を比較し、旧版になってから7日という保存条件で、削除対象になる時刻を計算します。この例ではS3と同じく翌日のUTC 00:00へ切り上げた時刻を使います。
現在の版、残っている旧版、削除マーカーを追跡し、見えなくなったことと保存データが消えたことを分けて説明します。
1同じキーに最初のバージョンを保存する
世代管理の記録を初期化し、11月1日09:00 UTCにtotal=100を保存します。
python3 objects.py init世代管理を有効にしたkeyの記録を用意する
python3 objects.py put --file v1.txt最初の内容を保存する --at 2026-11-01T09:00:00+00:00
python3 objects.py get現在の版の内容を読むversion=v001でtotal=100です。SHA-256は保存した内容のバイト列を照合する値で、version IDそのものとは別です。
2同じキーのオブジェクトを上書きする
11月3日09:00 UTCにtotal=120を保存します。
python3 objects.py put --file v2.txt同じkeyへ新しい内容を保存する --at 2026-11-03T09:00:00+00:00
python3 objects.py get現在の内容を確認する
python3 objects.py list旧版になった時刻と保存量を読む現在の版はv002、内容は120です。v001は残り、noncurrent_sinceは11月3日になります。旧版の保存期間を数える起点は、最初に作成した11月1日ではありません。
3削除でマーカーを現在の版にする
11月4日09:00 UTCに版を指定しない削除を行った記録を作ります。
python3 objects.py delete版指定なしの削除マーカーを作る --at 2026-11-04T09:00:00+00:00
python3 objects.py list残る旧版と現在のマーカーを読むv003が削除マーカーになり、v001とv002は残っています。保存本文は10バイトずつの合計20バイトです。削除マーカーの情報自体を含む実サービスの課金量ではなく、ここでは本文の合計を表示しています。
4現在の版を取得した結果
版を指定せずに取得します。
python3 objects.py get現在の版として取得する現在が削除マーカーなので404になります。この結果だけを見て、旧版のデータまで消えたと判断することはできません。
5旧版を指定して取得する
v001を明示して読みます。
python3 objects.py get --version v001最初の版を明示して取得するtotal=100を取得できます。削除マーカーが現在でも、保持されている旧版を指定すればその内容を読めます。版指定の取得に必要な権限は別途必要です。
6旧版になった時刻から期限を計算
11月10日00:00 UTCの時点で、旧版を削除対象として評価します。旧版になった時刻へ7日を加え、翌日のUTC 00:00に切り上げます。
python3 objects.py expire --at 2026-11-10T00:00:00+00:00対象時刻より前の判定を確認する
python3 objects.py listまだ残る版を確認するv001は11月3日09:00から7日後の11月10日09:00を、11月11日00:00へ切り上げます。v002の対象時刻は11月12日00:00です。この時点ではどちらも残ります。
7最初の旧版だけが対象になる日
11月11日00:00 UTCとして評価します。
python3 objects.py expire --at 2026-11-11T00:00:00+00:00最初の旧版が対象となる時刻で評価する
python3 objects.py list版ごとの対象時刻の差を確認するv001が削除され、v002とv003だけが残ります。v002が旧版になったのは11月4日なので、v001と同時には削除されません。実サービスでは、対象時刻になった瞬間の物理削除完了を保証するものではありません。
8本文がすべてなくなってもマーカーは残る
翌日の11月12日00:00 UTCで評価します。
python3 objects.py expire --at 2026-11-12T00:00:00+00:00二番目の旧版が対象となる時刻で評価する
python3 objects.py list本文の量とマーカーの件数を確認するv002も削除され、本文は0バイトです。現在のv003は削除マーカーとして残り、版の件数は1です。本文の保存期間と、不要になったマーカーの整理は別の処理です。
9旧版のない削除マーカーを整理する
旧版が一つも残っていない削除マーカーを取り除きます。
python3 objects.py cleanup旧版のない削除マーカーを除去する
python3 objects.py list残存する版がないことを確認するversions=0になります。上書き、通常の削除、旧版の期限切れ、マーカーの整理によって、何が残るかがそれぞれ変わりました。
まとめ
上書きは新しい版を作り、通常の削除では旧版が残る場合があります。
旧版の期限は、作成時刻ではなく旧版になった時刻を基準に確認します。
本文の削除と削除マーカーの整理を別々に追跡します。
操作履歴と解説を振り返れます。
シェル / Python 3
python3 objects.py init
python3 objects.py put --file v1.txt --at 2026-11-01T09:00:00+00:00
python3 objects.py getversioning=enabled key=reports/total.txt created v001 delete_marker=False version=v001 sha256=672b81d937db6951936238de4028bee103b91fb1627a817d0073f172533f0a7d total=100
python3 objects.py put --file v2.txt --at 2026-11-03T09:00:00+00:00
python3 objects.py get
python3 objects.py listcreated v002 delete_marker=False version=v002 sha256=fee7d664b5d6f2edc62952a67d6c0c5acde29eebdf9457d6b423e5d011593460 total=120 v001 current=False marker=False created=2026-11-01T09:00:00+00:00 noncurrent_since=2026-11-03T09:00:00+00:00 v002 current=True marker=False created=2026-11-03T09:00:00+00:00 noncurrent_since=None versions=2 stored_body_bytes=20
python3 objects.py delete --at 2026-11-04T09:00:00+00:00
python3 objects.py listcreated v003 delete_marker=True v001 current=False marker=False created=2026-11-01T09:00:00+00:00 noncurrent_since=2026-11-03T09:00:00+00:00 v002 current=False marker=False created=2026-11-03T09:00:00+00:00 noncurrent_since=2026-11-04T09:00:00+00:00 v003 current=True marker=True created=2026-11-04T09:00:00+00:00 noncurrent_since=None versions=3 stored_body_bytes=20
python3 objects.py get404 delete marker is current
python3 objects.py get --version v001version=v001 sha256=672b81d937db6951936238de4028bee103b91fb1627a817d0073f172533f0a7d total=100
python3 objects.py expire --at 2026-11-10T00:00:00+00:00
python3 objects.py listv001 eligible_at=2026-11-11T00:00:00+00:00 expired=False v002 eligible_at=2026-11-12T00:00:00+00:00 expired=False v001 current=False marker=False created=2026-11-01T09:00:00+00:00 noncurrent_since=2026-11-03T09:00:00+00:00 v002 current=False marker=False created=2026-11-03T09:00:00+00:00 noncurrent_since=2026-11-04T09:00:00+00:00 v003 current=True marker=True created=2026-11-04T09:00:00+00:00 noncurrent_since=None versions=3 stored_body_bytes=20
python3 objects.py expire --at 2026-11-11T00:00:00+00:00
python3 objects.py listv001 eligible_at=2026-11-11T00:00:00+00:00 expired=True v002 eligible_at=2026-11-12T00:00:00+00:00 expired=False v002 current=False marker=False created=2026-11-03T09:00:00+00:00 noncurrent_since=2026-11-04T09:00:00+00:00 v003 current=True marker=True created=2026-11-04T09:00:00+00:00 noncurrent_since=None versions=2 stored_body_bytes=10
python3 objects.py expire --at 2026-11-12T00:00:00+00:00
python3 objects.py listv002 eligible_at=2026-11-12T00:00:00+00:00 expired=True v003 current=True marker=True created=2026-11-04T09:00:00+00:00 noncurrent_since=None versions=1 stored_body_bytes=0
python3 objects.py cleanup
python3 objects.py listexpired delete marker removed versions=0 stored_body_bytes=0
演習完了