1. ホーム
  2. データベース
  3. デービーツー

DB2 のデッドロック解決プロセスが完全に文書化されています。

2022-01-19 11:32:13

本番環境で使用しているデータベースはDB2ですが、最近、select sql文が必ずデッドロックになるという不思議なデッドロックが頻発しています。

以前は、デッドロックの問題を引き起こすのは、たいていupdate/deleteなどの更新sql文でした。そして、このselect sql文は、大量のデータを扱うわけでもない、ごく一般的なsqlなのです。

このデッドロックを分析すると、難しいことがたくさんあるんです。

1. 本番環境のデータ量が多いため、本番環境の関連テーブルからテスト環境にデータを取り込めない。つまり、データ量のシミュレーションができない。
2. ログが出力されない。これは本番環境のログ出力レベルがERRORであるためです。
3, お客様が許可していないため、本番環境でのテストができない。
4, 本番環境のデータベースは、スナップショットなどの機能を有効にすることができません。パフォーマンスに影響が出るから。

ご想像の通り、スナップショットのような機能がなければ、デッドロックの解析はコードの解析に委ねられることになります。しかし、これは扱いが非常に複雑で、コードの解析だけでは手がかりがない。
ステージ1:データ量が原因だと思われます

本番環境では例外的にデータ量が多いため、この処理には他に多くのテーブルがあります。そこで、「大量のデータによってシステムに負荷がかかり、デッドロックが発生しているのでは?
そこで、デッドロックが発生したときのCPU、ハードディスク、ネットワークなどの負荷情報を取得しました。手がかりは見つかりませんでした。
第2段階:テスト環境で複数のユーザーを模擬して、複数のスレッドを使ってこの処理を行うテストプログラムを作成する。

このデッドロックを開発環境で再現できるようにするため、マルチスレッドのテストプログラムを作成し、マルチユーザーでの実行をシミュレートしました。残念ながら、それでも再現できませんでした。
フェーズ3:テスト環境データベースと製品環境データベースの差異を分析する
この時点では、やはりデータ量の多さが原因ではないかと考えていました。そこで、開発環境でも製品環境と同じように、できるだけ多くのデータを取得するようにしました。
その後、テストを実施したところ、やはり再現できませんでした。
ステージ4:ユーザーの行動ログを分析する

どうにもならないので、ユーザーの行動ログを解析して、そこから少しでも手がかりを見つけようとしたのです。しかし、なかなかうまくいかず、2人が同時に
この操作を2人が同時に行うと、基本的にデッドロックが発生します。そこで、この問題は2人が同時に操作することで発生すると判断しました。ところが、なぜか開発環境ではシミュレーションを行い
多くの人がやっているのに、なぜデッドロックが起きないのか?
第5ステージ データベース設定の問題点を発見する

再度テストプログラムを修正し、シミュレーションのユーザー数を増やしましたが、残念ながらまだ問題は再現されませんでした。このとき、私たちは、開発環境の
製品環境のデータベース設定と異なっている?2つのデータベースの設定を比較したところ、多くの異なるパラメーターが見つかりました。しかし、我々はロック関連にのみ焦点を当てました。
データベースの設定は、LOCKキーワードを含むものです。
フェーズ6 テスト環境データベースと製品環境データベースの設定を一致させる

ロックに関する設定を全て製品環境と同じに変更しました。しかし、それでもデッドロックは再現されませんでした。最終的に、ある人は、設定 "cur_commit" を発見しました。
が違っていた。そこで、ドキュメントを照会したところ、cur_commitという機能があることがわかりました。
cur_commit = false の場合、以下のようにするとデッドロックが発生します。
スレッド1がデータAを挿入し、次にスレッド2がデータBを挿入する。
スレッド2が何かをコミットする前に、スレッド1がデータAを照会してしまい、デッドロックが発生します。
開発環境では、cur_commit = trueなので、こちらもシミュレーションできていません。
そこで、cur_commitもfalseに変更しました。
ステージ7 テストプログラムを使ってシミュレーションする

上記の2つのスレッドの動作を模擬するようにテストプログラムを修正し、デッドロックの再現に成功しました。また、エラーログのメッセージも製品環境上のものと一致しています。
ステージ8 画面操作でシミュレーションする

その後、画面を使用して操作するようにプログラムを修正し、このデッドロックも再現することに成功しました。
解決策
解決方法は簡単で、クエリ文の条件をインデックスとして追加すれば、デッドロックは発生しなくなるのです。
このテーブルはデータ量が多くないので、パフォーマンスへの影響はほとんどありません。