UUIDv7は「時刻順」と「作成時刻」を保証しない
UUIDv7の時刻はずれることがあり、厳密な順序も保証されない。確実なのは一意性だけ。並び順や作成時刻を頼るなら、実装の動きを確かめてからにする。
#なぜ今日これを選んだか
自作アプリでは、記録のIDに時刻を埋め込んでいて、複数の端末から書き込んでいる。「IDが時刻順なら並べ替えはいらない」と思い込みやすいところなので、その前提がどこで崩れるかを知っておきたかった。
#要点
- RFC 9562 は、埋め込む時刻が実際の時刻にどれだけ近いかを定めていない。カウンタが溢れた時は時刻を先に進めることも認めている。Postgresのドキュメントにも、取り出した時刻は生成時刻と一致するとは限らないとある
- 著者がPythonの
uuid.uuid7()で時計を1時間戻すと、埋め込まれる時刻は止まったままになった。1ミリ秒に1件を超える負荷をかけ続けると、実際の時刻とのずれは約3,695秒から約3,995秒まで広がり続けた - 複数のノードにまたがる厳密な順序は、時計を十分に合わせられない以上は実現できない。再起動のあとに時計が戻ると、1台でも順番が逆転し得る。確実なのは一意性で、順序は「だいたい」と見ておく
#自分にとっての示唆
FORGEの会話ログは、IDに端末側の時刻を埋め込んでいる。今は問題が出ていないが、iPhone・iPad・Macから同時に書けば、端末ごとの時計のずれでIDの順番と実際の順番が入れ替わり得る。並び順は「IDの時刻」ではなく、サーバーが受け取った時刻を別の列に持って、それで決めるのが安全だ。明日からは、IDは「重複しない名札」、並び順は「受け取った時刻」と役割を分けて設計する。あわせて、Rustの uuid クレートが v7 で時計の巻き戻りをどう扱うかを、ソースで1か所だけ確かめてみる。