【63】【Rails】【データベース】タイムアウト、デッドロックを体験しよう。百聞は一見に如かず。

この記事を読むと、トランザクションの仕組み、タイムアウト、デッドロックを理解することができます

百聞は一見に如かず!
ということで、トランザクションの仕組み、タイムアウト、デッドロックを実際に体験しましょう。

環境構築

Dockerを使ってさくっと環境を構築しましょう。

usersの確認とデーターの挿入

usersテーブルの確認
SELECT * FROM users;

データの挿入
INSERT INTO users (name, created_at) VALUES ('ユーザーA', NOW());
INSERT INTO users (name, created_at) VALUES ('ユーザーB', NOW());

データの削除
DELETE FROM users;

トランザクションの試してみる

現在開いているターミナルをターミナルAします。
新規ウィンドウを作り、新たにターミナルを起動して下さい。こちらをターミナルBとします。
新たにターミナルを起動して、このデーターベースに接続して下さい

ターミナルA

BEGIN;
INSERT INTO users (name, created_at) VALUES ('ユーザーA', NOW());
INSERT INTO users (name, created_at) VALUES ('ユーザーB', NOW());
SELECT * FROM users;

ターミナルB

SELECT * FROM users;

ターミナルAがトランザクション中なので何も表示されません。

ターミナルA

COMMIT;

トランザクションの取り消し

BEGIN;
DELETE FROM users;
SELECT * FROM users;
ROLLBACK;

データを削除しましたが、トランザクションを取り消すと、削除したデータがもとに戻ります。

タイムアウトとデッドロック

タイムアウトを発生させる。

ターミナルA

BEGIN;
UPDATE users SET name = 'ユーザー123' WHERE id = 3;

ターミナルB

UPDATE users SET name = 'ユーザー111' WHERE id = 3;

パソコンが固まったような挙動になります。
これはAのトランザクションが終わるのを待っているからです。
定められた時間が過ぎるとタイムアウトになり、エラーが出力されます。

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

デッドロックを発生させる

ターミナルA

BEGIN;
UPDATE users SET name = 'ユーザー123' WHERE id = 3;

ターミナルB

BEGIN;
UPDATE users SET name = 'ユーザー100' WHERE id = 4;
UPDATE users SET name = 'ユーザー10' WHERE id = 3;

ターミナルBでさきほどのようにパソコンが固まったような状態になります。一定時間が過ぎるとタイムアウトになります。

ターミナルA
ターミナルB側がタイムアウトになる前に、下記のコマンドを実行します。

UPDATE users SET name = 'ユーザー1444' WHERE id = 4;

ターミナルB
デッドロックが発生します。

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

お互いがトランザクションの終了を待ち続ける状態になったからです。
一度体験すると、デッドロックやタイムアウトの理解は簡単ですね。

関連する記事

参考文献

【全エンジニア必須】実務に役立つ!Railsでバッチ処理を作ろう!

最後に
私がブログを書く目的は、素晴らしい本や、素晴らしい方々の技術記事を知って頂きたいからです。ぜひ、上記の参考文献を見て下さい。(noteなので広告とかは一切ありません。)

現在、株式会社grabssに行くために最後の悪あがきをしています!!
現在の進行状況
この記事は53件目の投稿。目標達成!!!!
目標再設定
20日までに100件目指す!!(53件目)

よろしければ、スキボタン及びサポートお願いします。勉強の励みになります。


この記事が気に入ったらサポートをしてみませんか?