Ground Sunlight

Windowsで作る - PHPプログラミングの開発環境

ユーザ用ツール

サイト用ツール


mariadb:10.4:transaction

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン 両方とも次のリビジョン
mariadb:10.4:transaction [2020/10/20 14:44]
y2sunlight [SQL文による手動トランザクション]
mariadb:10.4:transaction [2020/11/19 17:10]
y2sunlight [MySQLi による手動トランザクション]
行 1: 行 1:
 ====== MariaDB10.4 トランザクション ====== ====== MariaDB10.4 トランザクション ======
 +phpMyAdmin 4.9.0.1 (MariaDB 10.4.6)
 +
  --- //[[http://www.y2sunlight.com|y2sunlight]] 2019-10-15//  --- //[[http://www.y2sunlight.com|y2sunlight]] 2019-10-15//
  
行 5: 行 7:
  
 関連記事 関連記事
-  * [[xampp:7.2|XAMPP7.2のインストール]] 
   * [[mariadb:10.4:phpmyadmin|MariaDB10.4 phpMyAdminの使い方]]   * [[mariadb:10.4:phpmyadmin|MariaDB10.4 phpMyAdminの使い方]]
   * [[mariadb:10.4:mysqli|MariaDB10.4 PHPサンプルプログラム]]   * [[mariadb:10.4:mysqli|MariaDB10.4 PHPサンプルプログラム]]
行 12: 行 13:
   * MariaDB10.4 トランザクション   * MariaDB10.4 トランザクション
  
-以下「MySQL」は「MariaDB」に読み替えて下さい+以下「MySQL」は「MariaDB」に読み替えて下さい
  
 ---- ----
  
-MySQLではトランザクションセーフなテーブル(InnoDBなど)と非トランザクションセーフなテーブル(MyISAMなど)を作る事ができます。手動トランザクションが使えるのはトランザクションセーフなテーブルだけです。 MyISAMなどの非トランザクションセーフなテーブルの場合は、データベースの変更は直ちにコミットされます。本章ではストレージエンジンとしてInnoDBを使ったテーブルを対象とします。+===== 概要 ===== 
 + 
 +MySQLではトランザクションセーフなテーブル(InnoDBなど)と非トランザクションセーフなテーブル(MyISAMなど)を作る事ができます。手動トランザクションが使えるのはトランザクションセーフなテーブルだけです。 MyISAMなどの非トランザクションセーフなテーブルの場合は、データベースの変更は直ちにコミットされます。 
 + 
 +本章ではストレージエンジンとしてInnoDBを使ったテーブルを対象として、トランザクションについて説明します。InnoDBでは、以下のトランザクション分離レベルをサポートしています: 
 + 
 +  * READ UNCOMMITTED --- 非コミット読み取り 
 +  * READ COMMITTED --- コミット済み読み取り 
 +  * REPEATABLE READ --- 再読み込み可能読み取り 
 +  * SERIALIZABLE --- 直列化 
 + 
 +ここでは、これらの分離レベルの違いをサンプルプログラムを使用して実感しながら説明したいと思います。 
 + 
 +\\
  
-==== MySQLのトランザクション ====+===== MySQLのトランザクション =====
  
 MySQLはデフォルトで自動トランザクション機能(自動コミットモード)が有効です。本編ではMySQLiを使っているので、プログラムの途中で自動コミットモードを切り替える場合は、次のようにします。 MySQLはデフォルトで自動トランザクション機能(自動コミットモード)が有効です。本編ではMySQLiを使っているので、プログラムの途中で自動コミットモードを切り替える場合は、次のようにします。
行 80: 行 94:
 > [[https://mariadb.com/kb/en/library/set-transaction/]] > [[https://mariadb.com/kb/en/library/set-transaction/]]
  
-==== SQL文による手動トランザクション ====+\\ 
 + 
 +===== SQL文による手動トランザクション ====
 ブラウザからサンプルプログラム(sqlfile.php)を実行します。 ブラウザからサンプルプログラム(sqlfile.php)を実行します。
  
行 97: 行 114:
 ); );
 INSERT INTO syain VALUES(1,'Suzuki',50); INSERT INTO syain VALUES(1,'Suzuki',50);
-;+#;
 -- トランザクション開始 ------------------ -- トランザクション開始 ------------------
 -- SET AUTOCOMMIT = 0; -- SET AUTOCOMMIT = 0;
行 113: 行 130:
 </file> </file>
  
-10行目のセミコロン(;)だけの行はブラウザ上で改行する為に使用しています。誤りではありません。+10行目の ''#;'' だけの行はブラウザ上で改行する為に使用しています。誤りではありません。
  
 実行結果 実行結果
行 125: 行 142:
 この例で、START TRANSACTION文を1行目に移動して実行すると、奇妙な現象が起こります。ロールバックが効かなくなるのです。これは、DROP TABLE文により暗黙のコミットが発生してトランザクションが終了している為です。それ以降は自動コミットモードになるのでROLLBACK文は無効になります。この現象はDROP TABLEやCREATE TABLEなどのDDL文の場合に発生します。トランザクションを設計する場合は注意する必要があります。 この例で、START TRANSACTION文を1行目に移動して実行すると、奇妙な現象が起こります。ロールバックが効かなくなるのです。これは、DROP TABLE文により暗黙のコミットが発生してトランザクションが終了している為です。それ以降は自動コミットモードになるのでROLLBACK文は無効になります。この現象はDROP TABLEやCREATE TABLEなどのDDL文の場合に発生します。トランザクションを設計する場合は注意する必要があります。
  
-==== MySQLi による手動トランザクション ====+\\ 
 + 
 +===== MySQLi による手動トランザクション =====
  
 ブラウザからサンプルプログラム(sqlfile.php)を実行します。 ブラウザからサンプルプログラム(sqlfile.php)を実行します。
行 133: 行 152:
 </code> </code>
  
-<file sql transaction1b.sql>テーブル作成 -------------------------+<file sql transaction1b.sql> 
 +-- テーブル作成 -------------------------
 DROP TABLE IF EXISTS syain; DROP TABLE IF EXISTS syain;
 CREATE TABLE syain ( CREATE TABLE syain (
行 142: 行 162:
 ); );
 INSERT INTO syain VALUES(1,'Suzuki',50); INSERT INTO syain VALUES(1,'Suzuki',50);
-+#
-#トランザクション開始 ------------------ + 
-#EVAL $mysqli->autocommit();+-- トランザクション開始 ------------------ 
 +-- EVAL $mysqli->autocommit();
 EVAL $mysqli->begin_transaction(); EVAL $mysqli->begin_transaction();
 SELECT * FROM syain; SELECT * FROM syain;
  
-テーブルの更新+-- テーブルの更新
 UPDATE syain SET syain_age = syain_age + 1; UPDATE syain SET syain_age = syain_age + 1;
 INSERT INTO syain VALUES(2,'Yamamoto',30); INSERT INTO syain VALUES(2,'Yamamoto',30);
 SELECT * FROM syain; SELECT * FROM syain;
  
-トランザクション終了 -----------------+-- トランザクション終了 -----------------
 EVAL $mysqli->rollback(); EVAL $mysqli->rollback();
 SELECT * FROM syain; SELECT * FROM syain;
行 160: 行 181:
 上のスクリプトファイルにはEVAL文が含まれています。EVALに続く式(例えば:$mysqli->autocommit())はPHPのeval関数に引き渡されます。$mysqli変数は sqlfile.php の DoSqlScript()関数のローカルコープ内で使用できる変数です。[[mariadb:10.4:mysqli#サンプルプログラム|サンプルプログラム]]を参照して下さい。 上のスクリプトファイルにはEVAL文が含まれています。EVALに続く式(例えば:$mysqli->autocommit())はPHPのeval関数に引き渡されます。$mysqli変数は sqlfile.php の DoSqlScript()関数のローカルコープ内で使用できる変数です。[[mariadb:10.4:mysqli#サンプルプログラム|サンプルプログラム]]を参照して下さい。
  
-実行結果+=== 実行結果 ===
  
 [{{:mariadb:10.4:transaction1b.png|}}] [{{:mariadb:10.4:transaction1b.png|}}]
行 169: 行 190:
  
 MySQLiを利用してデータベースをアクセスする場合、移植性による理由から、begin_transaction/commit/rollbackメッソドを使用する場合が多いと思います。暗黙のコミットを発行するSQL文には十分な注意が必要です。 MySQLiを利用してデータベースをアクセスする場合、移植性による理由から、begin_transaction/commit/rollbackメッソドを使用する場合が多いと思います。暗黙のコミットを発行するSQL文には十分な注意が必要です。
 +
 +\\
  
 ==== トランザクションの分離レベル ==== ==== トランザクションの分離レベル ====
行 188: 行 211:
  
 <file sql transaction2a.sql> <file sql transaction2a.sql>
-テーブル作成 -------------------------+-- テーブル作成 -------------------------
 DROP TABLE IF EXISTS syain; DROP TABLE IF EXISTS syain;
 CREATE TABLE syain ( CREATE TABLE syain (
行 197: 行 220:
 ); );
 INSERT INTO syain VALUES(1,'Suzuki',50); INSERT INTO syain VALUES(1,'Suzuki',50);
-+#
-#トランザクション開始 ------------------+ 
 +-- トランザクション開始 ------------------
 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-#SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +-- SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 
-#SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +-- SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; 
-#SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;+-- SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
  
 START TRANSACTION; START TRANSACTION;
-EVAL #トランザクションA開始;+EVAL # トランザクションA開始;
 SELECT * FROM syain; SELECT * FROM syain;
  
-EVAL #ここで他のトランザクションがデータを更新する;+EVAL # ここで他のトランザクションがデータを更新する;
 EVAL sleep(5); EVAL sleep(5);
 SELECT * FROM syain; SELECT * FROM syain;
 SELECT * FROM syain LOCK IN SHARE MODE; SELECT * FROM syain LOCK IN SHARE MODE;
  
-トランザクション終了 -----------------+-- トランザクション終了 -----------------
 COMMIT; COMMIT;
-EVAL #トランザクションA終了;+EVAL # トランザクションA終了;
  
 EVAL sleep(5); EVAL sleep(5);
 SELECT * FROM syain; SELECT * FROM syain;
- 
 </file> </file>
  
行 241: 行 264:
  
 <file sql transaction2b.sql> <file sql transaction2b.sql>
-#トランザクション開始 ------------------+-- トランザクション開始 ------------------
 START TRANSACTION; START TRANSACTION;
 EVAL #トランザクションB開始; EVAL #トランザクションB開始;
  
-テーブルの更新+-- テーブルの更新
 INSERT INTO syain VALUES(2,'Yamamoto',30); INSERT INTO syain VALUES(2,'Yamamoto',30);
 UPDATE syain SET syain_age = syain_age + 1; UPDATE syain SET syain_age = syain_age + 1;
行 252: 行 275:
 EVAL sleep(5); EVAL sleep(5);
  
-トランザクション終了 -----------------+-- トランザクション終了 -----------------
 ROLLBACK; ROLLBACK;
 EVAL #トランザクションB終了; EVAL #トランザクションB終了;
行 261: 行 284:
 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。
  
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki> +  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki>'' 
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2b.sql</nowiki>+  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2b.sql</nowiki>''
  
 実行結果 実行結果
行 283: 行 306:
  
 <file sql transaction2c.sql> <file sql transaction2c.sql>
-自動コミットモード ------------------- +-- 自動コミットモード ------------------- 
-レコード挿入+-- レコード挿入
 INSERT INTO syain VALUES(2,'Yamamoto',30); INSERT INTO syain VALUES(2,'Yamamoto',30);
 SELECT * FROM syain; SELECT * FROM syain;
  
-レコード更新+-- レコード更新
 UPDATE syain SET syain_age = syain_age + 1; UPDATE syain SET syain_age = syain_age + 1;
 SELECT * FROM syain; SELECT * FROM syain;
行 297: 行 320:
 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。
  
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki> +  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki>'' 
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2c.sql</nowiki>+  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2c.sql</nowiki>''
  
 実行結果 実行結果
行 316: 行 339:
  
 <file sql transaction2c.sql> <file sql transaction2c.sql>
-自動コミットモード ------------------- +-- 自動コミットモード ------------------- 
-レコード挿入+-- レコード挿入
 INSERT INTO syain VALUES(2,'Yamamoto',30); INSERT INTO syain VALUES(2,'Yamamoto',30);
 SELECT * FROM syain; SELECT * FROM syain;
  
-レコード更新+-- レコード更新
 UPDATE syain SET syain_age = syain_age + 1; UPDATE syain SET syain_age = syain_age + 1;
 SELECT * FROM syain; SELECT * FROM syain;
行 328: 行 351:
 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。 以下の順でSQLスクリプトを実行します。2番目のスクリプトは5秒以内に実行します。
  
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki> +  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki>'' 
-  - <nowiki>http://localhost/mysql/sqlfile.php?f=transaction2c.sql</nowiki>+  - ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2c.sql</nowiki>''
  
 実行結果 実行結果
行 346: 行 369:
  
 <file sql transaction2c.sql> <file sql transaction2c.sql>
-自動コミットモード ------------------- +-- 自動コミットモード ------------------- 
-レコード挿入+-- レコード挿入
 INSERT INTO syain VALUES(2,'Yamamoto',30); INSERT INTO syain VALUES(2,'Yamamoto',30);
 SELECT * FROM syain; SELECT * FROM syain;
  
-レコード更新+-- レコード更新
 UPDATE syain SET syain_age = syain_age + 1; UPDATE syain SET syain_age = syain_age + 1;
 SELECT * FROM syain; SELECT * FROM syain;
 </file> </file>
  
-ブラウザから http://localhost/mysql/sqlfile.php?f=transaction2a.sql を実行し、直ぐに(5秒以内)、別のブラウザから http://localhost/mysql/sqlfile.php?f=transaction2c.sql を実行します。+ブラウザから ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2a.sql</nowiki>'' を実行し、直ぐに(5秒以内)、別のブラウザから ''<nowiki>http://localhost/mysql/sqlfile.php?f=transaction2c.sql</nowiki>'' を実行します。
  
 実行結果 実行結果
mariadb/10.4/transaction.txt · 最終更新: 2020/11/20 09:55 by y2sunlight