3秒でわかる
データベースで、それまでの変更をまとめて確定させる操作。途中で失敗したら全部を無かったことにできるロールバックと対になり、中途半端な状態を防ぎます。
もう少し詳しく
どういうものか
データベースのコミットは、トランザクションの中で行った変更を確定し、他の利用者からも見える状態にする操作です。コミットするまでの変更は、自分の作業中の状態にすぎません。
BEGIN;
UPDATE accounts SET balance = balance - 5000 WHERE id = 1;
UPDATE accounts SET balance = balance + 5000 WHERE id = 2;
<a href="/glossary/commit" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">COMMIT</a>;途中で問題が見つかったときは ROLLBACK で、BEGIN の直前まで戻せます。
なぜ必要か
振込のように、2 つの更新が両方成功して初めて正しい処理があります。1 つ目の UPDATE が終わった直後にサーバーが落ちたら、片方から引かれただけでもう片方に入っていない状態が残ります。コミットの仕組みは、この「中途半端な状態」を外から見せないためにあります。まとめて成立するか、まとめて無かったことになるか、そのどちらかにします。
具体例
Python から扱うときも同じです。
conn = sqlite3.connect("shop.db")
try:
cur = conn.cursor()
cur.execute("INSERT INTO orders(user_id, amount) VALUES(?, ?)", (1, 5200))
cur.execute("UPDATE stocks SET qty = qty - 1 WHERE item_id = ?", (77,))
conn.commit()
except Exception:
conn.rollback()
raiseつまずきやすいところ
コミットを忘れて「データが入らない」と悩む例が多いです。自動コミットが有効なライブラリと、明示的なコミットが必要なライブラリがあり、挙動が違います。自分が使っているドライバの既定値を確かめます。
長すぎるトランザクションも問題になります。BEGIN してから何分も放置すると、その行にロックがかかったままになり、他の処理が待たされます。読み込んで、確認して、更新して、すぐコミットする、という短い単位に切ります。
DDL の扱いも注意が要ります。MySQL では CREATE TABLE などが暗黙のコミットを起こし、その時点までの変更が確定します。
似た用語との違い
Git のコミットは自分の手元に記録を残す操作で、他人に見せるには push が要ります。データベースのコミットは、確定した瞬間から全員に見えます。名前は同じでも、見える範囲が変わる点が違います。