トランザクション分離レベル
トランザクション分離レベルとは、データベース内で同時に実行される複数のトランザクションが互いにどの程度干渉しないようにするかを制御する設定です。これにより、データの一貫性を保ちながら、複数のトランザクションが同時に操作できるようにします。分離レベルが低いほどトランザクション間の干渉が増えますが、パフォーマンスが向上し、分離レベルが高いほどデータの整合性が強化されますが、パフォーマンスに影響が出る可能性があります。
レベル | 特徴 |
---|---|
Read uncommitted | ダーティリード、反復不能読み取り、ファントムリード、直列化異常が起こる |
Read committed | 反復不能読み取り、ファントムリード、直列化異常が起こる |
Repeatable read | ファントムリード、直列化異常が起こる |
Serializable | ダーティリード、反復不能読み取り、ファントムリード、直列化異常のいずれも起こらない |
1. Read Uncommitted(読取り非コミット)
特徴:
- トランザクションがコミットされていない変更も他のトランザクションから見える状態です。
- 他のトランザクションによってまだコミットされていないデータを読み取ることができるため、最も低い分離レベルです。
問題点:
- ダーティリード: 他のトランザクションがコミットしていない変更を読み取ってしまう可能性があります。そのため、そのトランザクションがロールバックされた場合、読み取ったデータが無効になるリスクがあります。
- 反復不能読み取り: 同じクエリを複数回実行しても、異なる結果が返る可能性があります。これは、他のトランザクションがデータを変更する可能性があるためです。
- ファントムリード: 同じクエリを繰り返して実行すると、前回のクエリには存在しなかった行が新たに現れることがあります。
- 直列化異常: 複数のトランザクションが同時に実行されることで、処理結果が直列実行とは異なる結果になる可能性があります。
2. Read Committed(読取りコミット)
特徴:
- トランザクションがコミットされた変更のみが他のトランザクションから見える状態です。
- PostgreSQLでは、デフォルトの分離レベルです。
問題点:
- 反復不能読み取り: 同じトランザクション内であっても、同じクエリを複数回実行した場合に、異なる結果が返る可能性があります。他のトランザクションがその間にコミットを行ってデータを変更した場合、この現象が起こります。
- ファントムリード: 同じクエリを繰り返して実行すると、前回のクエリには存在しなかった行が結果セットに新たに現れることがあります。
- 直列化異常: 複数のトランザクションが同時に実行されることで、処理結果が直列実行とは異なる結果になる可能性があります。
3. Repeatable Read(リピート可能読み取り)
特徴:
- トランザクションが開始された時点で存在するデータを基にして、クエリが実行されます。つまり、同じトランザクション内で同じクエリを複数回実行しても、常に同じ結果が返されます。
- 他のトランザクションによる変更が、現在のトランザクション内で見えないようにすることができます。
問題点:
- ファントムリード: 他のトランザクションが新しい行を挿入した場合、同じクエリを実行したときに、以前は存在しなかった行が結果に含まれることがあります。
- 直列化異常: 他のトランザクションによる新規データの挿入がトランザクション内で見えないため、データの一貫性が完全には保証されない可能性があります。
4. Serializable(直列化可能)
特徴:
- 最も高い分離レベルであり、すべてのトランザクションが順次(直列に)実行されたかのように動作します。
- データの一貫性が最も強く保証され、ファントムリードや直列化異常が発生しないように設計されています。
メリット:
- ダーティリード、反復不能読み取り、ファントムリード、直列化異常のいずれも発生しません。データベース内のデータ整合性が完全に保たれます。
デメリット:
- トランザクションの同時実行性が大幅に制限されるため、システムのパフォーマンスに影響を与える可能性があります。特に、ロックの競合が増えると、トランザクションの実行が遅くなることがあります。