ホームページ  >  記事  >  データベース  >  mysqlトランザクションとは何ですか

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

藏色散人
藏色散人オリジナル
2023-04-04 10:46:155130ブラウズ

Mysql トランザクションは、データベース上での一連の操作の実行を指します。同じトランザクション内で、これらの操作はすべて成功するか失敗するかのいずれかであり、部分的に成功することはありません。トランザクションはアトミックな操作であり、最小実行単位は 1 つ以上の SQL ステートメントで構成されます。

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

このチュートリアルの動作環境: Windows 10 システム、MySQL バージョン 5.7、Dell G3 コンピューター。

#トランザクションの詳細説明

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

データベース内のトランザクションとは、データベースに対する一連の操作の実行を指します。同じトランザクション内で、これらの操作はすべて成功するか失敗するかのいずれかであり、部分的に成功することはありません。

#トランザクションはアトミックな操作です。最小実行単位です。 1 つ以上の SQL ステートメントで構成できます。
  • 同じトランザクション内で、すべての SQL ステートメントが正常に実行されると、トランザクション全体が成功します。1 つの SQL ステートメントが実行に失敗すると、トランザクション全体の実行が失敗します。
  • 例:

たとえば、ユーザー A がユーザー B に 100 を転送します。プロセスは次のとおりです:

アカウント A から 100 を差し引く
  1. アカウント B に 100 を追加
  2. トランザクションでサポートされている場合、上記の結果は 2 つだけです:

操作は成功しました。アカ​​ウント A は 100 減少します。 ; アカウント B が 100 増加します
  1. 操作は失敗しました: アカウント A も B も変更されていません
  2. トランザクション サポートがない場合、エラーが発生する可能性があります: アカウント A は 100 減らされ、この時点でシステムがハングするため、B アカウントは 100 を追加できず、A アカウントは突然 100 を失います。

トランザクション (ACID) のいくつかの特徴 - 重要なポイント

Atomicity(アトミシティ)トランザクションのプロセス全体は次のとおりです アトミック操作は同じです 最終的にはすべて成功するかすべて失敗します このアトミック性は最終結果からわかります 最終結果からこのプロセスは分割できません

Consistency(整合性)トランザクションは、データベースをある整合性状態から別の整合性状態に変更する必要があります。

まず、一貫性の定義を確認してください。いわゆる一貫性とは、データが意味のある状態にあることを意味します。これは、

文法的な

ではなく、意味的なです。最も一般的な例は送金です。例えば、口座Aから口座Bにお金を移動する場合、口座Aのお金が減っても口座Bのお金が増えていない場合、その時点でデータが不整合な状態になっていると考えられます。

この段落を理解すると、いわゆる一貫性とは、実際のビジネス ロジックからの最終結果が正しく、プログラマの期待する結果と完全に一致していることを意味します。

##分離

#トランザクションの実行は、他のトランザクションによって干渉されることはできません。つまり、トランザクション内で使用される操作とデータは他の同時トランザクションから分離されており、同時に実行されるトランザクションは相互に干渉できません。

トランザクションの分離レベルは次のとおりです:

Read uncommitted: read uncommitted

    Read commit: Read committed
    • Repeatable Read: 反復可能read
    • Serializable
    • ##永続性 (耐久性)
  • トランザクションが送信されると、その変更はデータベースは永続的である必要があります。トランザクションがコミットされると、データはハードディスクに保存され、変更は永続的になります。

Mysql でのトランザクション操作

MySQL のトランザクションは、デフォルトでは暗黙的なトランザクションです。挿入、更新、および削除操作が実行されると、データベースは自動的にトランザクションを開始し、コミットします。 、またはロールバックします。

暗黙的なトランザクションを有効にするかどうかは、変数 autocommit によって制御されます。 したがって、トランザクションは

暗黙的トランザクション

明示的トランザクション

に分類されます。

暗黙的なトランザクショントランザクションは、挿入、更新、削除ステートメントなど、自動的に開かれ、送信され、またはロールバックされます。トランザクションの開始、送信、またはロールバックは自動的に開始されます。 、mysql.controlによって送信またはロールバックされます。

自動送信のために変数 autocommit がオンになっているかどうかを確認します。
mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit   | ON   |+---------------+-------+1 row in set, 1 warning (0.00 sec)
autocommit が ON の場合、自動送信がオンになっていることを意味します。

明示的なトランザクション

トランザクションは手動で開く、送信する、またはロールバックする必要があり、開発者自身によって制御されます。

トランザクションを手動で制御する 2 つの方法:

方法 1:

構文:

//设置不自动提交事务set autocommit=0;//执行事务操作commit|rollback;
例 1: トランザクション操作を送信します。次のように:
mysql> create table test1 (a int);Query OK, 0 rows affected (0.01 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> set autocommit=0;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values(1);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)

例 2: ロールバック トランザクション操作、次のように:

mysql> set autocommit=0;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values(2);Query OK, 1 row affected (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)
上記のデータがロールバックされていることがわかります。

自動コミットを復元します:

mysql> set autocommit=1;Query OK, 0 rows affected (0.00 sec)

方法 2:

構文:

start transaction;//开启事务//执行事务操作commit|rollback;
例 1: トランザクション操作を次のように送信します。以下に続きます:
mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (2);Query OK, 1 row affected (0.00 sec)mysql> insert into test1 values (3);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   2 ||   3 |+------+3 rows in set (0.00 sec)

上面成功插入了2条数据。

示例2:回滚事务操作,如下:

mysql> select * from test1;+------+| a   |+------+|   1 ||   2 ||   3 |+------+3 rows in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> delete from test1;Query OK, 3 rows affected (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   2 ||   3 |+------+3 rows in set (0.00 sec)

上面事务中我们删除了test1的数据,显示删除了3行,最后回滚了事务。

savepoint关键字

在事务中我们执行了一大批操作,可能我们只想回滚部分数据,怎么做呢?

我们可以将一大批操作分为几个部分,然后指定回滚某个部分。可以使用savepoin来实现,效果如下:

先清除test1表数据:

mysql> delete from test1;Query OK, 3 rows affected (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)

演示savepoint效果,认真看:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (1);Query OK, 1 row affected (0.00 sec)mysql> savepoint part1;//设置一个保存点Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (2);Query OK, 1 row affected (0.00 sec)mysql> rollback to part1;//将savepint = part1的语句到当前语句之间所有的操作回滚Query OK, 0 rows affected (0.00 sec)mysql> commit;//提交事务Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)

从上面可以看出,执行了2次插入操作,最后只插入了1条数据。

savepoint需要结合rollback to sp1一起使用,可以将保存点sp1到rollback to之间的操作回滚掉。

只读事务

表示在事务中执行的是一些只读操作,如查询,但是不会做insert、update、delete操作,数据库内部对只读事务可能会有一些性能上的优化。

用法如下:

start transaction read only;

示例:

mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> start transaction read only;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   1 |+------+2 rows in set (0.00 sec)mysql> delete from test1;ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   1 |+------+2 rows in set (0.00 sec)

只读事务中执行delete会报错。

事务中的一些问题(重点)

这些问题主要是基于数据在多个事务中的可见性来说的。也是并发事务产生的问题。

更新丢失

丢失更新就是两个不同的事务(或者Java程序线程)在某一时刻对同一数据进行读取后,先后进行修改。导致第一次操作数据丢失。

第一类丢失更新 :A,B 事务同时操作同一数据,A先对改数据进行了更改,B再次更改时失败然后回滚,把A更新的数据也回滚了。(事务撤销造成的撤销丢失)

第二类丢失更新:A,B 事务同时操作同一数据,A先对改数据进行了更改,B再次更改并且提交,把A提交的数据给覆盖了。(事务提交造成的覆盖丢失)

脏读

一个事务在执行的过程中读取到了其他事务还没有提交的数据。 这个还是比较好理解的。

两个事务同时操作同一数据,A事务对该数据进行了修改还没提交的时候,B事务访问了该条事务,并且使用了该数据,此时A事务回滚,那么B事务读到的就是脏数据。

比如事务1,修改了某个数据 事务2,刚好访问了事务1修改后的数据

此时事务1,回滚了操作 事务2,读到还是回滚前的数据

读已提交

从字面上我们就可以理解,即一个事务操作过程中可以读取到其他事务已经提交的数据。

事务中的每次读取操作,读取到的都是数据库中其他事务已提交的最新的数据(相当于当前读)

不可重复读

在同一事务中,多次读取同一数据返回的结果有所不同,换句话说,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读” 在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。

这种情况发生 在一个事务内多次读同一数据。A事务查询某条数据,该事务未结束时,B事务也访问同一数据并进行了修改。那么在A事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。

事务1,查询某个数据 事务2,修改了某个数据,提交

事务1,再次查询这个数据

这样事务1两次查询的数据不一样,称为不可重复读

可重复读

一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。

幻读

脏读、不可重复读、可重复读、幻读,其中最难理解的是幻读

以mysql为例:

  • 幻读现象例子:

    • 可重复读模式下,比如有个用户表,手机号码为主键,有两个事物进行如下操作
    • 事务A操作如下: 1、打开事务 2、查询号码为X的记录,不存在 3、插入号码为X的数据,插入报错(为什么会报错,先向下看) 4、查询号码为X的记录,发现还是不存在(由于是可重复读,所以读取记录X还是不存在的)
    • 事物B操作:在事务A第2步操作时插入了一条X的记录,所以会导致A中第3步插入报错(违反了唯一约束)
    • 上面操作对A来说就像发生了幻觉一样,明明查询X(A中第二步、第四步)不存在,但却无法插入成功
    • 幻读可以这么理解:事务中后面的操作(插入号码X)需要上面的读取操作(查询号码X的记录)提供支持,但读取操作却不能支持下面的操作时产生的错误,就像发生了幻觉一样。
  • 看第二种解释:

    • 事务A在操作一堆数据的时候,事务B插入了一条数据,A事务再次(第二次)查询,发现多了一条数据,像是幻觉。与不可重复读类似,不同的是一个是修改删除操作,一个是新增操作。

如果还是理解不了的,继续向下看,后面后详细的演示。

事务的隔离级别

当多个事务同时进行的时候,如何确保当前事务中数据的正确性,比如A、B两个事物同时进行的时候,A是否可以看到B已提交的数据或者B未提交的数据,这个需要依靠事务的隔离级别来保证,不同的隔离级别中所产生的效果是不一样的。

事务隔离级别主要是解决了上面多个事务之间数据可见性及数据正确性的问题。(或者说为了解决并发控制可能产生的异常问题,数据库定义了四种事务的隔离级别)

隔离级别分为4种:

  1. 读未提交:READ-UNCOMMITTED
  2. 读已提交:READ-COMMITTED
  3. 可重复读:REPEATABLE-READ
  4. 串行:SERIALIZABLE

上面4中隔离级别越来越强,会导致数据库的并发性也越来越低。

查看隔离级别

mysql> show variables like 'transaction_isolation';+-----------------------+----------------+| Variable_name     | Value      |+-----------------------+----------------+| transaction_isolation | READ-COMMITTED |+-----------------------+----------------+1 row in set, 1 warning (0.00 sec)

隔离级别的设置

分2步骤,修改文件、重启mysql,如下:

修改mysql中的my.init文件,我们将隔离级别设置为:READ-UNCOMMITTED,如下:

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=READ-UNCOMMITTED

以管理员身份打开cmd窗口,重启mysql,如下:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

各种隔离级别中会出现的问题

隔离级别 脏读可能性 不可重复读可能性 幻读可能性
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE

下面我们来演示一下,各种隔离级别中可见性的问题,开启两个窗口,叫做A、B窗口,两个窗口中登录mysql。

READ-UNCOMMITTED:读未提交

将隔离级别置为READ-UNCOMMITTED:

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=READ-UNCOMMITTED

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

查看隔离级别:

mysql> show variables like 'transaction_isolation';+-----------------------+----------------+| Variable_name     | Value      |+-----------------------+----------------+| transaction_isolation | READ-UNCOMMITTED |+-----------------------+----------------+1 row in set, 1 warning (0.00 sec)

先清空test1表数据:

delete from test1;select * from test1;

按时间顺序在2个窗口中执行下面操作:

时间 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6 select * from test1;
T7
commit;
T8 commit;

A窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (1);Query OK, 1 row affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

看一下:

T2-A:无数据,T6-A:有数据,T6时刻B还未提交,此时A已经看到了B插入的数据,说明出现了脏读

T2-A:无数据,T6-A:有数据,查询到的结果不一样,说明不可重复读

结论:读未提交情况下,可以读取到其他事务还未提交的数据,多次读取结果不一样,出现了脏读、不可重复读、幻读

READ-COMMITTED:读已提交

将隔离级别置为READ-COMMITTED

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=READ-COMMITTED

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

查看隔离级别:

mysql> show variables like 'transaction_isolation';+-----------------------+----------------+| Variable_name     | Value      |+-----------------------+----------------+| transaction_isolation | READ-COMMITTED |+-----------------------+----------------+1 row in set, 1 warning (0.00 sec)

先清空test1表数据:

delete from test1;select * from test1;

按时间顺序在2个窗口中执行下面操作:

时间 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6 select * from test1;
T7
commit;
T8 select * from test1;
T9 commit;

A窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (1);Query OK, 1 row affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 |+------+1 row in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

看一下:

T5-B:有数据,T6-A窗口:无数据,A看不到B的数据,说明没有脏读

T6-A窗口:无数据,T8-A:看到了B插入的数据,此时B已经提交了,A看到了B已提交的数据,说明可以读取到已提交的数据

T2-A、T6-A:无数据,T8-A:有数据,多次读取结果不一样,说明不可重复读

结论:读已提交情况下,无法读取到其他事务还未提交的数据,可以读取到其他事务已经提交的数据,多次读取结果不一样,未出现脏读,出现了读已提交、不可重复读、幻读

REPEATABLE-READ:可重复读

将隔离级别置为REPEATABLE-READ

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=REPEATABLE-READ

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

查看隔离级别:

mysql> show variables like 'transaction_isolation';+-----------------------+----------------+| Variable_name     | Value      |+-----------------------+----------------+| transaction_isolation | REPEATABLE-READ |+-----------------------+----------------+1 row in set, 1 warning (0.00 sec)

先清空test1表数据:

delete from test1;select * from test1;

按时间顺序在2个窗口中执行下面操作:

时间 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6 select * from test1;
T7
commit;
T8 select * from test1;
T9 commit;
T10 select * from test1;

A窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   1 |+------+2 rows in set (0.00 sec)

B窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (1);Query OK, 1 row affected (0.00 sec)mysql> select * from test1;+------+| a   |+------+|   1 ||   1 |+------+2 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

看一下:

T2-A、T6-A窗口:无数据,T5-B:有数据,A看不到B的数据,说明没有脏读

T8-A:无数据,此时B已经提交了,A看不到B已提交的数据,A中3次读的结果一样都是没有数据的,说明可重复读

结论:可重复读情况下,未出现脏读,未读取到其他事务已提交的数据,多次读取结果一致,即可重复读。

幻读演示

将隔离级别置为REPEATABLE-READ

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=REPEATABLE-READ

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

查看隔离级别:

mysql> show variables like 'transaction_isolation';+-----------------------+----------------+| Variable_name     | Value      |+-----------------------+----------------+| transaction_isolation | REPEATABLE-READ |+-----------------------+----------------+1 row in set, 1 warning (0.00 sec)

准备数据:

mysql> create table t_user(id int primary key,name varchar(16) unique key);Query OK, 0 rows affected (0.01 sec)mysql> insert into t_user values (1,'路人甲Java'),(2,'路人甲Java');ERROR 1062 (23000): Duplicate entry '路人甲Java' ***\*for\**** key 'name'mysql> select * from t_user;Empty set (0.00 sec)

上面我们创建t_user表,name添加了唯一约束,表示name不能重复,否则报错。

按时间顺序在2个窗口中执行下面操作:

时间 窗口A 窗口B
T1 start transaction;
T2
start transaction;
T3
– 插入路人甲Java
insert into t_user values (1,‘路人甲Java’);
T4
select * from t_user;
T5 – 查看路人甲Java是否存在
select * from t_user where name=‘路人甲Java’;

T6
commit;
T7 – 插入路人甲Java
insert into t_user values (2,‘路人甲Java’);

T8 – 查看路人甲Java是否存在
select * from t_user where name=‘路人甲Java’;

T9 commit;

A窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from t_user where name='路人甲Java';Empty set (0.00 sec)mysql> insert into t_user values (2,'路人甲Java');ERROR 1062 (23000): Duplicate entry '路人甲Java' ***\*for\**** key 'name'mysql> select * from t_user where name='路人甲Java';Empty set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into t_user values (1,'路人甲Java');Query OK, 1 row affected (0.00 sec)mysql> select * from t_user;+----+---------------+| id | name      |+----+---------------+|  1 | 路人甲Java   |+----+---------------+1 row in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)

看一下:

A想插入数据路人甲Java,插入之前先查询了一下(T5时刻)该用户是否存在,发现不存在,然后在T7时刻执行插入,报错了,报数据已经存在了,因为T6时刻B已经插入了路人甲Java。

然后A有点郁闷,刚才查的时候不存在的,然后A不相信自己的眼睛,又去查一次(T8时刻),发现路人甲Java还是不存在的。

此时A心里想:数据明明不存在啊,为什么无法插入呢?这不是懵逼了么,A觉得如同发生了幻觉一样。

SERIALIZABLE:串行

SERIALIZABLE会让并发的事务串行执行(多个事务之间读写、写读、写写会产生互斥,效果就是串行执行,多个事务之间的读读不会产生互斥)。

读写互斥:事务A中先读取操作,事务B发起写入操作,事务A中的读取会导致事务B中的写入处于等待状态,直到A事务完成为止。

表示我开启一个事务,为了保证事务中不会出现上面说的问题(脏读、不可重复读、读已提交、幻读),那么我读取的时候,其他事务有修改数据的操作需要排队等待,等待我读取完成之后,他们才可以继续。

写读、写写也是互斥的,读写互斥类似。

这个类似于java中的java.util.concurrent.lock.ReentrantReadWriteLock类产生的效果。

下面演示读写互斥的效果。

将隔离级别置为SERIALIZABLE

# 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行transaction-isolation=SERIALIZABLE

重启mysql:

C:\Windows\system32>net stop mysql
mysql 服务正在停止..mysql 服务已成功停止。

C:\Windows\system32>net start mysql
mysql 服务正在启动 .mysql 服务已经启动成功。

查看隔离级别:

mysql> show variables like 'transaction_isolation';+-----------------------+--------------+| Variable_name     | Value     |+-----------------------+--------------+| transaction_isolation | SERIALIZABLE |+-----------------------+--------------+1 row in set, 1 warning (0.00 sec)

先清空test1表数据:

delete from test1;select * from test1;

按时间顺序在2个窗口中执行下面操作:

时间 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5 commit;
T6
commit;

上記のコマンドを時系列に実行すると、T5-A が完了するまで T4-B がブロックされることがわかります。

上記のデモは、読み取り-書き込み相互排除の効果です。書き込み-読み取りおよび書き込み-書き込み相互排除の効果については、自分で書くことができます。

トランザクションはシリアルにのみ実行できることがわかります。シリアル状況におけるダーティ リード、非反復読み取り、ファントム リードには問題はありません。

概要

  • Read Uncommitted(Read Uncommitted)

    • Read Uncommitted は分離レベルです。最低のトランザクションレベル。この分離レベルでは、あるトランザクションは更新されたもののコミットされていないデータを別のトランザクションから読み取ります。他のトランザクションがロールバックすると、現在のトランザクションによって読み取られたデータはダーティ データになります。これはダーティ リードと呼ばれます。
  • Read Committed

    • Read Committed 分離レベルでは、トランザクションで非反復読み取り (非反復読み取り) の問題が発生する可能性があります。非反復読み取りとは、トランザクション内で同じデータを複数回読み取ることを意味します。トランザクションが終了する前に別のトランザクションがたまたまこのデータを変更した場合、最初のトランザクションで 2 回読み取られたデータに不整合が生じる可能性があります。
  • Repeatable Read

    • Repeatable Read 分離レベルでは、トランザクションでファントム読み取り (ファントム読み取り) の問題が発生する可能性があります。ファントム読み取りとは、トランザクションで特定のレコードを初めてクエリしたときに、そのレコードが存在しないことが判明することを意味しますが、この存在しないレコードを更新しようとすると、実際には成功することがあり、同じレコードを読み取ると、再び、それは魔法のように機能します。ファントム読み取りとは、読み込まれていないため存在しないと思われているレコードですが、実際には正常に更新でき、更新に成功した後、再度読み込むと表示されるようになります。
  • Serializable

    • Serializable は最も厳密な分離レベルです。 Serializable 分離​​レベルでは、すべてのトランザクションが順番に実行されるため、ダーティ リード、非反復読み取り、ファントム リードは発生しません。
    • Serializable 分離​​レベルのトランザクションは最も高いセキュリティを備えていますが、トランザクションはシリアルに実行されるため、効率が大幅に低下し、アプリケーションのパフォーマンスが大幅に低下します。特に重要な状況がない場合、通常、Serializable 分離​​レベルは使用されません。

#デフォルトの分離レベル: 分離レベルが指定されていない場合、データベースはデフォルトの分離レベルを使用します。 MySQL で InnoDB を使用する場合、デフォルトの分離レベルはRepeatable Readです。

#分離レベルの選択について

さまざまな分離レベルによって引き起こされる現象をよく理解する必要があります。簡単に選択してください
  1. 分離レベルが高くなるほど、同時実行性は低くなります。たとえば、最高レベルの SERIALIZABLE では物事がシリアルに実行され、同時操作がシリアルになり、システムのパフォーマンスが直接低下します。 。
  2. 具体的な選択は、特定のビジネスに基づいて行う必要があります。
  3. READ-COMMITTED は通常、より頻繁に使用されます。

概要

トランザクションの 4 つの特性: 原子性、一貫性、分離性、耐久性を理解する
  1. マスター共通の概要トランザクション操作用のコマンド
  2. set autocommit は、自動トランザクション送信をオンにするかどうかを設定できます
  3. トランザクションの開始: トランザクションをオンにする
  4. トランザクションの読み取り専用開始: 読み取り専用をオンにします。トランザクションのみ##​​
  5. #commit: トランザクションをコミットします。
  6. rollback: トランザクションをロールバックします。
  7. savepoint: セーブポイントを設定します。
  8. rollback to save point: 次のことができます。セーブポイントにロールバックする
  9. 4 つの分離レベルをマスターし、その特性を理解する
  10. ダーティ リード、非再現リード、ファントム リード
  11. [関連する推奨事項:

    mysql ビデオ チュートリアル

    ]

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

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