qu'est-ce qu'une transaction MySQL
La transaction MySQL fait référence à l'exécution d'un lot d'opérations sur la base de données. Dans la même transaction, ces opérations finiront toutes par réussir ou échouer, et il n'y aura pas de succès partiel ; qui peut consister en une ou plusieurs instructions SQL.
L'environnement d'exploitation de ce tutoriel : système Windows 10, MySQL version 5.7, ordinateur Dell G3.
Explication détaillée des transactions
Qu'est-ce qu'une transaction ?
Une transaction dans une base de données fait référence à l'exécution d'un lot d'opérations sur la base de données. Dans la même transaction, ces opérations réussiront ou échoueront toutes.
- Une transaction est une opération atomique. Est une unité d’exécution minimale. Il peut être composé d'une ou plusieurs instructions SQL
- Dans la même transaction, lorsque toutes les instructions SQL sont exécutées avec succès, la transaction entière réussit. Si une instruction SQL ne parvient pas à s'exécuter, la transaction entière échoue.
Par exemple :
Par exemple, l'utilisateur A transfère 100 à l'utilisateur B. Le processus est le suivant :
- Déduisez 100 du compte A
- Ajoutez 100 au compte B
Avec le support des transactions, le ci-dessus aboutit à seulement 2 résultats :
- L'opération est réussie : le compte A est réduit de 100 ; le compte B est augmenté de 100
- L'opération échoue : il n'y a aucun changement dans les deux comptes A et B
S'il y a s'il n'y a pas de support de transaction, une erreur peut se produire : le compte A a été réduit de 100, mais le système était en panne à ce moment-là. Par conséquent, 100 n'ont pas été ajoutés au compte B, tandis que le compte A a perdu 100 à partir de rien.
Plusieurs caractéristiques des transactions (ACID) - Points clés
Atomicité (Atomicité)
L'ensemble du processus d'une transaction est comme une opération atomique En fin de compte, soit tous réussissent, soit tous échouent. déterminé à partir du résultat final Du point de vue du résultat final, ce processus est indissociable.
Cohérence
Une transaction doit faire passer la base de données d'un état de cohérence à un autre état de cohérence.
Tout d’abord, passons en revue la définition de la cohérence. La soi-disant cohérence signifie que les données sont dans un état significatif, qui est sémantiquement plutôt que grammaticalement . L’exemple le plus courant est celui des transferts d’argent. Par exemple, si une somme d’argent est transférée du compte A vers le compte B, si l’argent du compte A diminue mais que l’argent du compte B n’augmente pas, alors nous pensons que les données sont dans un état incohérent à ce moment-là.
D'après la compréhension de ce paragraphe, la soi-disant cohérence signifie qu'à partir de la logique métier réelle, le résultat final est correct et entièrement cohérent avec les résultats attendus du programmeur
Isolement Isolation
L'exécution d'une transaction ne peut pas être perturbé par d’autres transactions. Autrement dit, les opérations et les données utilisées dans une transaction sont isolées des autres transactions simultanées et les transactions exécutées simultanément ne peuvent pas interférer les unes avec les autres.
- Voici le niveau d'isolement de la transaction :
- Lecture non validée : lecture non validée
- Lecture validée : lecture validée
- Lecture répétable : lecture répétable
- Sérialisable : sérialisable
Durabilité
O une fois un La transaction est validée, ses modifications apportées aux données de la base de données doivent être permanentes. Lorsque la transaction est validée, les données seront conservées sur le disque dur et la modification sera permanente.
Opérations de transaction dans Mysql
Les transactions dans MySQL sont des transactions implicites par défaut. Lorsque des opérations d'insertion, de mise à jour et de suppression sont effectuées, la base de données démarre automatiquement la transaction, valide ou annule la transaction.
L'activation des transactions implicites est contrôlée par la variable autocommit.
Les transactions sont donc divisées en transactions implicites et transactions explicites.
Transactions implicites
Les transactions sont automatiquement ouvertes, soumises ou annulées, telles que les instructions d'insertion, de mise à jour, de suppression. L'ouverture, la soumission ou l'annulation des transactions sont automatiquement contrôlées en interne par MySQL.
Vérifiez si la variable autocommit est activée pour la soumission automatique
mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | ON |+---------------+-------+1 row in set, 1 warning (0.00 sec)
autocommit étant ON signifie que la soumission automatique est activée.
Transactions explicites
Les transactions doivent être ouvertes, soumises ou annulées manuellement et sont contrôlées par le développeur lui-même.
2 façons de contrôler manuellement les transactions :
Méthode 1 :
Syntaxe :
//设置不自动提交事务set autocommit=0;//执行事务操作commit|rollback;
Exemple 1 : Soumettre l'opération de transaction, comme suit :
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)
Exemple 2 : Annuler l'opération de transaction, comme suit :
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)
Vous pouvez voir que les données ci-dessus ont été restaurées.
Nous restaurons l'autocommit :
mysql> set autocommit=1;Query OK, 0 rows affected (0.00 sec)
Méthode 2 :
Syntaxe :
start transaction;//开启事务//执行事务操作commit|rollback;
Exemple 1 : Soumettez l'opération de transaction, comme suit :
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种:
- 读未提交:READ-UNCOMMITTED
- 读已提交:READ-COMMITTED
- 可重复读:REPEATABLE-READ
- 串行: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; |
Exécutez les commandes ci-dessus dans l'ordre chronologique et vous constaterez que T4-B sera bloqué jusqu'à ce que T5-A soit terminé.
La démonstration ci-dessus est l'effet de l'exclusion mutuelle en lecture-écriture. Vous pouvez écrire vous-même sur l'effet de l'exclusion mutuelle en écriture-lecture et en écriture-écriture.
On voit que les transactions ne peuvent être exécutées qu'en série. Il n'y a aucun problème avec les lectures sales, les lectures non répétables et les lectures fantômes dans les situations en série.
Résumé
-
Lecture non validée (Lecture non validée)
- Lire non validée est le niveau de transaction avec le niveau d'isolement le plus bas. Sous ce niveau d'isolement, une transaction lira les données mises à jour mais non validées d'une autre transaction. Si l'autre transaction est annulée, les données lues par la transaction en cours seront des données sales.
-
Lecture validée
- Sous le niveau d'isolement Lecture validée, une transaction peut rencontrer le problème de lecture non répétable. La lecture non répétable fait référence à la lecture des mêmes données plusieurs fois au sein d'une transaction, avant la fin de la transaction, si une autre transaction modifie les données, alors lors de la première transaction, les données lues deux fois peuvent être incohérentes.
-
Lecture répétable (Lecture répétable)
- Sous le niveau d'isolement Lecture répétable, une transaction peut rencontrer le problème de lecture fantôme (Phantom Read). La lecture fantôme signifie que dans une transaction, la première fois que vous interrogez un certain enregistrement, vous constatez qu'il n'existe pas. Cependant, lorsque vous essayez de mettre à jour cet enregistrement inexistant, vous pouvez réussir, et lorsque vous relisez le même enregistrement. , cela fonctionne comme par magie. La lecture fantôme est un enregistrement qui n'a pas été lu et dont on pense qu'il n'existe pas, mais en fait, il peut être mis à jour avec succès. De plus, une fois la mise à jour réussie, il apparaîtra lors de sa nouvelle lecture.
-
Sérialisable
- Sérialisable est le niveau d'isolement le plus strict. Sous le niveau d'isolement sérialisable, toutes les transactions sont exécutées dans l'ordre, de sorte que les lectures incorrectes, les lectures non répétables et les lectures fantômes ne se produiront pas.
- Bien que les transactions sous le niveau d'isolement sérialisable aient la sécurité la plus élevée, puisque les transactions sont exécutées en série, l'efficacité sera considérablement réduite et les performances de l'application seront considérablement réduites. Sauf situation particulièrement importante, le niveau d’isolement Serialisable n’est généralement pas utilisé.
Niveau d'isolement par défaut : Si aucun niveau d'isolement n'est spécifié, la base de données utilisera le niveau d'isolement par défaut. Dans MySQL, si vous utilisez InnoDB, le niveau d'isolement par défaut est Repeatable Read.
À propos du choix du niveau d'isolement
- Vous devez avoir une bonne compréhension des phénomènes provoqués par les différents niveaux d'isolement, et vous pourrez ensuite faire le choix en toute simplicité
- Plus le niveau d'isolement est élevé, plus le niveau d'isolement est bas. Par exemple, le plus haut niveau SERIALIZABLE rendra les choses exécutées en série, les opérations simultanées deviendront en série, réduiront directement les performances du système.
- Le choix spécifique doit être basé sur l'entreprise spécifique.
- READ-COMMITTED est généralement utilisé plus souvent.
Résumé
- Comprendre les 4 caractéristiques des transactions : atomicité, cohérence, isolation et durabilité
- Maîtriser l'introduction de commandes courantes pour les opérations de transaction
- set autocommit peut définir s'il faut activer la soumission automatique des transactions
- start transaction : démarrer la transaction
- start transaction read only : ouvrir une transaction en lecture seule
- commit : valider la transaction
- rollback : restaurer la transaction
- savepoint : définir le point de sauvegarde
- rollback to save point : vous pouvez revenir à une sauvegarde point
- Maîtrisez les 4 niveaux d'isolement et comprenez leurs caractéristiques
Lecture sale, lecture non répétable, lecture fantôme
[Recommandations associées : tutoriel vidéo mysql]
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Vous pouvez ouvrir PHPMYADMIN via les étapes suivantes: 1. Connectez-vous au panneau de configuration du site Web; 2. Trouvez et cliquez sur l'icône PHPMYADMIN; 3. Entrez les informations d'identification MySQL; 4. Cliquez sur "Connexion".

MySQL est un système de gestion de la base de données relationnel open source, principalement utilisé pour stocker et récupérer les données rapidement et de manière fiable. Son principe de travail comprend les demandes des clients, la résolution de requête, l'exécution des requêtes et les résultats de retour. Des exemples d'utilisation comprennent la création de tables, l'insertion et la question des données et les fonctionnalités avancées telles que les opérations de jointure. Les erreurs communes impliquent la syntaxe SQL, les types de données et les autorisations, et les suggestions d'optimisation incluent l'utilisation d'index, les requêtes optimisées et la partition de tables.

Redis utilise une architecture filetée unique pour fournir des performances élevées, une simplicité et une cohérence. Il utilise le multiplexage d'E / S, les boucles d'événements, les E / S non bloquantes et la mémoire partagée pour améliorer la concurrence, mais avec des limites de limitations de concurrence, un point d'échec unique et inadapté aux charges de travail à forte intensité d'écriture.

La position de MySQL dans les bases de données et la programmation est très importante. Il s'agit d'un système de gestion de base de données relationnel open source qui est largement utilisé dans divers scénarios d'application. 1) MySQL fournit des fonctions efficaces de stockage de données, d'organisation et de récupération, en prenant en charge les systèmes Web, mobiles et de niveau d'entreprise. 2) Il utilise une architecture client-serveur, prend en charge plusieurs moteurs de stockage et optimisation d'index. 3) Les usages de base incluent la création de tables et l'insertion de données, et les usages avancés impliquent des jointures multiples et des requêtes complexes. 4) Des questions fréquemment posées telles que les erreurs de syntaxe SQL et les problèmes de performances peuvent être déboguées via la commande Explication et le journal de requête lente. 5) Les méthodes d'optimisation des performances comprennent l'utilisation rationnelle des indices, la requête optimisée et l'utilisation des caches. Les meilleures pratiques incluent l'utilisation des transactions et des acteurs préparés

MySQL est choisi pour ses performances, sa fiabilité, sa facilité d'utilisation et son soutien communautaire. 1.MySQL fournit des fonctions de stockage et de récupération de données efficaces, prenant en charge plusieurs types de données et opérations de requête avancées. 2. Adoptez l'architecture client-serveur et plusieurs moteurs de stockage pour prendre en charge l'optimisation des transactions et des requêtes. 3. Facile à utiliser, prend en charge une variété de systèmes d'exploitation et de langages de programmation. 4. Avoir un solide soutien communautaire et fournir des ressources et des solutions riches.

Apache se connecte à une base de données nécessite les étapes suivantes: Installez le pilote de base de données. Configurez le fichier web.xml pour créer un pool de connexion. Créez une source de données JDBC et spécifiez les paramètres de connexion. Utilisez l'API JDBC pour accéder à la base de données à partir du code Java, y compris l'obtention de connexions, la création d'instructions, les paramètres de liaison, l'exécution de requêtes ou de mises à jour et de traitement des résultats.

Le processus de démarrage de MySQL dans Docker se compose des étapes suivantes: Tirez l'image MySQL pour créer et démarrer le conteneur, définir le mot de passe de l'utilisateur racine et mapper la connexion de vérification du port Créez la base de données et l'utilisateur accorde toutes les autorisations sur la base de données

PhPMyAdmin n'est pas seulement un outil de gestion de la base de données, il peut vous donner une compréhension approfondie de MySQL et améliorer les compétences en programmation. Les fonctions principales incluent l'exécution de la requête CRUD et SQL, et il est crucial de comprendre les principes des instructions SQL. Les conseils avancés incluent l'exportation / l'importation de données et la gestion des autorisations, nécessitant une compréhension approfondie de la sécurité. Les problèmes potentiels incluent l'injection SQL et la solution est des requêtes paramétrées et des sauvegardes. L'optimisation des performances implique l'optimisation des instructions SQL et l'utilisation de l'index. Les meilleures pratiques mettent l'accent sur les spécifications du code, les pratiques de sécurité et les sauvegardes régulières.
