ホームページ  >  記事  >  データベース  >  MySQLトランザクションプログラミングのパフォーマンスと問題分析【開発者必見】

MySQLトランザクションプログラミングのパフォーマンスと問題分析【開発者必見】

黄舟
黄舟オリジナル
2017-02-06 10:50:511057ブラウズ

ナンセンスではなく、役立つ情報が満載です。直接分析に進みます:

1. ループ内で送信される問題

多くの開発者は、よく作成するストアド プロシージャの例を以下に示します。

DROP PROCEDURE IF EXISTS load1;
CREATE PROCEDURE load1(count INT UNSIGNED)BEGIN   
DECLARE s INT UNSIGNED DEFAULT 1;   
DECLARE c CHAR(80) DEFAULT REPEAT('a',80);   
WHILE s <= count DO      
INSERT INTO t1 select NULL,c;      
COMMIT;      
SET s=s+1;   
END WHILE;
END;

上記の例では、commit コマンドを追加するかどうかは重要ではありません。 MySQL の innodb のストレージ エンジンはデフォルトで自動送信になっているため、ストアド プロシージャ内のコミットを削除しても結果は同じになります。以下に示すように、開発者が見落としやすいもう 1 つの問題も次のとおりです。

DROP PROCEDURE IF EXISTS load2;
 CREATE PROCEDURE load2(count INT UNSIGNED)BEGIN  
  DECLARE s INT UNSIGNED DEFAULT 1;   
  DECLARE c CHAR(80) DEFAULT REPEAT(&#39;a&#39;,80);   
  WHILE s <= count DO      
  INSERT INTO t1 select NULL,c;      
  SET s=s+1;   
  END WHILE;
  END;

上記のストアド プロシージャに関係なく、エラーが発生すると、データベースは不明な場所に留まります。たとえば、10,000 個のデータを挿入したいのですが、5,000 個のデータを挿入するときにエラーが発生しました。しかし、この 5,000 個のデータはすでにデータベースに格納されています。もう 1 つの問題はパフォーマンスです。挿入がトランザクション内に配置されるため、上記の 2 つのストアド プロシージャは、以下のストアド プロシージャよりも高速ではありません。以下に示すように、3 番目の方法の方がはるかに高速であることがわかります。これは、言及ごとに REDO ログを書き込む必要があるため、load1 とload2 は実際に 100 万回の REDO ログを書き込むためです。ストアド プロシージャload3 については、REDO ログを 1 回だけ書き込みました。

最初にテストテーブルを準備します

DROP PROCEDURE IF EXISTS load3; 
CREATE PROCEDURE load3(count INT UNSIGNED)BEGIN   
DECLARE s INT UNSIGNED DEFAULT 1;   
DECLARE c CHAR(80) DEFAULT REPEAT(&#39;a&#39;,80);   
START TRANSACTION;   
WHILE s <= count DO      
INSERT INTO t1 select NULL,c;      
SET s=s+1;   
END WHILE;   
COMMIT;
END;

テストを実行します

CREATE TABLE `t1` (`id` int NOT NULL AUTO_INCREMENT ,`name` varchar(500) NULL ,PRIMARY KEY (`id`)) ;

2番目のストアドプロシージャload2については、トランザクションを手動で開始することもでき、ストアドプロシージャload3の効果も実現できます。実行時間は次のとおりです。

09:50:44 test> call load1(1000000);
Query OK, 0 rows affected (1 min 4.90 sec)09:54:23 test> truncate table t1;
Query OK, 0 rows affected (0.05 sec)09:54:25 test> call load2(1000000);
Query OK, 1 row affected (1 min 3.38 sec)09:55:32 test> truncate table t1;
Query OK, 0 rows affected (0.20 sec)09:55:58 test> call load3(1000000);
Query OK, 0 rows affected (33.90 sec)

2. 自動送信の使用について

一部の特殊なシナリオでは、自動送信が必ずしも良いとは限らない場合があります。たとえば、前述の循環送信の問題では、MySQL データベースはデフォルトで自動送信 (自動コミット) になります。 MySQL の送信メソッドは次の方法で変更できます:

09:57:42 test> begin;
Query OK, 0 rows affected (0.00 sec)09:57:46 test> call load2(1000000);
Query OK, 1 row affected (34.08 sec)09:58:26 test> commit;
Query OK, 0 rows affected (0.76 sec)

START TRANSATION または BEGIN を使用してトランザクションを明示的に開始することもできます。 MySQL は自動的に

SET AUTOCOMMIT=0 を実行し、COMMIT または ROLLBACK がトランザクションを終了した後に SET AUTOCOMMIT=1 を実行します。

3. 自動ロールバックを使用して例外を処理する

ストアド プロセスで例外が発生した場合はどうすればよいですか? Innodb ストレージ エンジンは、HANDLER を介したトランザクションの自動ロールバックをサポートしています。保存処理中にエラーが発生した場合、ロールバック操作が自動的に実行されます。次の例を見てみましょう。

10:35:34 test> SET AUTOCOMMIT=0;
Query OK, 0 rows affected (0.00 sec)

テストテーブルは次のとおりです

CREATE PROCEDURE sp_auto_rollback_demo()
BEGIN
   DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
   START TRANSACTION;
   INSERT INTO b select 1;
   INSERT INTO b select 2;
   INSERT INTO b select 1;
   INSERT INTO b select 3;
   COMMIT;

END;

上記のストアドプロシージャを実行すると、2番目のレコード1を挿入するときにエラーが発生しますが、自動ロールバック操作が有効になっているため、このストアドプロシージャの実行結果は手順は以下の通りです:

CREATE TABLE `b` (  
 `a` int(11) NOT NULL DEFAULT &#39;0&#39;,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

問題なく正常に動作しているようですが、sp_auto_rollback_demo を実行した際に成功したのか失敗したのか?これは次のように処理できます。例は次のとおりです。

10:09:46 test> call sp_auto_rollback_demo;
Query OK, 0 rows affected (0.01 sec)
10:10:04 test> select * from b;Empty set (0.00 sec)

エラーが発生した場合は、最初にロールバックしてから、操作中にエラーが発生したことを示す -1 を返します。 1 が返されると、通常の動作が示されます。実行結果は次のとおりです。

DROP PROCEDURE IF EXISTS sp_auto_rollback_demo;
CREATE PROCEDURE sp_auto_rollback_demo()BEGIN   
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT -1; 
END;   
START TRANSACTION;   
INSERT INTO b select 1;   
INSERT INTO b select 2;   
INSERT INTO b select 1;   
INSERT INTO b select 3;   
COMMIT;   
SELECT 1;
END;

上記は、MySQL トランザクション プログラミングのパフォーマンスと問題分析の内容です [開発者必読]。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) を参照してください。 )!

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。