当前位置:网站首页>MySQL基础——事务
MySQL基础——事务
2022-06-29 15:50:00 【白巧克力x】
目录
上篇文章学习了MySQL基础——多表查询,这篇文章学习MySQL基础——事务。
事务
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,所以这些操作要么同时成功,要么同时失败。
事务的四大特性:
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败;
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态;
隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行;
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变是永久的。
MySQL的事务默认是自动提交的,当执行一条DML语句,MySQL会隐式的提交事务。
默认自动提交事务可能会导致数据出错,例如,有如下数据表:

接下来我们模拟收付款,同时执行如下代码:
update account set money=money - 1000 where name='买家'; # 买家付款
update account set dasa money=money + 1000 where name='商家'; # 商家收款执行结果如下图所示:

由于第二条MySQL语句是错误的,MySQL自动提交事务错误,导致商家没有收到款。
事务操作
既然自动提交事务可能会导致数据错误,那么我们把自动提交事务改为手动提交事务。
手动提交事务
在修改事务提交方式之前,执行如下代码查看事务的提交方式:
select @@autocommit;如下图所示:

其中1为自动提交事务,0为手动提交事务。
查看事务提交方式后,执行如下代码把事务提交方式改为手动提交:
set @@autocommit=0;如下图所示:

把事务提交方式改为手动提交后,需要执行如下代码提交事务和回滚事务:
commit; #提交事务
rollback; #回滚事务接下来我们还是模拟收付款来演示手动提交事务,同时执行如下代码:
update account set money=money - 1000 where name='买家'; # 买家付款
update account set money=money + 1000 where name='商家'; # 商家收款发现数据没有发生改变,如下图所示:

这是因为还没提交事务,此时我们只需要执行如下代码数据会发生改变:
commit;如下图所示:

接下来我们同时执行如下代码演示事务执行出错的情况:
update account set money=money - 1000 where name='买家';
update account set dasa money=money + 1000 where name='商家';
rollback; # 回滚事务如下图所示:


通过回滚事务把正确和错误的事务修改值恢复到修改前的值。
自动提交事务中手动提交
当我们不想把自动提交事务改为手动提交事务,而防止自动提交事务出错时,可以在自动提交事务中,手动开始事务,代码如下:
start transaction 或 begin;示例代码如下:
set @@autocommit=1; # 把事务提交方式改为自动提交
start transaction; # 开始事务
update account set money=money - 1000 where name='买家'; # 买家付款
update account set money=money + 1000 where name='商家'; # 商家收款如下图所示:


发现数据没有发生改变,这时只需要执行如下代码数据就会发生改变:
commit;并发事务问题
当有两个或两个以上的事务同时执行、提交事务时,可能会引发并发事务问题,并发事务常见的问题有:
脏读:一个事务读取了另一个事务还没提交的数据;
不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,这种称为不可重复读;
幻读:一个事务按照条件查询数据时,没有对应的数据行,但在插入数据时,这行数据已经存在了,好像出现了“幻影”。
事务隔离级别
为了解决事务并发问题,我们设置事务的隔离级别,不同的隔离级别可以解决不同的事务并发问题,如下表:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| Read uncommitted | 不可解决 | 不可解决 | 不可解决 |
| Read committed | 可解决 | 不可解决 | 不可解决 |
| Repeatable Read(默认) | 可解决 | 可解决 | 不可解决 |
| Serializable | 可解决 | 可解决 | 可解决 |
在设置事务的隔离级别之前,我们首先执行如下代码看看事务的隔离级别:
select @@transaction_isolation;设置事务隔离级别语法格式如下:
set [session | global] transaction isolation level {read uncommitted | read committed | repeatable read | serializable}其中session是当前会话窗口有效,global是对当前客户端的所有会话窗口有效。
接下来我们来演示隔离级别解决事务并发问题。
Read uncommitted
首先依次执行如下代码查看和设置隔离级别:
select @@transaction_isolation;
set session transaction isolation level read uncommitted;如下图所示:

接下来通过两个cmd窗口通过start transaction手动开启两个事务,并依次执行如下代码:
# 窗口1
use mytest; # 选择mytest数据库
set session transaction isolation level read uncommitted; # 设置事务级别为read uncommitted
start transaction; # 开始事务
select * from account; # 查看数据
#窗口2
use mytest; # 选择mytest数据库
start transaction; # 开始事务
update account set money=money - 1000 where name='买家'; #更新数据
# 窗口1
select * from account; # 查看数据如下图所示:

在窗口2更新数据事务后,没有提交事务,但在窗口1查看数据发现数据已经更新了,这就属于脏读了。
Read committed
接下来我们通过设置Read committed事务隔离级别解决脏读问题,同样打开两个cmd窗口通过start transaction手动开启两个事务,并依次执行如下代码:
# 窗口1
use mytest; # 选择mytest数据库
set session transaction isolation level read committed; # 设置事务级别为read committed
start transaction; # 开始事务
select * from account; # 查看数据
#窗口2
use mytest; # 选择mytest数据库
start transaction; # 开始事务
update account set money=money - 1000 where name='买家'; #更新数据
# 窗口1
select * from account; # 查看数据
#窗口2
commit;如下图所示:

这样就成功解决了脏读问题。虽然Read committed隔离级别可以解决脏读问题,解决不了不可重复读和幻读。
接下来演示不可重复读,示例代码如下:
# 窗口1
use mytest; # 选择mytest数据库
set session transaction isolation level read committed; # 设置事务级别为read committed
start transaction; # 开始事务
select * from account; # 查看数据
#窗口2
use mytest; # 选择mytest数据库
start transaction; # 开始事务
update account set money=money - 1000 where name='买家'; #更新数据
# 窗口1
select * from account; # 查看数据
#窗口2
commit; # 提交事务
#窗口1
select * from account; # 查看数据如下图所示:

在窗口1中一次事务执行了3次查询数据表操作,前面两次结果相同,第三次查询的结果不同,这就叫不可重复读。
Repeatable Read
为了解决不可重复读,把事务隔离级别改为Repeatable Read,示例代码如下 :
# 窗口1
use mytest; # 选择mytest数据库
set session transaction isolation level repeatable read; # 设置事务级别为repeatable read
start transaction; # 开始事务
select * from account; # 查看数据
#窗口2
use mytest; # 选择mytest数据库
start transaction; # 开始事务
update account set money=money + 1000 where name='买家'; #更新数据
commit;
# 窗口1
select * from account; # 查看数据
# 窗口1
commit; # 提交事务
select * from account; # 查看数据如下图所示:

在窗口1开启一个事务并查询数据表的数据后,在窗口2中开启事务并更新提交事务,再返回窗口1中查询数据表发现查询结果和之前查询一样,这就叫可重复读,在窗口1中提交第一个事务后,再次查询数据表数据发现数据发生了改变。这就解决了并发问题的不可重复读。
Repeatable Read可以解决脏读和不可重复读,但解决不了幻读。
接下来我们演示幻读,示例代码如下:
# 窗口1
use mytest;
start transaction;
select * from account where id='3';
# 窗口2
use mytest;
start transaction;
insert into account(id,name,money) values(3,'中间商',2000);
commit;
# 窗口1
insert into account(id,name,money) values(3,'大中间商',2000);
select * from account where id='3';如下图所示:

在窗口1中开启事务并查询id为3的数据,发现数据表中没有id为3的数据,在窗口2中,开启事务并添加id为3的数据并提交事务后,在窗口1中添加id为3的数据,发现已经有id为3的数据了,但查询id为3的数据时,发现没有查到,这就是幻读。
Serializable
为了解决幻读并发事务问题,我们把事务隔离级别改为Serializable,示例代码如下:
# 窗口1
use mytest; # 选择mytest数据库
set session transaction isolation level Serializable; # 设置事务级别为Serializable
start transaction; # 开始事务
select * from account where id='5'; # 查看数据
# 窗口2
use mytest;
start transaction;
insert into account(id,name,money) values(5,'厂商',2000);如下图所示:

在窗口1查询id为5的数据,因为没有id为5的数据,所以没有查询到,在窗口2中插入id为5的数据,发现一直没有插入成功,这是因为在窗口1中已经开启了一个事务,需要窗口1开启的事务结束后,才能执行窗口2的事务,这样就解决了幻读问题。
好了,MySQL基础——事务就学到这里了,下篇文章学习MySQL进阶——存储引擎。
公众号:Python侦探
边栏推荐
- 加速智能驾驶项目落地?你还缺一套真值测评系统
- A. Print a Pedestal (Codeforces logo?)
- SSL free certificate application, how about the actual effect of free SSL certificate?
- Aleph Farms聘请监管事务主管,提前为全球商业化做好准备
- 京东方:随着下半年旺季到来、促销拉动、新产品发布等影响,需求有望出现好转
- C语言——printf打印进制前缀
- 对于产业互联网的认识,直接关系着我们究竟会以怎样的心态来看待它
- 如何修复运行缓慢的 WordPress 网站?
- 作为开发人员,无代码开发平台 iVX 你有必要了解一下
- Where has lifeifei reached in his key "embodied intelligence"?
猜你喜欢

隐私计算助力数据的安全流通与共享

迪赛智慧数——其他图表(基本旭日图):毕业演讲高频词

Sophon Base 3.1 推出MLOps功能,为企业AI能力运营插上翅膀

Sophon CE社区版上线,免费Get轻量易用、高效智能的数据分析工具

golang操作etcd

Science: the interrelated causes and consequences of sleep in the brain

卫龙辣条第三次冲刺上市:业绩增速下滑,刘卫平、刘福平提前套现

京东方:随着下半年旺季到来、促销拉动、新产品发布等影响,需求有望出现好转

Mysql database Basics: introduction to data types

加速智能驾驶项目落地?你还缺一套真值测评系统
随机推荐
小程序在产业互联网有「大」作为
云原生数据库查询优化-统计信息与行数估计
实践 | 移动端图片上传旋转、压缩的解决方案
为Golang项目编写Makefile
MySQL error: expression 1 of order by claim is not in group by claim and contains nonaggregated column
按键精灵打怪学习-多窗口多线程后台判断人物、宠物血量和宠物快乐度
Blue bridge cup several full array questions
路由汇总带来的三层环路-解决实验
SSL free certificate application, how about the actual effect of free SSL certificate?
CVPR 2022 | greatly reduce the manual annotation required for zero sample learning. Mapuosuo and Beiyou proposed category semantic embedding rich in visual information
Magento 和 WordPress 的区别
telnet+ftp 对设备进行 操控 和 升级
【Proteus仿真】数码管递加/递减带闪烁消隐显示
How to install WordPress on a web site
关于 麒麟系统启动应用报错“undefined symbol: __cxa_throw_bad_array_new_length, version Qt_5“ 的解决方法
关于开展2022年江苏省重点领域 首版次软件产品征集工作的通知
MATLAB给数据加噪声/扰动
C11新特性——auto、decltype类型指示符
Sophon CE社区版上线,免费Get轻量易用、高效智能的数据分析工具
Timecho of Tianmou technology completed Angel round financing of nearly RMB 100 million and built the original time series database of the industrial Internet of things around Apache iotdb