1.事物的概念

事务就是将一组MySQL语句打包成为一个整体,在这组MySQL语句执行的过程中,要么全部成功,要么全部失败,一个事务中的MySQL语句可以有一条或多条,我们平时写的一条条MySQL语句本质上就是一个个只有一条MySQL语句的事务。

2.事务的ACID特性

事务的ACID特性指的是Atomicity(原⼦性)Durability(持久性)Consistency(⼀致性)Isolation (隔离性)

Atomicity(原子性):一个事务中的MySQL语句要么全部执行成功,要么全部执行失败,不会出现一个事务只执行成功了一半的情况,即一个事务就是一个不可再分的最小单元,只有执行成功和执行失败两种状态。而如果一个事务在执行过程中发生错误,就会使数据回滚(rollback)到事务还未执行的初始状态。

Consistency(一致性):在事务开始和事务结束以后,数据库的完整性不会被破坏,即事务写入的数据要满足预设的所有规则,包括数据的精度、关联性以及关于事务执⾏过程中服 务器崩溃后如何恢复

Isolation(隔离性):数据库允许多个并发事务对数据进行读写和修改,而隔离性可以用来防止由于多个事务的交叉执行而导致的数据不一致的情况。我们可以根据不同的应用场景下的数据库性能和安全的要求来选择不同的隔离级别

Durability(持久性):事务结束之后,对数据的修改会永久地写入存储介质,即使系统崩溃也不会丢失

3.如何使用事务

3.1 查看支持事务的存储引擎

使用事务的前提是数据库支持事务,而在MySQL中支持事务的存储引擎为InnoDB,我们可以通过show engines; 语句进行查看,查看结果如下图所示

从图中可以看出,InnoDB引擎中的transaction(事务)一列是YES,说明该引擎支持事务

3.2 使用事务的语法

3.2.1 开始事务

开始事务有两个语句,任选其一即可,且MySQL当中不区分大小写,根据个人习惯来使用就可以

语法一:

START TRANSACTION;

语法二:

BEGIN;

3.2.2 回滚事务

回滚事务即使数据恢复到还没有执行这个事务时的状态

rollback;

3.2.3 提交事务

提交事务即使该事务运行且将数据进行持久化保存

commit;

无论是提交事务或者是回滚事务,在这之后的事务都会关闭。

事务中间的语句和之前的普通MySQL语句一样。

3.3 保存点

当我们在直接回滚事务时,会直接将数据恢复成事务还未执行时的状态,但如果事务的前半部分并没有问题,在直接回滚事务后我们又要重新去写相应的SQL语句,这就会增添很多麻烦。那么有没有一个东西可以使事务回滚时回到指定的位置而不是开头呢?对此,MySQL提出了保存点的概念,在事务执行的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态。

设置保存点的语法:

SAVEPOINT savepoint1;

后面跟的是保存点的名字

示例:

当我们设定了一个保存点sp1后,即使在下面又进行了数据的修改,但当我们回滚事物时指定其回滚到sp1时,数据就会恢复到保存点sp1时的状态,具体细节如下:

4.事务的隔离和隔离级别

4.1 隔离性的概念

MySQL服务可以同时被多个客户端访问,每个客户端执行的SQL语句以事务为基本单位,那么不 同的客户端在对同⼀张表中的同⼀条数据进户修改的时候就可能出现相互影响的情况为了保证不同的事务之间在执行的过程中不受影响,那么事务之间就需要要相互隔离,这种特性就是隔离性。

4.2 隔离级别

事务间不同程度的隔离,称为事务的隔离级别,不同的隔离级别在性能和安全方面做了取舍,有 的隔离级别注重并发性,有的注重安全性,有的则是并发和安全适中。在MySQL的InnoDB引擎中事务的隔离级别有四种,分别是:

1.READ UNCOMMITTED  读未提交

2.READ COMMITTED  读已提交

3.REPEATABLE READ  可重复读

4.SERIALIZABLE  串行化

4.3 不同隔离级别存在的问题

1.READ UNCOMMITTED  读未提交与脏读

READ UNCOMMITTED隔离级别 由于在读取数据时不做任何限制,所以并发性能很高,但是会出现大量的数据安全问题,比如在事务A中执行了⼀条 INSERT 语句,在没有执行COMMIT的情况下,会在事务B中被读取到,此时如果事务A执行回滚操作,那么事务B中读取到事务A写入的数据将没有意义,我们把这个现象叫做 " 脏读 "。

在进行脏读现象的观察时,我们要先将MySQL的限制级别调整为 read uncommitted; 调整方式如下图所示:

脏读现象如下图所示,由该图可知,在第一个事务刚插入了 “王五” 这条记录还未提交事务时,第二个事务查询时就已经可以查出 “王五” 这条记录,此时若第一个事务进行了回滚操作(rollback)后,第二个事务查询到的关于 “王五” 的这条记录就是一条无效记录,这也就是脏读现象。

2.READ COMMITTED  读已提交与不可重复读

当我们将隔离级别调整为READ COMMITTED时,这时事务只能读到了其他事务提交之后的数据,这样就避免了脏读问题,但会出现不可重复读的问题,比如事务A先对某条数据进行了查询,之后事务B对这条数据进行了修改,并且提交( COMMIT )事务,事务A再对这条数据进行查询时,得到了事务B修改之后的结果,这导致了事务A在同⼀个事务中以相同的条件查询得到了不同的值,这个现象叫做"不可重复读"。

在进行不可重复读的现象的观察时,我们也要记得把MySQL的隔离级别调整为 read conmmitted;

调整方法如下:

不可重复读现象如下图所示,当事务1对某一条记录进行了查询,之后事务2对该条记录进行了修改并提交事务,后续若事务1再次查询该条记录时的值将是事务2进行修改之后的值,这就是不可重复读现象

3.REPEATABLE READ  可重复读与幻读

为了解决不可重复读问题,我们可以把隔离级别调整务中读取的数据在任何时候都是相同的结果,但还会出现一个问题,事务A查询了一个区间的记录得到结果集A,事务B向这个区间的间隙中写入了一条记录并提交,事务A再查询这个区间的结果集时会查到事务B新写入的记录得到结果集B,两次查询的结果集不一致,这个现象就是"幻读"。

在进行幻读的现象的观察时,我们不好将隔离级别设置为repeatable read 来观察,因为MySQL中的innoDB存储引擎使用了next-key锁,锁住了目标记录和之前行的间隙,解决了部分的幻读问题(并非完全解决)。这也使得我们不方便观察幻读现象。所以,为了方便,我们还是在read committed 隔离级别下观察幻读现象

幻读现象如下图所示:

当事务1查询一个结果集之后,事务2往该结果集中插入了一条数据并提交,此时事务1再次查询该结果集时出现的结果就会多出事务2新插入的记录,这条记录就是幻读行,而这个现象就称作幻读

4.SERIALIZABLE  串行化

串行化使每一条SQL语句依次执行,使事务没有了并发性,以效率为代价换来了绝对的数据安全,不会引发以上的各种问题。

四种隔离级别的并发性能和隔离力度如下图所示:

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐