MySQLでわざとデッドロックを発生させる方法!解消方法も解説!

  • 2019年8月11日
  • 2024年7月14日
  • SQL
  • 8662view
SQL

Mysqlで疑問を持ったことはありませんか?

  • 「デッドロック起こすな!」と言うけど、そもそもどうやってデッドロックが発生するの?
  • デッドロックが起きたらどうすればよいの(MySQLの場合)?
  • デッドロックは、どうやって起こさないようにするの?

 

今回は、上記のような3つの疑問に答えていきます。

\IT未経験者からのサポートあり!転職サービス3選!!/

サービス名
未経験 未経験OK 未経験の転職専用 経験者向け
公開の求人数 ITエンジニア全体で1万件以上
ITエンジニア未経験で600件以上
未公開 5,000件以上
利用対象 全職種 IT特化 IT特化
特徴 ✓誰もが知る転職サービス
✓経歴を登録しておくとオファーが来る
✓企業担当者と条件交渉
✓スキルの身につく企業を紹介
✓IT専門のエージェントが対応
✓転職成功すると年収200万円以上の大幅アップがある
転職サポート内容
  • 求人検索
  • 企業担当者と交渉
  • 求人紹介
  • ライフプランのサポート
  • キャリア相談
  • 求人紹介
  • 提出書類の添削
  • 面接対策
公式サイト リクナビネクスト テックゲート レバテックキャリア

 

デッドロックとは?

 

MySQLの公式サイトにデッドロックについてこのように書かれています。

(デットロックとは)さまざまなトランザクションが進行できない状況 (それぞれが、他方が必要とするロックを保持しているため)。リソースが利用可能になるまで両方のトランザクションが待機しているため、どちらもそれが保持しているロックを解放しません。

 

(UPDATE や SELECT … FOR UPDATE などのステートメントを通じて) トランザクションが複数のテーブル内の行を反対の順にロックすると、デッドロックが発生することがあります。

出典

14.2.11 デッドロックの対処方法

並列に複数の処理が動いていて、ロックの順番を考慮せずに同じテーブルのデータ(今回の解説では行単位)をロックするとデッドロック状態になることがあります。

MySQLではデッドロックが起きるとどんな挙動をするの?

結論から言うと、MySQLは、デッドロックになってしまったトランザクションは、トランザクションは停止してロールバックします。

よって、デッドロックのまま処理がずっと進まないという、最悪の自体を防ぐことは可能です。

 

実際にデットロックが出ると、以下のようなエラーが出力されて、処理は停止します。

「Deadlock found when trying to get lock; try restarting transaction」

 

デッドロックを引き起こす方法

実際にSQLを書いてデッドロックを引き起こしてみます

デッドロックを引き起こすための環境とデータ準備

 

テーブルを作成する

 

■本の在庫管理用のテーブル作成

CREATE TABLE `m_books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL COMMENT '名前',
  `count` int(10) DEFAULT '0' COMMENT '在庫',
  `created` datetime NOT NULL,
  `modified` datetime DEFAULT NULL,
  `del` tinyint(4) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`,`created`),
  UNIQUE KEY `uniqe` (`id`,`created`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

 

■(本の)ジャンル用のテーブル

CREATE TABLE `m_genre` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL COMMENT 'ジャンル名',
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  `del` tinyint(4) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

データを入れるinsert文

データは、テーブルごとに1レコード用意する。

INSERT INTO `m_books` (`id`, `name`, `count`, `created`, `modified`, `del`)
VALUES
	(1, '本1', 10, '0000-00-00 00:00:00', NULL, 0);

INSERT INTO `m_genre` (`id`, `name`, `created`, `modified`, `del`)
VALUES
	(1, '始まり', '0000-00-00 00:00:00', NULL, 0);

 

以上でデータの準備は終わりです。

 

2つのスクリプトを用意する

タスクA
begin;
update m_books set count = 2 where id = 1;
update m_genre set `name` = "test2" where id = 1;
commit;

タスクB
begin;
update m_genre set `name` = "test" where id = 1;
update m_books set count = 1 where id = 1; #デッドロック
commit;

 

 

実行順番に注意してスクリプトを事項する

 

以下の画像を参考に①から順番に処理を実行します。

 

⑥のところでデッドロックを検出します。

 

デッドロックを検出すると、MySQLから以下のエラーがでて。タスクA,Bのupdateは反映されませんでした。

「Deadlock found when trying to get lock; try restarting transaction」

 

 

デッドロックを起こさないためには?

今回の例では、タスクA,Bでテーブルのデータの更新順番が逆になっていました。

その結果、デッドロックになりました。

 

この解決方法は、updateの順番を決めることで、デッドロックにならずにすみます。

 

具体的に言うと、タスクA,B共に以下のような処理順番にすればよいです。

以下の例では、タスクA,B共にm_books、m_genreの順番にテーブルの行を更新しています。

 

begin;

update m_books set count = [代入する値] where id = 1;

update m_genre set `name` = [代入する文字列] where id = 1;

commit;

 

デッドロックが起きたときの調査方法

コマンド「SHOW ENGINE INNODB STATUS」を実行します。

最近のデッドロックの原因を特定に役立ちします。

 

実際に「SHOW ENGINE INNODB STATUS」を実行すると、以下のようなログが出てきます。

「LATEST DETECTED DEADLOCK」の部分を確認すると、どのsqlでデッドロックが発生したのか分かるので、調査する際に大変役立ちます。

------------------------
LATEST DETECTED DEADLOCK
------------------------

(2) TRANSACTION:
TRANSACTION 4340031, ACTIVE 65 sec starting index read
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1184, 3 row lock(s), undo log entries 1
MySQL thread id 28, OS thread handle 0x700001c0f000, query id 874 localhost 127.0.0.1 root updating
update m_genre set `name` = "test2" where id = 1

 

\IT未経験者からのサポートあり!転職サービス3選!!/

サービス名
未経験 未経験OK 未経験の転職専用 経験者向け
公開の求人数 ITエンジニア全体で1万件以上
ITエンジニア未経験で600件以上
未公開 5,000件以上
利用対象 全職種 IT特化 IT特化
特徴 ✓誰もが知る転職サービス
✓経歴を登録しておくとオファーが来る
✓企業担当者と条件交渉
✓スキルの身につく企業を紹介
✓IT専門のエージェントが対応
✓転職成功すると年収200万円以上の大幅アップがある
転職サポート内容
  • 求人検索
  • 企業担当者と交渉
  • 求人紹介
  • ライフプランのサポート
  • キャリア相談
  • 求人紹介
  • 提出書類の添削
  • 面接対策
公式サイト リクナビネクスト テックゲート レバテックキャリア

 

プログラミングを短期間で学ぶ方法

プログラミングを短期間で効率的に学ぶ方法を紹介します。

それは、以下のようなサービス、プログラミングスクールを利用することです。

プログラミングスキルを習得している人でも機械学習の習得は、独特の考え方の習得が必要になるため難しいです。

だから、独学で迷うよりは、プロに教えてもらったほうが、遥かに最短経路で身につけることができます!

\プログラミングスクール!あなたの疑問を解消する無料説明会7選/

スクール名 侍エンジニア塾 DMM WEBCAMP テックアカデミー テックキャンプ ドットプロ Aidemy Premium Plan 0円スクール
イメージ
説明会参加の
オススメ度(※1)
無料説明会の内容 プログラミングが向いているか?どの言語を学べばよいか?本当に未経験からエンジニアに転職できるのか?という疑問を解消できる 無料カウンセリングでは、エンジニア転職の最新動向、あなたに合ったキャリアを提案! 1週間のプログラミング体験(メンターに質問できる!)、無料カウンセリングは現役のエンジニアによる疑問解消! IT業界の不明点、プログラミングの不明点の解消 無料カウンセリング。転職、受講に関する様々な疑問の解消 初めてのAI学習の不安や疑問の解消。転職や副業、未経験からの学習にまつわるお悩みも解消! 転職、受講に関する様々な疑問の解消
無料説明会の参加特典 電子書籍プログラミング学習メソッドのプレゼント 参加特典あり(時期によって異なります) 要お問い合わせ 要お問い合せ 要お問い合せ 要お問い合せ 要お問い合せ
学べる内容
  • WEB開発
  • AI(機械学習)
  • WEB開発
  • WEB開発
  • AI(機械学習)
  • IOS,Androidアプリ開発
  • ゲーム開発
  • 数学・統計学
  • WEB開発
  • AI(機械学習)
  • WEB開発(AIと組み合わせた講座あり)
  • AI(機械学習)
  • WEB開発(AIと組み合わせた講座あり)
  • AI(機械学習)
  • WEB開発
公式サイトに行く 無料カウンセリング 無料カウンセリング プログラミング無料体験 無料カウンセリング 無料カウンセリング 無料カウンセリング 無料カウンセリング

※1・・・オススメ度の評価基準は、参加特典、公開されている説明会(無料カウンセリング)の内容を元にしています。

まとめ

デッドロックは、いつも同じタイミングで発生するわけでないので、気ずきずらいです。

設計段階から、デッドロックが起きないように、テーブルの読み込み順番を考慮しておく必要があります。

 

\IT未経験者からのサポートあり!転職サービス3選!!/

サービス名
未経験 未経験OK 未経験の転職専用 経験者向け
公開の求人数 ITエンジニア全体で1万件以上
ITエンジニア未経験で600件以上
未公開 5,000件以上
利用対象 全職種 IT特化 IT特化
特徴 ✓誰もが知る転職サービス
✓経歴を登録しておくとオファーが来る
✓企業担当者と条件交渉
✓スキルの身につく企業を紹介
✓IT専門のエージェントが対応
✓転職成功すると年収200万円以上の大幅アップがある
転職サポート内容
  • 求人検索
  • 企業担当者と交渉
  • 求人紹介
  • ライフプランのサポート
  • キャリア相談
  • 求人紹介
  • 提出書類の添削
  • 面接対策
公式サイト リクナビネクスト テックゲート レバテックキャリア
最新情報をチェックしよう!