一、概念
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) 系统崩溃或断电时事务自动回退
示例:
数据库事物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 种数据不一致问题:脏读、幻读、不可重复读
用到命令:设置session 级别事务隔离级别:
set session transaction isolation level read uncommitted/committed/repeatable read/serializable;
查询事务隔离级别:
select @@tx_isolation;
开始一个事务:begin;
事务回滚:rollback;
提交事务:commit;
脏读(Drity Read)
如有事务A和B,A读取了B未提交的数据
表原始数据
操作步骤,开两个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;
5.client1执行:rollback;
6.client2执行:select from user;不可重复读(Non-repeatable read)
当一个事务在执行过程中,数据被另外一个事务修改,造成本次事务前后读取的信息不一样
set session transaction isolation level read committed;幻读(Phantom Read)
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
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
不可重复读和幻读的差别在于侧重点不同,前者侧重于修改,后者侧重于新增、删除