「ずっと待ってるのに何も進まない…」PostgreSQLのデッドロックって結局なに?
データベースを触り始めると、一度は耳にする(そして少し怖い)言葉、「デッドロック」。
エンジニアの先輩たちが「あ、これデッドロックしてるわ」なんて顔を見合わせているのを見て、「一体何が起きているんだろう?」と不安になったことはありませんか?
今日は、このデッドロックという現象を、専門用語を抜きにして、皆さんの日常にある「あるある」に例えて解説してみますね。これを読めば、もう怖くありませんよ!
—
デッドロックを「行列」に例えてみよう
想像してみてください。あなたは今、とある超人気カフェのレジに並んでいます。
- あなた(トランザクションA):コーヒーを受け取るために、レジでお会計中。
- 後ろの人(トランザクションB):お会計を済ませて、すぐ横にある「砂糖・ミルクコーナー」に行きたい。
ここで、こんな状況が起きたとします。
1. あなたは、お会計を終えるために「砂糖・ミルクコーナー」の場所を通らなければいけません。
2. 後ろの人は、あなたがお会計を終えるのを待っています。
3. しかし! あなたが「砂糖・ミルクコーナー」に行こうとすると、そこにはすでに後ろの人が場所を占領していて、「邪魔だよ、どいてくれ」と動いてくれません。
4. 後ろの人は、「早くあなたがレジを終わらせてくれないと、自分がそこにたどり着けない」と言って動きません。
結果、あなたも後ろの人も、お互いが「相手が動くのを待っている」状態になり、永遠に列が動きません。
これが「デッドロック」の正体です。データベースの世界では、「お互いが相手の持っているデータ(ロック)を欲しがって、永遠に譲り合わない状態」のことをこう呼ぶんです。
PostgreSQLは「凄腕の店員さん」
じゃあ、このままじゃカフェの行列は一生解消されませんよね。でも、PostgreSQLというシステムは、そんなお人好しではありません。
PostgreSQLは、まるでカフェの店員さんのように、この「膠着(こうちゃく)状態」を常に監視しています。
もし、トランザクションAとトランザクションBが「ずっと待っている」ことを検知すると、PostgreSQLは瞬時にこう判断します。
「あ、これはダメだ。このままじゃ一生終わらないから、片方を強制終了させよう!」
そうして、どちらか一方のトランザクションを「お前は一度引き下がれ!」とエラーにして追い返します。追い返された方は、「あ、ダメだったか…」と一度諦めて、後でもう一度やり直すことになります。
こうすることで、残されたもう一方は無事に処理を進めることができるんです。
なぜこんなことが起きるの?
デッドロックは、主に「複数の作業を、バラバラの順番で処理しようとした時」に起こりやすいです。
例えば、
- あなた:Aの棚を確保してから、Bの棚を触る。
- 相手:Bの棚を確保してから、Aの棚を触る。
このように、「掴む順番」が逆転していると、デッドロックの罠にはまりやすくなります。
どうやって対策すればいいの?
初心者の方がまず意識すべきことは、これだけです。
- 「データの更新順序をプログラム全体で統一する」
「Aの処理をする時は、必ずA→Bの順番でロックを取る」とルールを決めておけば、そもそもデッドロックは起きにくくなります。まるで、カフェの列を「入り口から並ぶ」と決めておくようなものですね。
—
まとめ:恐れることはありません!
デッドロックは、データベースが「これ以上待っていても無駄だよ」と教えてくれる、いわば「整理のサイン」です。
もしエラーが出ても、「あ、今はちょっとタイミングが重なっちゃったんだな」と冷静に受け止めてください。多くの場合、少し時間を置いてから再試行すれば、何事もなかったかのように解決します。
データベースは、私たちが思っているよりもずっと賢く、私たちのデータを守ってくれています。失敗を恐れず、色々な処理を試してみてくださいね!
それでは、また次回の記事でお会いしましょう!
コメント