質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

解決済

2回答

532閲覧

MySQL トランザクションの処理について

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2022/02/24 13:05

編集2022/02/25 22:42

トランザクションの処理について、色々ネットサーフィンし色々な記事を見ましたが、
自分なりに理解したつもりでしたが、実際に組み込んで試してみた所、
動作に不可解な部分があったので質問させていただきました。

データの整合性を保つため、トランザクションの処理が必要と、サイトを確認しました。
(トランザクションについて調べ、銀行の残高を例にしたサイトでした)
振込の際、銀行Aの減額処理と銀行Bの増額処理が正常に行われてないと、データの整合性が保てない等の内容でした。

現在、こちらのサイトのトランザクション処理を参考に記述しておりますが、
下記動作が正常なのか、確認お願いします。

id は PRIMARY

  • クエリ1. (初期データ)

INSERT INTO testtable (id, name) VALUES (1, 'yamada');

  • クエリ2. (処理時間稼ぐ為のデータ)

INSERT INTO testtable (id, name) SELECT COALESCE(MAX(id)+1,1), 'kato' FROM testtable;
INSERT INTO testtable (id, name) SELECT COALESCE(MAX(id)+1,1), 'sato' FROM testtable;
......(2,000件程度)

  • クエリ3.

INSERT INTO testtable (id, name) SELECT COALESCE(MAX(id)+1,1), 'suzuki' FROM testtable;

当方の認識としては、
『クエリ1のデータ(id:1)が予め入力されており、クエリ2の大量データをトランザクションで処理。
クエリ2の処理に時間かかる場合、クエリ3を実行すると、クエリ2の処理が終わってから実行される。』と、思っておりましたが
実際は、クエリ2の実行・処理中にクエリ3を実行したところ、ID:2として処理が完了し、クエリ2はID:3から連番が振られていました。

上記のトランザクション処理は正しいのか。また、トランザクション処理でおすすめや参考になるサイト等あればお教えいただければ幸いです。
初歩的な質問で申し訳御座いませんが、お願い致します。

動作環境(Xserver)
MariaDB 10.5
PHP 7.4.25
追記:
'SELECT @@GLOBAL.tx_isolation, @@tx_isolation'
REPEATABLE-READ, REPEATABLE-READ

クエリ1,2,3は別セッションとなります(3セッション)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nukasa

2022/02/24 14:17

トランザクションのことをうんぬんするなら、トランザクション分離(アイソレーション)のことを考慮しなければなりません。 クエリ1~3が、同一DBセッションで実行されたのか、別のDBセッションで実行されたのか、分離レベルは何なのかを明確にしなければ、議論をスタートできません。
退会済みユーザー

退会済みユーザー

2022/02/24 23:29 編集

コメントをいただき、ありがとうございます。 恐れ入ります、「クエリ1~3が、同一DBセッションで実行されたのか、別のDBセッション」の部分ですが、 DBセッションとは (https://lukesilvia.hatenablog.com/entry/20090523/p1) の内容の事で合ってますでしょうか。 知識が乏しく勉強中ですため、気分を害す返答・質問でしたら申し訳御座いませんが、 ご教授いただければ幸いです。
nukasa

2022/02/25 00:45

https://lukesilvia.hatenablog.com/entry/20090523/p1 に書かれているのは、アプリケーションサーバーのセッション情報をDBに永続化するための方法を書いてあるもので、DBセションとは関係ありません。 DBセッションというのは、DBに接続してから切断するまでの一連の作業を紐づけるものです。mysqlコマンドで、クエリ1~3を連続して発行しているなら、同一セッションです。クエリ2を処理している最中に、別のウィンドウからmysqlコマンドを別に起動し、そこでクエリ3を実行するのであれば、セッションは別になります。
退会済みユーザー

退会済みユーザー

2022/02/25 04:08

ご返答ありがとうございます。 php-gres さま AUTO_INCREMENT にて設定しますと、idのカラムは他テーブルとのデータにJOINしており、削除等が行われると手間が掛かるかと思いました事、1万件を挿入した後、5千件のデータを削除した際、AUTO_INCREMENT を戻さないと歯抜けになることが懸念され、長さでも直ぐに天井となる事、その際のメンテナンス軽減のためです。 MAX()+1の連番はそこまで良くない方法となりますでしょうか、、。 不具合が発生する例もしくは、処理速度の面でもシーケンスの方がよろしいでしょうか。。 ご意見をお教えいただけませんでしょうか。 シーケンスについては、新しい情報でしたため、URLをお教えいただきありがとうございます。 参考にします。 nukasa さま DBセッションについて、噛み砕いていただきありがとうございます。 セッションについては、クエリ1、2、3で別セッション(計3セッション)になります。 また、分離レベルを確認しましたところ、 'SELECT @@GLOBAL.tx_isolation, @@tx_isolation' REPEATABLE-READ, REPEATABLE-READ となっております。が、情報は足りてますでしょうか。
guest

回答2

0

処理を待たせるならsleepが使えると思います

//基本データ

SQL

1create table tbl(id int primary key auto_increment,name varchar(10)); 2insert into tbl(name) values('yamada');

//以下実行中に、その下のSQLを実行

SQL

1start transaction; 2select * from tbl for update; 3select sleep(5); 4insert into tbl(name) values('kato'),('sato'); 5commit; 6 7start transaction; 8insert into tbl(name) values('suzuki'); 9commit;

必ず並行して動作させてください

投稿2022/02/25 05:01

yambejp

総合スコア114843

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/02/25 23:49

ご回答いただき、ありがとうございます。 コードまでご丁寧に記載いただき、一度当方にてコードを修正した後、上記コードも試してみようと思います。 今回は他の方の回答にベストアンサーを付けさせていただきましたが、身近にプログラムの詳しい人がおりませんため、別質問させていただく時には、コメントをいただければ幸いです。 よろしくお願いします。
guest

0

ベストアンサー

クエリ1~3がすべて別セッションということですから、トランザクションは別々に制御されます。トランザクション分離レベルが REPEATABLE READ とのことですから、INSERTした行は、commitするまでは、他のセッションからは見えません。
MAX(cmid) も他のセッションで登録したcmidは、commit するまで見えないので、自セッションがINSERT文を実行した時点で、見えているsumidの最大値ということになります。
IDをAUTO INCREMENT ではなく、自力で採番するというのは、重複したIDを振ってしまう、ダメなコーディングの代表(アンチパターン)ですね。

投稿2022/02/25 04:24

nukasa

総合スコア406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/02/25 23:47

ご丁寧に回答いただきありがとうございます。 トランザクションについて、理解が深まりました。 また、自力採番のダメなコーディングも指摘いただき、ありがとうございます。 AUTO INCREMENTでは意図しない場面でカウンターが進み、悩み自力採番を採用しましたが、改めて調べました所、カウンターが進む対策も出来そうです。(私の調べが足りませんでした) 少しコードを書き直し、試してみようと思います。 また、こちらの回答をベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問