事务:transaction
事务用来维护数据库的完整性。
事务的4个特性(ACID):
- 原子性(A):执行事务时,要么都成功,要么都不成功,由恢复机制实现
- 一致性(C):执行后,保持数据的一致,由用户负责
- 隔离性(I):事务之间相互独立,互不影响,通过系统的并发控制机制实现
- 持久性(D):数据永久存储在数据库中,通过恢复机制实现
事务的ACID原则保证了一个事务或者成功提交,或者失败回滚,二者必居其一。
事务控制语句
- 开始事务:
begin 或start transaction
- 提交事务:
commit
,使对数据库的所有修改成为永久性的 - 回滚事务:
rollback
,回滚结束的事务,并撤销正在进行的所未提交的修改 - 创建保存点:
savepoint identifier
,允许在事务中创建一个保存点,一个事务可以有多个savapoint - 删除保存点:
release savapoint identifier
, - 事务回滚到标记点:
rollback to idetifier
- 设置事务的隔离级别:
set transaction
mysql 事务处理的两种方法
- begin commit rollback实现
- 直接用set 来改变mysql的自动提交模式
-set autocommit=0
禁止自动提交
-set autocommit=1
开启自动提交
事务测试
1. 第一种方式开启事务
- 查看mysql事务自动提交方式
select @@autocommit;
注: ‘@@’ 表示内置对象
- 关闭自动提交事务:
set autocommit = 0
2. 第二种方式开启事务
- 开始一个事务
在没有commit之前查询如上图所示,但是数据库内部显示如下所示,并没有显示新插入的数据33。
commit后,数据库的显示如下,出现了新插入的数据,证明在事务未被提交之前不会改变数据库。且commit之后rollback无效。
实例
- 背景描述
- 场景设置
- 操作
- 创建数据库和表,并插入数据
create database shop; # 创建数据库
use shop; # 使用数据库
create table account #创建表
(
id int not null primary key auto_increment,
name varchar(32) not null,
cash decimal(9,2) not null
);
# 插入数据
insert into account(name,cash) values('A',2000.00),('B',10000.00);
- 开始事务
begin;
update account set cash = cash - 500 where name = 'A'; #A账户减少500元
update account set cash = cashh + 500 where name = 'B'; # 模拟B账户增加出错
select * from account ; #查看当前状态
rollback ;# 回滚
select * from account ; #查看当前状态
commit ; #提交
事务的隔离级别
隔离等级
1. Read Uncommitted(读取未提交的内容):在该隔离级别,所有的事务都可以看到其他未提交事务的执行结果,也称之为脏读(Dirty Ready)
2. Read Committed(读取提交内容):一个事务在提交之前对其他事务是不可见的,这个级别支持不可重复读取,避免脏读。
3. Repeatable Read(可复读):mysql默认的隔离级别,他确保同一事务的多个实例在并发读取数据时,会看到同样的数据,但是会导致幻读,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围内的数据时,会发现有新的"幻影"行,Innodb和Falcon存储引擎通过多版本并发控制(MVCC)机制解决了该问题。
4. Serializerable(可串行化):最高的隔离级别,通过强制事务排序,使之不可能相互冲突,解决了幻读问题,它是在每个读的数据行上加上共享锁,在这个级别可能导致大量的超时和锁竞争。
脏读:当一个事务的数据未提交时,另一个事务在查看数据时将刚才未提交的数据查询到
幻读:读取到数据,因某一个事务的原因,导致刚才数据消失
查看隔离级别
- 查看当前会话的隔离级别
select @@tx_isolation; 注:mysql8.0之前
select @@transaction_isolation; 注:mysql8.0之后 - 查看系统的隔离级别
select @@global.tx_isolation; 注:mysql8.0之前
select @@global.transaction_isolation; 注:mysql8.0之后
设置隔离级别
set transaction_isolation =’ 隔离方式’