MySQL 事务(详细版)

目录

一、事务简介

1、事务的概念

2、事务执行的案例

3、对于事务的理解

二、事务操作

(一)未控制事务

(二)控制事务一

(三)控制事务二

三、事务四大特性

四、并发事务问题

五、事务隔离级别

1、事务隔离级别的介绍

2、操作事务隔离级别的语法

3、实例分析(串行化)


一、事务简介

1、事务的概念

事务****是一组操作的集合它是一个不可分割的工作单位。

当我们进行事务操作时,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

2、事务执行的案例

就比如:张三给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加 1000。 这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。

**正常情况:**转账这个操作,需要分为以下这么三步来完成,三步完成之后,张三减少1000,而李四增加1000,转账成功。

**异常情况:**转账这个操作,也是分为以下这么三步来完成,在执行第三步是报错了,这样就导致张三减少1000块钱,而李四的金额没变,这样就造成了数据的不一致,就出现问题了。

为了解决上述的问题,就需要通过数据的事务来完成。

我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。如果**执行过程中报错,则回滚事务,**把数据恢复到事务开始之前的状态。

3、对于事务的理解

**默认情况下,每一条SQL语句都是一个事务。**这条SQL语句一旦执行完成,事务就会自动提交,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务。

事务一旦提交,表格就会有对应的变化。

如果有一件事,例如上面的转账操作,必须三个步骤同时完成才可以,**此时就需要将几条SQL语句作为一个事务,**保证它们同时成功或同时失败不影响原来的数据。

所以此时**我们就要对事务进行控制,**将几条SQL语句组合为一个事务。如果成功,就统一提交,如果失败,则避免影响数据库的内容。

二、事务操作

数据准备:

sql 复制代码
drop table if exists account;

create table account(
    id int primary key AUTO_INCREMENT comment 'ID',
    name varchar(10) comment '姓名',
    money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
(一)未控制事务

1、测试正常情况

sql 复制代码
-- 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 = '李四';

测试完毕之后检查数据的状态,可以看到数据操作前后是一致的。(总余额)

2、测试异常情况

sql 复制代码
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- SQL语句中写中文必然报错
-- 但是在dataship中这条语句会被跳过,实际执行时,不会报错
出错了....
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

我们把数据都恢复到2000, 然后再次一次性执行上述的SQL语句(出错了.... 这句话不符合SQL语法,执行就会报错),检查最终的数据情况,发现数据在操作前后不一致了(总余额)

(二)控制事务一

1、查看/设置事务提交方式

-- 查看事务的提交方式

select @@autocommit ;
-- 如果赋值为1,就是自动提交事务;

-- 如果赋值为0,就是手动提交事务;

-- MySQL中默认自动提交事务,所以要设置为手动。

set @@autocommit = 0 ;

2、提交事务

-- 手动提交的情况下,要执行了commit,事务才会提交,数据库中内容才会发生改变。

commit ;

3、回滚事务

-- 执行过程中,如果发生了异常,就去执行rollback回滚,撤回该事务内已执行的操作。

rollback ;

注意事项:

上述的这种方式,我们是修改了事务的自动提交行为,把默认的自动提交修改为了手动提
,此时我们执行的DML语句都不会提交,需要手动的执行commit进行提交

如果业务操作正常完成,事务需要提交,就执行commit指令;如果执行事务操作的过程中出现了异常,那就执行rollback指令回滚事务,保证数据库中数据的正确性与完整性

(三)控制事务二

1、开启事务

-- 手动开启事务,而不是修改事务的提交方式

start transaction ; 或****begin ;

2、提交事务

-- 如果事务执行成功,执行commit指令

commit ;

3、回滚事务

-- 如果事务执行失败,执行rollbakc指令

rollback ;

sql 复制代码
-- 开启事务
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;

三、事务四大特性

1、原子性(Atomicity)

事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

2、一致性(Consistency)

事务完成时,必须使所有的数据都保持一致状态。

3、隔离性(Isolation)

数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行

就如下图的上半部分,事务AB并发执行,但是不会相互影响。事务A在操作的时候,不会影响并发的事务B的执行;事务B在操作的时候,也不会影响并发的事务A的执行;它们两个是在独立的环境下运行的。

4、持久性(Durability)

事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

就如下图的下半部分,因为数据库当中的数据最后是存储在了磁盘当中的,而存储在磁盘当中的数据,就可以永久地保留下来。

四、并发事务问题

并发事务问题是事务A和事务B在同时操作某一个数据库甚至一张表时,引发的问题。

1、赃读:一个事务读到另外一个事务还没有提交的数据

比如,在事务A执行了 select 与 update 语句后,并未提交;但是在事务B中执行 select 语句后,却查询到了事务A未提交的数据。

**2、不可重复读:**一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读

比如,在事务A两次读取同一条记录,却因为期间事务B中 id=1 的数据被更新且提交导致读取到的数据却是不一样的。

**3、幻读:**一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 "幻影"。

比如,在事务A中第一次查询,没有查询到信息 ;然后事务B中插入并提交了id =1的数据;此时在事务A中插入 id = 1 的数据无法插入,因为 id 是主键,id =1的数据在事务B中就已经插入;但是在事务A中再查询一次后,又无法查询得到。

五、事务隔离级别

1、事务隔离级别的介绍

为了解决并发事务所引发的问题 ,在数据库中引入了事务隔离级别。主要有以下几种:

Repeatable Read是MySQL的默认事务隔离级别

事务隔离级别越高,数据越安全,但是性能越低;反之事务隔离级别越低,性能越高,但是数据越不安全。所以我们要权衡数据的安全性以及数据库的并发性能。

其中,串行化指的是再进行并发事务操作的时候,一次只允许操作一个事务

事务A在操作的时候,只有当事务A提交完成之后,事务B才能来操作。

就比如上面幻读的例子中,如果是在串行化的情况下,因为事务A是在事务B之前执行,所以事务A执行完成之前,事务B根本无法执行下去。

事务B执行insert语句在执行后,光标会一直卡着,**直到事务A执行完毕后,事务B才会执行,**这样就可以避免幻读。

2、操作事务隔离级别的语法

(1)查看事务隔离级别

select @@transaction_isolation

(2)设置事务隔离级别

-- session与global二选一

-- session 是指当前设置的事务隔离级别 仅对当前对话窗口有效

-- global 是指当前设置的事务隔离级别 对所有对话窗口有效

-- 后面的四个事务隔离级别四选一即可

set { session | global } transaction isolation level { Read Uncommitted | Read committed | Repeatable Read | Serializable}

3、实例分析(串行化)

通过cmd打开两个命令行,在里面执行SQL语句,模拟两个并发事务。在下图中上面的命令行为事务A,下面的命令行为事务B。

(1)事务A还没有提交之前

事务隔离级别为Serializable (串行化) 时,一次只允许操作一个事务,所以即便事务B的insert语句被执行了,光标也会一直卡着,无法执行,直到事务A执行完毕。

(2)事务A提交之后

事务A提交后,事务B即可执行,但是此时 id = 3 的数据已经存在, 所以会报错

以上即为MySQL 事务 的全部内容,创作不易,麻烦三连支持一下呗~

相关推荐
TiDB 社区干货传送门4 分钟前
从开发者角度看数据库架构进化史:JDBC - 中间件 - TiDB
数据库·oracle·中间件·tidb·数据库架构
虾球xz8 分钟前
游戏引擎学习第280天:精简化的流式实体sim
数据库·c++·学习·游戏引擎
uwvwko1 小时前
BUUCTF——web刷题第一页题解
android·前端·数据库·php·web·ctf
扶尔魔ocy1 小时前
【Linux C/C++开发】轻量级关系型数据库SQLite开发(包含性能测试代码)
linux·数据库·c++·sqlite
旋风菠萝1 小时前
项目复习(1)
java·数据库·八股·八股文·复习·项目、
w23617346011 小时前
Django框架漏洞深度剖析:从漏洞原理到企业级防御实战指南——为什么你的Django项目总被黑客盯上?
数据库·django·sqlite
2302_809798322 小时前
【JavaWeb】MySQL
数据库·mysql
drowingcoder2 小时前
MySQL相关
数据库
Musennn3 小时前
MySQL刷题相关简单语法集合
数据库·mysql
Think Spatial 空间思维4 小时前
【HTTPS基础概念与原理】TLS握手过程详解
数据库·网络协议·https