前言
大家好吖,欢迎来到 YY 滴MySQL系列 ,热烈欢迎! 本章主要内容面向接触过C++ Linux的老铁
主要内容含:
基本内容总览
- 详细内容查看下文
一.事务简介
- 核心理念: 把一系列操作当作一个整体
二.事务操作(模拟转账失败)
1.事务操作系列语法1-【查看/设置事务提交方式–提交事务–回滚事务】
- 自动:@@autocommit=1
- 手动:@@autocommit=0
--查看事务提交方式 SELECT @@autocommit ;//会显示 @@autocommit=1;默认为自动 --设置事务提交方式 SET @@autocommit=0;//手动 --提交事务 COMMIT; --回滚事务 ROLLBACK ;
2.事务操作系列语法2-【开启事务–提交事务–回滚事务】
- 总览如下
--开启事务 START TRANSACTION 或 BEGIN; --提交事务 COMMIT ; --回滚事务 ROLLBACK;
※数据准备环节
-- 数据准备 create table account( id int auto_increment primary key comment '主键ID', name varchar(10) comment '姓名', money int comment '余额' ) comment '账户表'; insert into account(id, name, money) VALUES (null,'张三',2000),(null,'李四',2000); -- 恢复数据操作 update account set money = 2000 where name = '张三' or name = '李四';
3.模拟转账失败-(方式一:修改事务提交方式为手动)
- 我们这个实验要用到上面的系列语法1
--查看事务提交方式 SELECT @@autocommit ;//会显示 @@autocommit=1;默认为自动 --设置事务提交方式 SET @@autocommit=0;//手动 --提交事务 COMMIT; --回滚事务 ROLLBACK ;
- 如下方代码所示,我们用
程序执行报错 ...
模拟抛异常 - 此时由于我们 设置为手动提交
set @@autocommit = 0;
, 所以事务并未提交; - 后续
rollback ;
回滚事务即可;
-- 方式一 select @@autocommit; set @@autocommit = 0; -- 设置为手动提交 -- 转账操作 (张三给李四转账1000) -- 1. 查询张三账户余额 select * from account where name = '张三'; -- 2. 将张三账户余额-1000 update account set money = money - 1000 where name = '张三'; 程序执行报错 ...//模拟抛异常 -- 3. 将李四账户余额+1000 update account set money = money + 1000 where name = '李四'; -- 提交事务 commit; -- 回滚事务 rollback ;
4.模拟转账失败-(方式二:不修改事务提交方式,自动)
- 我们这个实验要用到上面的系列语法2
--开启事务 START TRANSACTION 或 BEGIN; --提交事务 COMMIT ; --回滚事务 ROLLBACK;
- 开始操作前记得 改回自动提交
set @@autocommit = 1; -- 改回自动提交
- 如下方代码所示,我们用
程序执行报错 ...
模拟抛异常 - 此时由于我们 开启了事务
start transaction ;
, 所以事务报错后并未提交; - 后续
rollback ;
回滚事务即可;
-- 方式二 -- 改回自动提交 set @@autocommit = 1; -- 转账操作 (张三给李四转账1000) start transaction ; -- 1. 查询张三账户余额 select * from account where name = '张三'; -- 2. 将张三账户余额-1000 update account set money = money - 1000 where name = '张三'; 程序执行报错 ... -- 3. 将李四账户余额+1000 update account set money = money + 1000 where name = '李四'; -- 提交事务 commit; -- 回滚事务 rollback;
三.事务四大特性(A-C-I-D)
- 如下图所示
四.并发事务问题(脏读-幻读-不可重复读)
基本概念一览
- 脏读:一个事务 读到 另外一个事务还 没有提交的数据。
- 不可重复读:一个事务 先后读取同一条记录,但两次读取的 数据不同,称之为不可重复读。
- PS:不可重复读是解决脏读导致的
- 幻读:一个事务按照条件 查询数据时, 没有对应的数据行,但是在 插入数据时,又发现这行数据 已经存在,好像出现了幻影”。
- PS:幻读是解决不可重复读导致的
1.脏读
- 脏读:一个事务 读到 另外一个事务还 没有提交的数据。
- 如下图所示:
2.不可重复读
- 不可重复读:一个事务 先后读取同一条记录,但两次读取的 数据不同,称之为不可重复读。
- PS:不可重复读是解决脏读导致的
- 如下图所示:
3.幻读
- 幻读:一个事务按照条件 查询数据时, 没有对应的数据行,但是在 插入数据时,又发现这行数据 已经存在,好像出现了幻影”。
- PS:幻读是解决不可重复读导致的
- 如下图所示:
五.事务隔离级别
1.事务隔离级别&要点
- 要点:事务隔离级别越高,数据越 安全 ,但是 性能 越低。
- 事务隔离级别,如下所示:
2.查看/修改事务隔离级别语法
- 如下图所示
- 下图:修改隔离级别后查看
--查看事务隔离级别语法 SELECT @@TRANSACTION_ISOLATION; --修改事务隔离级别语法 SET [SESSION|GLOBLE] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
3.用两个Mysql客户端模拟并发事务,并测试各个隔离级别效果
※事务回顾隔离级别
- 事务隔离级别,如下所示:
1.模拟脏读
- 脏读:一个事务 读到 另外一个事务还 没有提交的数据。
2.修改隔离级别——[避免脏读—>不可重复读]
- 不可重复读:一个事务 先后读取同一条记录,但两次读取的 数据不同,称之为不可重复读。
- PS:不可重复读是解决脏读导致的
- 现象: 同样sql在同一语句查询中不一致
3.修改隔离级别——[避免不可重复读—>幻读]
- 幻读:一个事务按照条件 查询数据时, 没有对应的数据行,但是在 插入数据时,又发现这行数据 已经存在,好像出现了幻影”。
- PS:幻读是解决不可重复读导致的
- 注意:我们这次实验不用修改隔离级别,因为是默认的(如果已经修改了同上面改回来即可)
- 现象如图所示:
4.修改隔离级别——[避免幻读—>进入阻塞状态]
- 阻塞状态:在阻塞状态下,进程或线程可能会被挂起,直到条件满足或事件发生后才能被唤醒并继续执行。