一、概念

1. 什么是数据库事务?

事务(Transaction)是一个操作序列(集合)。这些操作要么都做,要么都不 做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位。

2. 事务控制语句

事务控制语句

事务控制语句包含以下 7 个关键字:
① BEGIN 显式地开启一个事务
② COMMIT 提交事务,并使已对数据库进行的所有修改成为永久性的
③ ROLLBACK ,会进行回滚。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改
④ SAVEPOINT identifier,允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT
⑤ RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常
⑥ ROLLBACK TO identifier 把事务回滚到保存点
⑦ SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE

事务的结束

事务的结束可由以下操作进行触发:
1) 用户显式执行 commit 语句提交操作或 Rollback 语句回退
2) 开启了自动提交,执行了DML语句后
通过SET AUTOCOMMIT=1 可以设置开启自动提交,但是一般会关闭自动提交,因为效率太低
3) 执行DDL语句,事务会自动提交
4) 用户正常断开连接时,Transaction自动提交
5) 系统崩溃或断电时事务自动回退

示例:

image.png

数据库事物ACID

原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

一、事务隔离级别

1.1 SQL标准四个隔离级别

隔离级别 脏读 不可重复 读 幻读
READ- UNCOMMITTED(读未提交)
READ-COMMITTED(读已提交) ×
REPEATABLE- READ 可重复读(mysql 默认) × ×
SERIALIZABLE(序列化)
串行执行,读操作一定要等写操作执行完成
× × ×

读取未提交:

  • 事务的修改,即使没有提交,对其他事务也都是可见的。
  • 事务能够读取未提交的数据,这种情况称为脏读

    读取已提交:

  • 事务读取已提交的数据,大多数数据库的默认隔离级别。当一个事务在执行过程中,数据被另外一个事务修改,造成本次事务前后读取的信息不一样,这种情况称为不可重复读

    可重复读:

  • 这个级别是MySQL的默认隔离级别,它解决了脏读的问题,同时也保证了同一个事务多次读取同样的记录是一致的,但这个级别还是会出现幻读的情况。

  • 幻读是指当一个事务A读取某一个范围的数据时,另一个事务B在这个范围插入行,A事务再次读取这个范围的数据时,会产生幻读

    可串行化:

  • 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

  • 事务隔离机制的实现基于锁机制和并发调度。
  • 其中并发调度使用的是MVCC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。
  • 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,
  • InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读)并不会有任何性能损失。

    1.2 隔离级别存在问题

    不同的隔离级别会产生不同的问题,具体有如下 3 种数据不一致问题:脏读、幻读、不可重复读
    用到命令:
    1. 设置session 级别事务隔离级别:
    2. set session transaction isolation level read uncommitted/committed/repeatable read/serializable;
    3. 查询事务隔离级别:
    4. select @@tx_isolation;
    5. 开始一个事务:begin;
    6. 事务回滚:rollback;
    7. 提交事务:commit;

    脏读(Drity Read)

    如有事务A和B,A读取了B未提交的数据
    image.png
    表原始数据
    image.png
    操作步骤,开两个navicat窗口
    1.client1执行:
    set session transaction isolation level read uncommitted;
    begin;
    2.client2执行:
    set session transaction isolation level read uncommitted;
    begin;
    3.client1执行:update user set name=’骚欣2’ where id =1;
    4.client2执行:select from user;
    image.png
    5.client1执行:rollback;
    6.client2执行:select
    from user;
    image.png

    不可重复读(Non-repeatable read)

    当一个事务在执行过程中,数据被另外一个事务修改,造成本次事务前后读取的信息不一样
    set session transaction isolation level read committed;
    image.png

    幻读(Phantom Read)

    在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
    image.png
    client1:
    set session transaction isolation level repeatable read;
    begin;
    insert into user values(5,”豫东”);
    commit;
    client2:
    set session transaction isolation level repeatable read;
    begin;
    select * from user;
    insert into user values(5,”豫东”);
    commit;
    报错:
    insert into user values(5,”豫东”)
    > 1062 - Duplicate entry ‘5’ for key ‘PRIMARY’
    > 时间: 0.009s
    不可重复读和幻读的差别在于侧重点不同,前者侧重于修改,后者侧重于新增、删除