当前位置:首页 > 文章列表 > 数据库 > MySQL > mysql事务的含义是什么

mysql事务的含义是什么

来源:亿速云 2023-05-10 17:46:26 0浏览 收藏

一分耕耘,一分收获!既然都打开这篇《mysql事务的含义是什么》,就坚持看下去,学下去吧!本文主要会给大家讲到等等知识点,如果大家对本文有好的建议或者看到有不足之处,非常欢迎大家积极提出!在后续文章我会继续更新数据库相关的内容,希望对大家都有所帮助!

mysql事务是指对数据库执行一批操作,在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况;事务是一个原子操作,是一个最小执行单元,可以由一个或多个SQL语句组成。

什么是事务?

数据库中的事务是指对数据库执行一批操作,在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。

  • 事务是一个原子操作。是一个最小执行单元。可以由一个或多个SQL语句组成

  • 在同一个事务当中,所有的SQL语句都成功执行时,整 个事务成功,有一个SQL语句执行失败,整个事务都执行失败。

举个例子:

比如A用户给B用户转账100操作,过程如下:

  1. 从A账户扣100

  2. 给B账户加100

如果在事务的支持下,上面最终只有2种结果:

  1. 操作成功:A账户减少100;B账户增加100

  2. 操作失败:A、B两个账户都没有发生变化

如果没有事务的支持,可能出现错:A账户减少了100,此时系统挂了,导致B账户没有加上100,而A账户凭空少了100。

事务的几个特性(ACID) -重点

原子性(Atomicity)

事务的整个过程如原子操作一样,最终要么全部成功,或者全部失败,这个原子性是从最终结果来看的,从最终结果来看这个过程是不可分割的。

一致性(Consistency)

一个事务必须使数据库从一个一致性状态变换到另一个一致性状态。

首先回顾一下一致性的定义。所谓一致性,指的是数据处于一种有意义的状态,这种状态是语义上的而不是语法上的。最常见的例子是转帐。例如从帐户A转一笔钱到帐户B上,如果帐户A上的钱减少了,而帐户B上的钱却没有增加,那么我们认为此时数据处于不一致的状态。

从这段话的理解来看,所谓一致性,即,从实际的业务逻辑上来说,最终结果是对的、是跟程序员的所期望的结果完全符合的

隔离性(Isolation)

一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

  • 这里先提一下事务的隔离级别:

    • 读未提交:read uncommitted

    • 读已提交:read committed

    • 可重复读:repeatable read

    • 串行化:serializable

持久性(Durability)

一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。

Mysql中事务操作

mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务。

是否开启隐式事务是由变量autocommit控制的。

所以事务分为隐式事务显式事务

隐式事务

事务自动开启、提交或回滚,比如insert、update、delete语句,事务的开启、提交或回滚由mysql内部自动控制的。

查看变量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)

可以看到上面数据回滚了。

我们把autocommit还原回去:

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
T1start transaction;
T2select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6select * from test1;
T7
commit;
T8commit;

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
T1start transaction;
T2select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6select * from test1;
T7
commit;
T8select * from test1;
T9commit;

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
T1start transaction;
T2select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5
select * from test1;
T6select * from test1;
T7
commit;
T8select * from test1;
T9commit;
T10select * 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
T1start 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’;

T9commit;

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
T1start transaction;
T2select * from test1;
T3
start transaction;
T4
insert into test1 values (1);
T5commit;
T6
commit;

按时间顺序运行上面的命令,会发现T4-B这样会被阻塞,直到T5-A执行完毕。

上面这个演示的是读写互斥产生的效果,大家可以自己去写一下写读、写写互斥的效果。

可以看出来,事务只能串行执行了。串行情况下不存在脏读、不可重复读、幻读的问题了。

小结

  • 读未提交( Read Uncommitted )

    • 读未提交是隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据,这就是脏读(Dirty Read)。

  • 读已提交( Read Committed )

    • 在 Read Committed 隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。

  • 可重复读( Repeatable Read )

    • 当使用Repeatable Read隔离级别时,某个事务可能会面临幻像读取的问题。幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。幻影读取是一种记录被遗漏的情况,认为不存在,但实际上可以成功更新。更新成功后,再次读取会出现该记录。

  • 可串行化( Serializable )

    • Serializable 是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。

    • 虽然 Serializable 隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。通常情况下,除非涉及到非常重要的场景,否则不会使用Serializable隔离级别。

默认隔离级别:如果没有指定隔离级别,数据库就会使用默认的隔离级别。在MySQL中,如果使用 InnoDB,默认的隔离级别是Repeatable Read。

关于隔离级别的选择

  1. 需要对各种隔离级别产生的现象非常了解,然后选择的时候才能游刃有余

  2. 隔离级别越高,并发性也低,比如最高级别SERIALIZABLE会让事物串行执行,并发操作变成串行了,会导致系统性能直接降低。

  3. 具体选择哪种需要结合具体的业务来选择。

  4. 读已提交(READ-COMMITTED)通常用的比较多。

今天带大家了解了的相关知识,希望对你有所帮助;关于数据库的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

版本声明
本文转载于:亿速云 如有侵犯,请联系study_golang@163.com删除
mysql数据库如何批量替换mysql数据库如何批量替换
上一篇
mysql数据库如何批量替换
可复现、自动化、低成本、高评估水平,首个自动化评估大模型的大模型PandaLM来了
下一篇
可复现、自动化、低成本、高评估水平,首个自动化评估大模型的大模型PandaLM来了
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • AI Make Song:零门槛AI音乐创作平台,助你轻松制作个性化音乐
    AI Make Song
    AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
    7次使用
  • SongGenerator.io:零门槛AI音乐生成器,快速创作高质量音乐
    SongGenerator
    探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
    7次使用
  •  BeArt AI换脸:免费在线工具,轻松实现照片、视频、GIF换脸
    BeArt AI换脸
    探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
    6次使用
  • SEO标题协启动:AI驱动的智能对话与内容生成平台 - 提升创作效率
    协启动
    SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
    13次使用
  • Brev AI:零注册门槛的全功能免费AI音乐创作平台
    Brev AI
    探索Brev AI,一个无需注册即可免费使用的AI音乐创作平台,提供多功能工具如音乐生成、去人声、歌词创作等,适用于内容创作、商业配乐和个人创作,满足您的音乐需求。
    14次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码