トランザクションで書き込みをアトミックにし、ACIDの保証が日々の実践で何を意味するのかを理解しましょう。
このレッスンを Kodokon で開く銀行の振込は二つのUPDATEです。一方の口座から引き落とし、もう一方に入金します。二つ目が失敗すると、データベースは嘘をつくことになります。トランザクションはそのブロックを分割不可能にし、ACIDの保証を与えます。Atomicity(原子性、全か無か)、Consistency(一貫性、制約が有効なまま保たれる)、Isolation(分離性、並行するトランザクションが互いの中途半端な状態を決して見ない)、Durability(永続性、COMMITはクラッシュを生き延びる)。このレッスンでは、本物のsqlite3クライアントを使うのがよいでしょう。一部のウェブのサンドボックスは、クエリごとに自動でコミットしてしまいます。
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
owner TEXT NOT NULL,
balance REAL NOT NULL CHECK (balance >= 0)
);
INSERT INTO accounts (owner, balance)
VALUES
('alice', 500.0),
('bruno', 120.0);通常のケース。BEGINがトランザクションを開き、書き込みが積み重なり、COMMITがそれらを一度に確定します。その間、他のどの接続も中間状態(aliceは引き落とし済み、brunoはまだ入金されていない)を見ることはありません。
BEGIN;
UPDATE accounts
SET balance = balance - 200
WHERE owner = 'alice';
UPDATE accounts
SET balance = balance + 200
WHERE owner = 'bruno';
COMMIT;
SELECT owner, balance FROM accounts;今度は失敗のケース。brunoから400を引き落とすとCHECK (balance >= 0)に違反します。その文は失敗します。SQLiteの微妙な点として、デフォルトでは、エラーは問題のある文を取り消しますが、トランザクションは開いたままにします。決めるのはあなたのアプリケーションコードの役目です。ROLLBACKですべてを取り消す(まっとうな反射)か、エラーが回復可能なら続行するか。
BEGIN;
UPDATE accounts
SET balance = balance - 400
WHERE owner = 'bruno';
-- Error: CHECK (balance >= 0) rejects the row.
ROLLBACK;
SELECT owner, balance FROM accounts;