LoginSignup
11
2

More than 3 years have passed since last update.

SQLのトランザクションと制御、設定 ~駆け出しエンジニア編~

Last updated at Posted at 2019-12-21

こんにちは!
オズビジョン開発グループのShoです。

2019年9月~29歳で未経験から営業→エンジニアになった私が、
脱未経験エンジニアを目指して、業務の中で学んだこと、会社の業務について書いて行きます。
私の現状については前回の投稿をご参照ください。
[前回の投稿]

今回は、SQLのトランザクション処理の制御について書いて行きます。

対象読者

私と同じように、異職種からwebエンジニア(バックエンド、フロントエンド)に転職された方。
経験1年未満で毎日分からないことだらけの方。
トランザクションって何?という方。
これから人生で初めて本番環境のDBを触る方。

今回の投稿の背景

自社のwebサービスにて新機能の追加を担当しており、
実装、テストを終え、本番環境へのリリース手順の作成を任されました。
その際にデータベースへのレコード追加の手順があり、
対象のDBとSQL文を下記のように手順に加えました。


対象DB:hoge

insert into hoges(hoge,fuga) values('qiita','キータ',now());

そして完成したリリース手順をレビュー依頼に出し、
考慮が足りない点、不足している手順、質問などレビューが返ってきました。

その中で、

トランザクションの設定を行って下さい。
本番環境でDBを操作する場合は、ロールバックの余地を残してください。

というコメントを頂きました。

・・・指摘の内容が分からない!!!

トランザクションの意味は理解していましたが、その設定とはどういうこと??
と頭の中が??になりました。

という訳で、今回はSQLでのトランザクションの設定、制御について簡単にまとめました。

トランザクションとは

ざっくり説明すると、

  • 「複数の処理」のまとまり。
  • 処理1 → 処理2 → 処理3 = 1つのトランザクション
  • 1つのトランザクションに於いては、複数の処理は分離できない。
  • 上記のトランザクションでは、処理1が組み込まれてるので、処理1だけ切り離して独立させることはできない。
  • トランザクションは「成功」か「失敗」のいずれかの結果となる。

よく銀行の振込み処理などが例で使用されます。
AさんからBさんの口座へ1,000円の振込みをする
処理1: Aさんの口座から1,000円を差し引き、残高10,000円-1,000円=9,000円にする。
処理2: Bさんの口座へ1,000円プラスして、残高20,000円+1,000円=21,000円にする。
上記のトランザクションでは、
Aさんの残高が9,000円、Bさんの残高が21,000円となったので「成功」です!

もし、処理2で何かしらのエラーで起きた場合は、
処理1でAさんの口座から1,000円が引かれているので、
振込み前の状態に戻す必要があります。
Aさんの1,000円どこ行った!!となってしまったら大変です。
これはトランザクションの「失敗」です。

このような複数の処理のまとまりによる、一連の処理トランザクションです。

SQLでもテーブル作成やカラムの追加、レコードの追加の流れもトランザクションです。
この際にどこかの処理で、エラーが起きた際にロールバックできるようにしてね!!!
というのが私が受けたレビューでの指摘です。
本番環境のDBでエラーが起きて最初の状態に戻れなかったら厄介です。
(考えただけで怖い)

SQLでのトランザクションの制御、設定

では、私はどのように修正すべきでしょうか。
結果のSQL文から書きます。


begin;

select  * from hoges where hoge = 'Qiita';
# 検索して0

insert into hoges(hoge,fuga) values('Qiita','キータ',now());

select  * from hoges where hoge = 'Qiita'; 
#検索して1

commit;
  • begin;でここからトランザクションの開始です!という開始の宣言。
  • Qiitaが新しく追加するものなので、追加前に存在しないかの確認
  • レコードの追加
  • レコードが本当に追加されたかの確認。
  • commit;で処理の確定(この場合はinsert)

上記のようにbegin;からcommit;で処理の確定が行われるまでが、一連のトランザクションとして扱われます。
今回の処理でエラーが起きた際にはrollback;処理前の状態に戻すことができます。

今回は一つのトランザクションなので省略していますが、
複数のトランザクションがある場合は、トランザクション毎に名前をつければ、指定した処理をロールバックすることが可能です。
begin transaction [トランザクション名];
rollback transaction [トランザクション名];

途中のselectは実際の処理ではなく、確認の為に挟んでいます。
本番環境ともなれば随時確認しながら進めて行くことが重要、ということも勉強になりました。

レビューがなかったら、本番DBに直でinsertしてました。
今考えると危なすぎです...。

もし、初めて本番環境でDBを操作することがある方は頭に入れておくと良いと思います。
誰かの参考になれば幸いです。

余談

手順のレビューをもらい、手順にトランザクションの制御を入れ上述のように修正しました。

実はOKをもらう前にもう一回修正をしております。
"Qiitaで検索して0件"
"Qiitaで検索して1件"
という項目も入れた方がいいよ!と言われ、
手順に上記の文章をそのまま書きました。

そしてレビューで
...いやそこはSQL文で書いてよ!笑
と突っ込まれ、上記のselect文にするんだ!と気づきました。
そりゃそうですよね。当たり前です...。
恥ずかしい...。

エンジニア力のなさを実感した瞬間です。笑

11
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
2