Dev Study
← 研修トップ

データの入口

行に順番はあるのか。索引を足すと答えは変わるのか。COMMIT の前にエラーが出たら何が残るのか。「重複を確かめてから入れる」がなぜ重複を防げないのか。データベースが引き受けるのは、順序も一意性も「全部か無しか」も、宣言された分だけです。『データベースの仕組み』の前に読む入口として、Codd の原論文と PostgreSQL・MySQL の公式文書、そして実機の出力から積み上げます。

  1. 1
    行には順番がない — 並びは、頼んだときだけ保証される
    ORDER BY を付けない SELECT は、行を決まった順では返しません。PostgreSQL 18 で3行の表の1行を更新しただけで、同じ問い合わせの並びが 1,2,3 から 2,3,1 に変わりました。
    約 8 分
  2. 2
    問い合わせは道筋を書かない — 索引は答えを変えず、道筋を変える
    SQL の問い合わせに書くのは「どんな行が欲しいか」という条件だけで、どうやって探すかという道筋は書きません。だから索引を作っても消しても、返ってくる行の集合は変わりません。
    約 8 分
  3. 3
    全部か無しか。境界は BEGIN と COMMIT で宣言する
    トランザクションは複数の文を「全部か無しか」にまとめる仕組みです。その「全部」がどこからどこまでかは、データベースが推し量るのではなく、アプリが BEGIN と COMMIT で宣言します。
    約 8 分
  4. 4
    「コミットが返った」は、どこまで届いたことか
    既定の PostgreSQL は、変更の記録(WAL)がディスクへ書き出されるのを待ってから COMMIT の成功を返します。だから返った直後にサーバが落ちても変更は残ります。これが ACID の D(永続性)です。
    約 8 分
  5. 5
    原子性は割り込みを防がない — 読んでから書く間に消える更新
    値を読み、アプリで足し、書き戻す。これを2つのトランザクションが同時に行うと、両方ともエラーなくコミットしたのに片方の更新が消えることがあります。どちらも「全部か無しか」は守られています。
    約 9 分
  6. 6
    一意性は、宣言したときだけ存在する
    「同じメールアドレスが無いか確かめてから INSERT する」を2つの接続で同時に走らせると、制約を宣言していない表には同じ行が2つ入ります。どちらのトランザクションも正しくコミットした結果であり、データベースは「一つしかない」ことを知らされていないので止めません。
    約 9 分
  7. 7
    一つの事実を一か所に置く — 正規化は、守らせたい事実をキーに変えること
    顧客名を注文の行ごとに書き写した表で1行だけ名前を直すと、同じ顧客に名前が2つ残ります。データベースは壊れていません。「顧客1人に名前は1つ」とは、どこにも宣言されていなかったからです。
    約 9 分