分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE
SQL標準の分離レベルとPostgreSQLの実装を比較し、ワークロードに適したレベルを選びます。
「分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
4つの標準レベル
SQL標準では、4つの分離レベルが定義されています。
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
PostgreSQLが実装しているのは3つです(READ UNCOMMITTED は READ COMMITTED と同じ動作をします)。
READ COMMITTED(PostgreSQLのデフォルト)
各ステートメントは、そのステートメントの開始前にコミットされたデータを参照します。1つのトランザクション内でも、異なるスナップショットが見える場合があります。
-- Inside one transaction:
SELECT balance FROM accounts WHERE id = 1; -- 100
-- meanwhile another tx commits balance=200
SELECT balance FROM accounts WHERE id = 1; -- 200 (non-repeatable read)REPEATABLE READ(スナップショット分離)
トランザクション開始時に取得されたスナップショットを参照します。同じ行を読み直すと、常に同じ値が返されます。PostgreSQLの REPEATABLE READ はファントムも防止します。
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT balance FROM accounts WHERE id = 1; -- 100
-- another tx commits balance=200
SELECT balance FROM accounts WHERE id = 1; -- still 100
COMMIT;SERIALIZABLE
最も強い分離レベルです。トランザクションが1つずつ順番に実行された場合と同じ結果になります。PostgreSQLはSerializable Snapshot Isolation(SSI)を使用し、同時実行される依存関係を検出して、競合するトランザクションを中止します。
BEGIN ISOLATION LEVEL SERIALIZABLE;
...
COMMIT;
-- ERROR: could not serialize access due to read/write dependencies分離レベルの設定
トランザクション単位、セッション単位、またはグローバルに設定できます。
-- Per transaction:
BEGIN ISOLATION LEVEL SERIALIZABLE;
-- Per session:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Default for new transactions in this session:
SET default_transaction_isolation = 'repeatable read';
-- Global default in postgresql.conf:
-- default_transaction_isolation = 'read committed'各レベルで許可される異常
| レベル | ダーティ | 非反復 | ファントム |
|---|---|---|---|
| READ UNCOMMITTED | あり得る | あり得る | あり得る |
| READ COMMITTED | なし | あり得る | あり得る |
| REPEATABLE READ | なし | なし | なし(PGでは) |
| SERIALIZABLE | なし | なし | なし |
パフォーマンス上のトレードオフ
- READ COMMITTED — オーバーヘッドが最小で、デフォルト
- REPEATABLE READ — 同じプランとスナップショットの一貫性が得られ、書き込み競合がない限りパフォーマンスへの影響はない
- SERIALIZABLE — 追加の管理処理が必要で、トランザクションが中止される可能性があるため、アプリケーションにリトライ処理が必要
SERIALIZABLEのリトライパターン
SERIALIZABLE はコード 40001 で中止される場合があります。ループでリトライします。
for (let i = 0; i < 3; i++) {
try {
await client.query('BEGIN ISOLATION LEVEL SERIALIZABLE');
// ... work ...
await client.query('COMMIT');
break;
} catch (e) {
if (e.code === '40001') continue;
throw e;
}
}一貫性のあるスナップショットの読み取り
一貫性のあるデータを必要とする長時間実行の分析クエリには、REPEATABLE READ が適切なバランスです。
書き込み競合の動作
2つのトランザクションが同じ行を変更する場合:
- READ COMMITTED — 2つ目は待機し、その後、新しい行を読み直して再試行する
- REPEATABLE READ — 2つ目は「could not serialize」で中止されるため、アプリケーションでリトライが必要
適切なレベルを選ぶ
目安は次のとおりです。
- OLTP — READ COMMITTED(デフォルト)
- 一貫性が必要なレポート — REPEATABLE READ
- 金銭処理・在庫 — SERIALIZABLE + リトライ、または明示的なロック(FOR UPDATE)
明示的なロックが分離レベルを上回る場合
単一の競合の多い行では、READ COMMITTED で SELECT ... FOR UPDATE を使うほうが、SERIALIZABLE より単純な場合がよくあります。
まとめ
分離レベルでは、安全性と同時実行性のバランスを取ります。
- READ COMMITTED がデフォルト
- 一貫性のある読み取りには REPEATABLE READ
- 「直列実行と同じ」結果には SERIALIZABLE — リトライ処理が必要
クイックチェック
PostgreSQLのデフォルトの分離レベルはどれですか。
よくある質問
「分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE」レッスンは無料ですか?
はい。「分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE」で何を学びますか?
SQL標準の分離レベルとPostgreSQLの実装を比較し、ワークロードに適したレベルを選びます。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ACID特性とアノマリー
- 分離レベル:READ COMMITTED、REPEATABLE READ、SERIALIZABLE
- デッドロック:検出と回避
- 楽観的ロックと悲観的ロック