ホームページ  >  記事  >  データベース  >  MySQL トランザクションの最も完全かつ詳細な説明

MySQL トランザクションの最も完全かつ詳細な説明

藏色散人
藏色散人転載
2019-09-10 14:36:483235ブラウズ

トランザクションとは何ですか?

トランザクションを説明する公式の MySQL 文は何ですか? MySQL トランザクションは主に、大規模な操作と複雑性の高いデータを処理するために使用されます。では、なぜデータ量がこれほど膨大になるのでしょうか?なぜ複雑性が高いのでしょうか?私自身の理解を使って説明しましょう。トランザクションとは、実はMySQLにおけるデータの処理方法の一つで、主にデータの整合性が高く、データ間の依存関係が大きい場合に使用されます。たとえば、シャオ・チャンさんがシャオ・リーさんのキャッシュカードに200元を送金したが、シャオ・チャンさんが送金を確認するボタンをクリックしたところ、システムが突然クラッシュした。次のような誤った状況がいくつかあります:

1. Xiao Zhang のお金は Xiao Li の口座に送金されましたが、彼自身の口座のお金は差し引かれませんでした。

2. Zhang のお金は差し引かれませんでした。 Xiao Li の口座に送金されましたが、彼自身の口座のお金が差し引かれました。

このようなビジネス シナリオでは、MySQL トランザクションのメンテナンスが必要です。マシンに障害が発生した場合でも、データはまだ正しいです。.

トランザクションの利用条件

MySQL トランザクションを利用するには、MySQL のストレージ エンジンのサポートが必要です。現在、トランザクションをサポートする MySQL の組み込みストレージ エンジンには InnoDB と NDB クラスターが含まれ、サードパーティのストレージ エンジンには PBXT と XtrDB が含まれます。

MySQL のトランザクションには次の特性があります (ACID):

原子性:

トランザクションは、分割できない最小単位である必要があります。動作するには、各トランザクションのすべての操作が成功または失敗する必要があります。一部の操作が失敗し、一部の操作が成功するということは決してあり得ません。これは、いわゆるアトミック性の概念です。

一貫性:

一貫性は上記の例と同様で、例外が発生してもデータは正しいままです。つまり、トランザクションの実行に失敗した場合でも、データは異常事態の影響を受けず、常に正確性を維持します。

分離:

When aトランザクションはまだコミットされていないため、各トランザクションは互いに分離されており、相補性が影響を受けます。

Durability (耐久性):

When トランザクションが送信された後、

トランザクションの分離レベル

MySQL の分離特性について話すときは、分離についても話さなければなりません。性別にはいくつかのレベルがあります。これが関係する理由については、次のように簡単に理解できます。トランザクション操作を同時に実行する 2 つのリクエストがあり、これら 2 つのトランザクションが同じデータに対して操作される場合、どちらの最終結果はどちらのリクエストに基づいて決まります。勝つ?分離レベルが異なると結果も異なるため、トランザクションの分離レベルも非常に重要なポイントです。

分離レベルは次の点に分かれています:

1. 非コミット読み取り(READ UNCOMMITTED)

1 つのトランザクションでデータに加えられた変更は、コミットされていない場合でも、他のトランザクションには引き続き表示されます。この場合、ダーティ リードが発生しやすくなり、データの整合性に影響します。

例: Xiao Ming が Alipay で支払いをしたとき、キャッシュ カードの残高がまだ 300 元あることを確認しましたが、実際には、彼のガール フレンドがキャッシュ カードに 200 元を入金していたため、残高は 100 元しかありませんでした。この時点で、ガールフレンドは保存したくなかったので、ロールバック操作をクリックしましたが、Xiao Ming は支払いに失敗しました。

2. READ COMMITTED

A トランザクションが始まると、送信された他のトランザクションのみが表示されます。この場合、反復不可能な読み取りが発生しやすくなります (2 つの読み取り結果が異なります)

例: 上記と同じ例を使用すると、彼のガール フレンドがカードをスワイプしたとき、カード内の残高は100元ですが、最後の支払いをクリックすると、残高が足りないと表示され、この時点でカード内のお金がなくなっていました。これは、Xiao Ming のガール フレンドが支払いを行ったとき、Xiao Ming が操作したトランザクションはまだ送信されていなかったため、Xiao Ming のガール フレンドが 2 回目にした結果は異なっていたためです。

##レコードを複数回読み取った結果は一貫しています。繰り返し読み取りを行うことで、上記の繰り返し不可能な読み取り状況を解決できます。しかし、トランザクションが特定の範囲のレコードを読み取っているときに、別のトランザクションがその範囲に新しいデータを挿入し、トランザクションが再度データを読み取ると、そのデータが最初に読み取ったデータよりも大きいことが判明するという状況が発生します。もう 1 つのレコードがあります。これはいわゆるファントム リーディングです。2 つの読み取り結果には一貫性がありません。

例: Xiao Ming のガールフレンドが銀行カードの記録をチェックしたとき、彼女は 5 つの消費記録を確認しました。今回、Xiao Ming は「消費」を読んでいました。この消費記録は消費記録に記録されていました。彼女がもう一度記録を読んだところ、6 つの記録があることがわかりました。

4. シリアル化可能

シリアルはキューのようなもので、各トランザクションはキューに入れられて実行を待ち、前のトランザクションが送信されて初めて次のトランザクションを操作できるようになります。この状況は上記のファントム読み取りを解決できますが、各データにロックが追加されるため、多数のロック タイムアウトやロックの競合が容易に発生する可能性があります。特に、一部の同時実行性の高いビジネス シナリオには適していません。

# #例: 銀行にお金を預けるために列に並びますが、前の人がすべての操作を完了した場合にのみ、次の人が先に進むことができます。真ん中の人はキューに飛び込むことはできません。1 人ずつ並ぶことしかできません。トランザクションのシリアル化はそのような概念です。実際、いわゆるシリアル モードもそのような概念です。

MySQL トランザクションの最も完全かつ詳細な説明

MySQL トランザクションの最も完全かつ詳細な説明

#分離の概要

上記の例を通して、それを見つけるのは難しくありません。ダーティ リードとノンリピータブル リードはデータの更新に重点を置き、ファントム リードはデータの挿入に重点を置きます。

複数のストレージ エンジンのトランザクション処理方法

上記のトランザクション使用条件に従って、次のことが得られます。 MyISAM ストレージ エンジンなど、一部のストレージ エンジンはトランザクションをサポートしていないことが知られています。トランザクションでトランザクション ストレージ エンジンと非トランザクション ストレージが使用されている場合、コミットは正常に続行できますが、非トランザクション ストレージ エンジンをロールバックすると、応答エラー メッセージが表示されます。特定の情報はストレージ エンジンに関連しています。

トランザクションの使用方法##MySQL のトランザクションは暗黙的に有効になります。つまり、SQL ステートメントはトランザクションです。SQL ステートメントが実行されると、トランザクションは提出されました。デモ中、私たちは明示的にオンにしました。

MySQL での自動コミット

前述したように、MySQL のトランザクションは暗黙的にオンになります。つまり、毎回SQL は自動的に送信されます。閉じる必要がある場合は、自動コミット オプションを設定する必要があります。

// 查看autocommit配置值(1或者ON则表示开启)
mysql root@127.0.0.1:(none)> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set
Time: 0.018s
// 设置autocommit配置值
mysql root@127.0.0.1:(none)> set autocommit = 0;
Query OK, 0 rows affected
Time: 0.000s
mysql root@127.0.0.1:(none)> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set
Time: 0.013s

1。テーブル構造は次のとおりです

mysql root@127.0.0.1:test> desc user;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | <null> | auto_increment |
| name | varchar(255) | YES | | <null> | |
| age | int(2) | YES | | <null> | |
+-------+--------------+------+-----+---------+----------------+
3 rows in set
Time: 0.013s

SQL ステートメント

CREATE TABLE `test`.`Untitled` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`age` int(2) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2. トランザクションを使用する

MySQL はトランザクションを実装します

以下のコードでは、主に次の操作を実行します

a. トランザクションを開きます

b. データを変更します

c. データが変更されたかどうかをクエリします

d. データのロールバック

e. データを再度クエリし、データが変更前の状態に戻りました

f . データを変更します

g. トランザクションの送信

h. データをクエリし、データが最後に変更されたことを確認します変更された状態

##i. トランザクション ロールバックを試行します

j. クエリを実行してロールバックされたかどうかを確認すると、データがまだ最後に変更された状態にあることがわかり、トランザクション ロールバックが行われます。失敗しました

// 我们先查看表中的数据,id为1的age字段是12
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 12 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.013s
// 开启事务
mysql root@127.0.0.1:test> begin;
Query OK, 0 rows affected
Time: 0.001s
// 将id为1的age字段改为10
mysql root@127.0.0.1:test> update user set age=10 where id=1;
Query OK, 1 row affected
Time: 0.001s
// 再次查询数据时,发现数据改为修改后的值
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 10 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.012s
// 此时我们进行回滚操作
mysql root@127.0.0.1:test> rollback;
Query OK, 0 rows affected
Time: 0.001s
// 再次查询发现数据回到最初状态
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 12 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.019s
// 我们再次对数据进行修改
mysql root@127.0.0.1:test> update user set age=15 where id=1;
Query OK, 1 row affected
Time: 0.001s
// 此时将事务进行提交
mysql root@127.0.0.1:test> commit;
Query OK, 0 rows affected
Time: 0.000s
// 发现此时的数据变为我们最终提交的值
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 15 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.012s
// 我们尝试用刚才回滚的方式进行还原数据
mysql root@127.0.0.1:test> rollback;
Query OK, 0 rows affected
Time: 0.000s
// 发现数据无法回退了,仍然是提交后的数据
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 15 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.017s

PHP トランザクション実装サンプル コード

<?php
// 连接MySQL
$mysqli = new mysqli(&#39;127.0.0.1&#39;, &#39;root&#39;, &#39;123456&#39;, &#39;test&#39;, 3306);
// 关闭事务自动提交
$mysqli->autocommit(false);
// 1.开启事务
$mysqli->begin_transaction();
// 2.修改数据
$mysqli->query("update user set age=10 where id=1");
// 3.查看数据
$mysqli->query("select * from user");
// 4.事务回滚
$mysqli->rollback();
// 5.查看数据
$mysqli->query("select * from user");
// 7.修改数据
$mysqli->query("update user set age=15 where id=1");
// 8.事务提交
$mysqli->commit();
// 9.事务回滚
$mysqli->rollback();
// 10.查看数据
$mysqli->query("select * from user");
トランザクションの分離レベルを設定する方法

// 查看当前的事务隔离级别
mysql root@127.0.0.1:test> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set
Time: 0.015s
// 设置隔离级别
set session transaction isolation level 隔离级别(上面事务隔离级别中的英文单词);

以上がMySQL トランザクションの最も完全かつ詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は公众号 深夜有话聊で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。