目次
トランザクションのプロセス全体は次のとおりです アトミック操作は同じです 最終的にはすべて成功するかすべて失敗します このアトミック性は最終結果からわかります 最終結果からこのプロセスは分割できません" >Atomicity(アトミシティ)トランザクションのプロセス全体は次のとおりです アトミック操作は同じです 最終的にはすべて成功するかすべて失敗します このアトミック性は最終結果からわかります 最終結果からこのプロセスは分割できません
トランザクションは、データベースをある整合性状態から別の整合性状態に変更する必要があります。 " >Consistency(整合性)トランザクションは、データベースをある整合性状態から別の整合性状態に変更する必要があります。
したがって、トランザクションは " >暗黙的なトランザクションを有効にするかどうかは、変数 autocommit によって制御されます。 したがって、トランザクションは
mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit   | ON   |+---------------+-------+1 row in set, 1 warning (0.00 sec)
ログイン後にコピー
autocommit が ON の場合、自動送信がオンになっていることを意味します。 " > 自動送信のために変数 autocommit がオンになっているかどうかを確認します。
mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit   | ON   |+---------------+-------+1 row in set, 1 warning (0.00 sec)
ログイン後にコピー
autocommit が ON の場合、自動送信がオンになっていることを意味します。
トランザクションを手動で制御する 2 つの方法: " >トランザクションを手動で制御する 2 つの方法:
ホームページ データベース mysql チュートリアル mysqlトランザクションとは何ですか

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

Apr 04, 2023 am 10:46 AM
mysql 事務

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 までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

MySQL:世界で最も人気のあるデータベースの紹介 MySQL:世界で最も人気のあるデータベースの紹介 Apr 12, 2025 am 12:18 AM

MySQLはオープンソースのリレーショナルデータベース管理システムであり、主にデータを迅速かつ確実に保存および取得するために使用されます。その実用的な原則には、クライアントリクエスト、クエリ解像度、クエリの実行、返品結果が含まれます。使用法の例には、テーブルの作成、データの挿入とクエリ、および参加操作などの高度な機能が含まれます。一般的なエラーには、SQL構文、データ型、およびアクセス許可、および最適化の提案には、インデックスの使用、最適化されたクエリ、およびテーブルの分割が含まれます。

単一のスレッドレディスの使用方法 単一のスレッドレディスの使用方法 Apr 10, 2025 pm 07:12 PM

Redisは、単一のスレッドアーキテクチャを使用して、高性能、シンプルさ、一貫性を提供します。 I/Oマルチプレックス、イベントループ、ノンブロッキングI/O、共有メモリを使用して同時性を向上させますが、並行性の制限、単一の障害、および書き込み集約型のワークロードには適していません。

MySQLの場所:データベースとプログラミング MySQLの場所:データベースとプログラミング Apr 13, 2025 am 12:18 AM

データベースとプログラミングにおけるMySQLの位置は非常に重要です。これは、さまざまなアプリケーションシナリオで広く使用されているオープンソースのリレーショナルデータベース管理システムです。 1)MySQLは、効率的なデータストレージ、組織、および検索機能を提供し、Web、モバイル、およびエンタープライズレベルのシステムをサポートします。 2)クライアントサーバーアーキテクチャを使用し、複数のストレージエンジンとインデックスの最適化をサポートします。 3)基本的な使用には、テーブルの作成とデータの挿入が含まれ、高度な使用法にはマルチテーブル結合と複雑なクエリが含まれます。 4)SQL構文エラーやパフォーマンスの問題などのよくある質問は、説明コマンドとスロークエリログを介してデバッグできます。 5)パフォーマンス最適化方法には、インデックスの合理的な使用、最適化されたクエリ、およびキャッシュの使用が含まれます。ベストプラクティスには、トランザクションと準備された星の使用が含まれます

なぜMySQLを使用するのですか?利点と利点 なぜMySQLを使用するのですか?利点と利点 Apr 12, 2025 am 12:17 AM

MySQLは、そのパフォーマンス、信頼性、使いやすさ、コミュニティサポートに選択されています。 1.MYSQLは、複数のデータ型と高度なクエリ操作をサポートし、効率的なデータストレージおよび検索機能を提供します。 2.クライアントサーバーアーキテクチャと複数のストレージエンジンを採用して、トランザクションとクエリの最適化をサポートします。 3.使いやすく、さまざまなオペレーティングシステムとプログラミング言語をサポートしています。 4.強力なコミュニティサポートを提供し、豊富なリソースとソリューションを提供します。

Apacheのデータベースに接続する方法 Apacheのデータベースに接続する方法 Apr 13, 2025 pm 01:03 PM

Apacheはデータベースに接続するには、次の手順が必要です。データベースドライバーをインストールします。 web.xmlファイルを構成して、接続プールを作成します。 JDBCデータソースを作成し、接続設定を指定します。 JDBC APIを使用して、接続の取得、ステートメントの作成、バインディングパラメーター、クエリまたは更新の実行、結果の処理など、Javaコードのデータベースにアクセスします。

DockerによるMySQLを開始する方法 DockerによるMySQLを開始する方法 Apr 15, 2025 pm 12:09 PM

DockerでMySQLを起動するプロセスは、次の手順で構成されています。MySQLイメージをプルしてコンテナを作成および起動し、ルートユーザーパスワードを設定し、ポート検証接続をマップしてデータベースを作成し、ユーザーはすべての権限をデータベースに付与します。

phpmyAdminの包括的な使用ガイド phpmyAdminの包括的な使用ガイド Apr 10, 2025 pm 10:42 PM

PHPMyAdminは単なるデータベース管理ツールではなく、MySQLを深く理解し、プログラミングスキルを向上させることができます。コア関数には、CRUDおよびSQLクエリの実行が含まれ、SQLステートメントの原則を理解することが重要です。高度なヒントには、データのエクスポート/インポートと許可管理が含まれ、深いセキュリティの理解が必要です。潜在的な問題にはSQLインジェクションが含まれ、ソリューションはパラメーター化されたクエリとバックアップです。パフォーマンスの最適化には、SQLステートメントの最適化とインデックスの使用が含まれます。ベストプラクティスは、コード仕様、セキュリティプラクティス、および定期的なバックアップを強調しています。

See all articles