(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示

继续讲解 Mysql 数据库中最重要的一个概念:事务

文章目录

    • 事务
      • 1.1 什么是事务
      • 1.2 执行原理
      • 1.3 如何操作事务
      • 1.4 事务的特点(ACID原则)
      • 1.5 事务并发
      • 1.6 事务隔离级别
        • 1.6.1 事务并发问题操作演示
        • 1.6.2 脏读演示
        • 1.6.3 不可重复读演示
        • 1.6.4 幻读演示

事务

1.1 什么是事务

1、事务是构成多用户使用数据库的基础。

2、举个例子来理解事务:

例子:向公司添加一名新的员工,这个过程大致分为这三步:在数据库中创建一条新的记录 ----> 为新员工添加部门 ----> 建立他的工资和奖金记录。

如果这 3 步中任何一步失败,则系统就必须撤销在此之前所有的变化,删除所有不完整记录的痕迹。这 3 个任务就构成了一个事务,其中任何一个任务的失败都会导致整个事务被撤销。

3、事务:是原子操作,是一个最小执行单元,由一个或多个 SQL 语句组成。这个单元中的每个 SQL 语句是相互依赖的,而且单元作为一个整体是不可分割的。如果单元中的一个语句不能完成,整个单元就会回滚(撤销),所有影响到的数据将返回到事务开始以前的状态。

4、简单总结事务的定义:

  • 一个数据库操作序列
  • 一个不可分割的工作单位
  • 恢复和并发控制的基本单位

事务和程序的比较:

  • 在关系数据库中,一个事务可以是一条或多条 SQL 语句,也可以包含一个或多个程序。
  • 一个程序通常包含多个事务。

1.2 执行原理

1、数据库会为每一个客户端都维护 一个独立空间的缓存区(回滚段)

2、一个事务中所有的 增删改 语句的执行结果会先缓存在回滚段中,而不是持久化到数据库中(查询不存在事务,不影响)

  • 成功:当事务中所有 SQL 语句均正常结束(commit),才会将回滚段中的数据同步到数据库。
  • 失败:整个事务将回滚(rollback)

1.3 如何操作事务

1、默认情况下事务是自动提交的(比如:你写一个 SQL 语句,在没有开始事务的情况下,就默认提交了,假如后面 SQL 语句有问题,前面的需要回滚,但是你已经提交了,就回滚不了了,所以这样不行)

事务开始:设置事务为手动提交set autocommit=0; 0 表示手动提交,1 表示自动提交

事务结束:分为两种情况:

  • 提交事务,事务就结束了,命令为:commit;
  • 回滚事务,事务也结束了,命令为:rollback;

2、未来在 java 代码中的操作

try{
    执行事务
     //上面没报错就提交事务   
    提交事务
} catch() {
    回滚事务
}

1.4 事务的特点(ACID原则)

原子性(Atomicity):表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败。

一致性(Consistency):表示一个事务内有一个操作失败时,所有更改过的数据都必须回滚到修改前的状态。

隔离性(Isolation):指一个事务的操作不能影响到另外一个事务的执行。

持久性(Durability):指即使系统崩溃,一个提交的事务仍然存在(也就是说:一个事务操作完成对数据库的影响是永久的)

1.5 事务并发

什么是事务并发:多个人(人:事务)同时操作同一个表中的数据。

带来的问题:

  • 脏读: 事务A读到了事务B未提交保存的数据。

    举例:比如账户里面有800块钱,此时事务A正常读。但是此时事务B给账户加了200块钱,事务A再读时,读到了1000块钱,但是现在事务B要回滚,这200块没有成功,但是事务A读到了,这不允许,因为事务A读取到了一个不存在的脏数据。

  • 不可重复读: 事务A在同一个事务中,因为事务B修改了数据,并提交了,同样的条件下,造成事务A两次读取到的数据不一致。

    例如:事务在 T1 时间读取到了某一行数据, 在 T2 时间重新读取这一行时候,这一行的数据已经发生修改,所以再次读取时得到了一个和 T1 查询时不同的结果。(因为中间有其他事务提交了 修改

  • 幻读: 事务A在同一个事务中,因为事务B新增了数据,并提交了,如果事务A修改数据, 会出现多修改了一条数据,出现幻觉。

    第一次和第二次读出来的记录数不一样。(因为中间有其他事务提交了 插入/删除

区别:

  • 不可重复读:重点是修改,读的数据不一样;
  • 幻读:重点是新增或者是修改,读的记录数不一样。

1.6 事务隔离级别

使用事务隔离级别来解决:读未提交: read uncommitted、读已提交: read committed、可重复读(mysql 默认的隔离级别): repeatable read、串行化: serializable

×:不能解决 √:能解决
脏读 不可重复读 幻读
读未提交 × × ×
读已提交 × ×
可重复读 ×
串行化

命令行查看事务隔离级别的时候报错:

原因:老版本 MySQL 比如 5 中用的是 tx_isolation,而应该是在 5.7.20 版本之后,用的是 transaction_isolation。 所以:在 MySQL 8 及之后的版本中,只需将语句中的 tx_isolation 替换为 transaction_isolation 即可:

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第1张图片

每启动一个 MySQL 程序,就会获得一个单独的数据库连接

-- 查看当前的隔离级别
select @@transaction_isolation;
-- 设置当前mysql连接的隔离级别(session表示连接的当前窗口)
set session transaction isolation level 隔离级别的英文名称;
-- 设置数据库系统全局的隔离级别
set global transaction isolation level 隔离级别的英文名称;
1.6.1 事务并发问题操作演示

下面进行实际操作演示事务并发:由于 navicat 中无法演示不同事务,这里直接开两个 cmd 窗口来演示不同的事务。
(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第2张图片
事务并发操作的表为:
(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第3张图片

1.6.2 脏读演示

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第4张图片

每个问题的演示都要设置为手动提交:每个事务都需要。

但是设置隔离级别,这里只设置了出现问题的事务(比如:事务A,最好每个事务也设置下)


(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第5张图片

这也出现了另外一个问题,同一个事务内,事务A三次读取的数据不一样,导致不可重复读

怎么解决脏读? 设置隔离级别:读已提交:read committed(这里只给事务A设置了隔离,也可以给B设置同样的隔离级别)

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第6张图片

1.6.3 不可重复读演示

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第7张图片

解决: 设置隔离级别:可重复读 repeatable read

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第8张图片

1.6.4 幻读演示

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示_第9张图片

注意:幻读在实际开发中是可以接收的

解决: 设置隔离级别:serializable。一般不用解决

你可能感兴趣的:(MySQL,mysql,oracle,数据库)