これはなに
外部キー制約で発生するデッドロックとその回避方法についてまとめ
わしはなんも知識がないので前提を調べるところから
目次
- 前提知識
- 外部キーとは
- 外部キー制約とは
- デッドロックとは
- なぜ外部キー制約によるデッドロックが発生するのか
- 概要
- MySQLの場合
- PostgreSQLの場合
- 解消方法
1. 前提知識
外部キーと外部キー制約
- 外部キーについて
- リレーションRの属性Fが他のリレーションSの主キーKを参照しているとき、Fは外部キーである
- 外部キー制約について
- 解説書から引用
(外部キー)RとSをリレーションスキーマとする(RとSは必ずしも異なっていない必要はない).このとき、Rの属性集合F(⊆ΩR)がSの外部キー(foreign key)であるとは、Sの主キーをK(⊆ΩS)とするとき、Rの任意のインスタンスRに対して、SのあるインスタンスSがそんざいしていて、次が成立するときをいう。
(∀t∈R)((∃u∈S)((t[F]=u[K])∨(t[F]がーである)))
(『リレーショナルデータベース入門[第3版]』p40より引用)
- なにが書いてあるかパッとだと分かんないんだけど、要するに下記
- Rの任意のタプルtに対し、tのF値と一致する主キーを持つSのタプルuが存在する/またはtのF値は空である
デッドロック
- 複数トランザクションが並行した際に、お互いがお互いの使いたい資産をロックすることで起きる袋小路のこと
2. なぜ外部キー制約によるデッドロックが発生するのか
概要
- 外部キーを持つテーブルの任意のレコードを操作した際、親テーブルにもレコード単位の共有ロックがかかる
- 詳細は利用するRDBによって異なるらしい
MySQLの場合
PostgreSQLの場合
- ガッツリとした言及はない気がする
- 同時実行制御
- ここの13.3あたりに記載あり
3. 解消方法
- 基本的に外部キー制約特有の解消方法とかはないはず
- デッドロック一般の回避方法をやれば良さそう
- 解消方法
- 起きないようにする
- リソースのアクセス順序を統一する
- 不必要にトランザクションを長くしない
- 不必要に占有ロックしない
- なるべく行ロックする
- 起きたとき
- タイムアウトやリトライ回数制限などで処理を切り上げる
- WebフレームワークのORMとか使ってると、デッドロック起きたら実行を諦めてくれる機能があったりする
感想
- Good
- トランザクションとデッドロックまわり、ふんわりとしか意識してなかったけど整理できて良かったです
- やれそう
- 処理がこけがちだったり遅いときにここら辺が関係してる、みたいなのはありそう
- デッドロックおきましたのログを見れるようになっておくと何かがはかどるかも