PostgreSQLがデッドロックを検知したとき、セッション切るのは後勝ちでも先勝ちでも無く雰囲気でセッション切ってくるのはなんとかならんのか(ならん気がする。
— そーだい@初代ALF (@soudai1025) 2017年11月6日
正確には次の通り。
デッドロックの自動対応について
- デッドロックを検出するとPostgreSQLは該当のトランザクションのどれか(後述)をabortします(ロールバックではない)
- トランザクションをabortされるとPostgreSQLはその後のSQLに全てErrorを返します。
- その為、そのセッション中のトランザクションはabortedになるので自分でロールバックするか自らセッションを切断して(切るとロールバックされるので)セッションを接続し直すかをしないとQueryを実行できなくなる
デッドロックの検出方法
- デッドロックについては正確にはロック獲得待ちのトランザクションに対してdeadlock_timeoutに設定した秒数毎にデッドロックかチェック
- このチェックに該当した方がデッドロックとしてトランザクションをabort
- チェックに先に引っかかる方をabortするのでどちらをabortするかはチェックのタイミング次第
- そのため、どちらのトランザクションがabortされるかアプリケーションやユーザ側から任意に指定(判断すること)が出来ない
参考までにこちらをどうぞ。
6. ロック制御 · PostgreSQL Internals
(PostgreSQLで大切なことは postgresql internalsでカバーできるのですごい便利)
ちなみにMySQL
マジで雰囲気なの?MySQLだと「更新量が多い方のトランザクションが生き残る」だけど、そういうルールないんですか?あと「セッションを切る」の?「セッションは生き残るけどトランザクションはロールバックされる」ではなくて? https://t.co/JgnBtoutCf
— atsuizo (@atsuizo) 2017年11月6日
MySQL、滅茶苦茶便利じゃん。
ちなみにdeadlock_timeoutはDefaultが1秒なのだけど1秒ごとにデッドロックをチェックするの結構重いのでロック待ちが発生するような設計の場合は10秒に伸ばしたりします。 (そもそもデッドロックが起きたらダメ)