1.事务
一个最小的不可再分的工作单元;
通常一个事务对应一个完整的业务(例如转账业务);
一个完整的业务中包含大量的DML(insert、update、delete)语句。
2.事务四大特征(ACID)
原子性:事务中的所有操作,要么全部完成,要么全部不完成。执行过程只要发生错误,就一定会回滚。
一致性:事务执行前后需保证数据处于一致性的状态。比如约束完整、触发器正常、数据精准度等。
隔离性:事务的执行不被其它事务干扰。事务之间是相互隔离的。
持久性:事务处理结束后,对数据的修改是永久的,即便系统故障也不会丢失。
3.隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
读已提交(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
查看Mysql数据库当前隔离级别
8.0版本之前
SELECT @@tx_isolation;
8.0版本之后
SELECT @@transaction_isolation;
Mysql默认隔离级别是:可重复读REPEATABLE-READ
4.读未提交
设置隔离级别:READ UNCOMMITTED
设置完隔离,需要重新连接
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Mysql默认设置,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。
查看当前自动提交状态
show variables like 'autocommit';
设置只对当前连接有效
set autocommit = 0;
ON:表示启动
OFF:表示关闭
创建账户表
create table account(
id int primary key,
name varchar(20) not null,
money double(11,2) default 0.00
);
插入数据
insert into account values(1, "小明", 1000.00), (2, "小强", 1000.00);
开启事务
START TRANSACTION;
或者
begin;
老板给小明发1千工资,还没提交,小明查询工资多了1千,跟老板收到工资,于是老板回滚了。
update account set money = money + 1000.00 where name = '小明';
rollback;
老板发1k工资开启了事务,小明读取到未提交的数据2k,在老板回滚后,小明数据又恢复到1k,小明看到的2k数据是脏数据,这种情况称为脏读。
不可重复读
事务的四大特征之隔离性:事务的执行是不受其他事务的干扰的。
A事务两次查询到的结果不一致
幻读
A事务两次查询到的结果不一致
从上面看,感觉不可重复读跟幻读很想。
两者的区别
不可重复读:是针对数据修改,可通过行锁解决
幻读:是针对数据新增或删除,会改变记录总数,需要通过表锁解决
5.读已提交
设置隔离级别:READ COMMITTED
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
取消自动提交
set autocommit = 0;
show variables like 'autocommit';
脏读
解决脏读问题
不可重复读
不能解决不可重复读问题
同样的也不能解决幻读问题
6.可重复读
设置隔离级别:REPEATABLE READ
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
set autocommit = 0;
能解决脏读就不演示了
不可重复读
能解决不可重复读
但不能解决幻读
7.串行化
设置隔离级别:SERIALIZABLE
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
set autocommit = 0;
能解决脏读,也能解决不可重复读,这里不演示
幻读
串行化,使事务排队,前一个事务未完成,下一个事务等待
虽然串行化可以解决幻读问题,但太影响性能了,用户体验极差