MySQL深入理解事务(详解)

事务概述

事务是数据库区别于文件系统的重要特性之一,当我们有了事务就会让数据库始终保持一致性,同时我们还能通过事务机制恢复到某个时间点,这样可以保证已提交到数据库的修改不会因为系统崩溃而丢失。

1、基本概念

事务:一组逻辑操作单元,是数据库从一种状态变换到另一种状态。

事务处理的机制:保证所有的事务都作为一个工作单元来执行,即使出项了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都提交commit,那么这些修改就永久的保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚rollback到最初状态

#案例:AA用户给BB用户转账100
update account set money = money - 100 where name = 'AA';
update account set money = money + 100 where name = 'BB';

2、事务的ACID特性

  • 原子性(atomicity)

原子性是指事务是一个不可分割的工作单元,要么全部提交,要么全部失败回滚。既要么转账成功,要么转账失败,是不存在中间的状态。如果无法保证原子性会怎么样?就会出项数据不一致的情形,A账户减去100元,而B账户增加100元操作失败,系统将无故丢失100元。

  • 一致性(consistency)

一致性是指事务执行前后,数据从一个合法性状态变换到另外一个合法性状态。这种状态是语义上的而不是语法上的,跟具体的业务有关。

那什么是合法的数据状态呢?满足预定的约束的状态就叫做合法的状态。通俗一点,这状态是由你自己来定义的(比如满足现实世界中的约束)。满足这个状态,数据就是一致性的,不满足这个状态,数据就是不一致的!如果事务中的某个操作失败了,系统就会自动撤销当前正在执行的事务,返回到事务操作之前的状态。

举例1:A账户有200元,转账300元出去,此时A账户余额为-100元。你自然就发现了此时数据是不一致的,为什么呢?因为你定义了一个状态,余额这列必须>=0。

举例2:A账户有200元,转账50元给B账户,A账户的钱扣了,但是B账户因为各种意外,余额并没有增加。你也知道此时数据是不一致的,为什么呢?因为你定义了一个状态,要求A+B的总余额 必须不变。

  • 隔离性(isolation)

事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

如果无法保证隔离性会怎么样?假设A账户有200元,B账户0元,A账户往B账户转账两次,每次金额为50元,分别在两个事务中执行。如果无法保证隔离性,会出项下面的情形:

UPDATE accounts SET money = money - 50 where NAME = 'AA';UPDATE accounts SET money = money + 50 where NAME = 'BB';
事务1事务2
从磁盘上将A账户余额读取到变量A中 A为200
执行操作A=A-50
将A的值写回磁盘 A为150
从磁盘中将B账户余额读取到变量B中 B为0
执行操作B=B+50
从磁盘上将A账户余额读取到变量A中 A为150
执行操作A=A-50
将A的值写回磁盘 A为100
从磁盘中将B账户余额读取到变量B中 B为0
执行操作B=B+50
将B值写回磁盘 B为50
将B值写回磁盘 B为50
  • 持久性(durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作的数据库故障不应该对其他有任何影响。

持久性是通过事务日志来保证的。日志包括了重做日志回滚日志。当我们通过事务对数据进行修改的时候,首先会将数据库的变化信息记录到重做日志中,然后再对数据库中对应的行进行修改。这样中的好处是,即使数据库系统崩溃,数据库重启后也能找到没有更新到数据库系统中的重做日志,重新执行,从而使事务具有持久性。

总结:ACID是事务的四大特性,在这四个特性中,原子性是基础,隔离性是手段,一致性是约束条件,而持久性是我们的目的。数据库事务,其实就是数据库设计者为了方便起见,把需要保证的原子性,隔离性,一致性和持久性的一个或多个数据库操作称为一个事务。

3、数据并发问题

针对事务的隔离性和并发性,我们怎么做取舍呢?先看一下访问相同数据的事务在不保证串行执行(也就是执行完一个再执行另一个)的情况下可能会出现哪些问题:

1、脏写(Dirty Write)

对于两个事务SessionA、SessionB,如果事务SessionA修改了另一个未提交事务SessonB修改过的数据,那就意味着发生了脏写,如图所示:

发生时间编号SessionASessionB
1Begin;
2Begin;
3UPDATE student SET name = ‘李四’ WHERE studentno = 1;
4UPDATE student SET name=‘张三’ WHERE studentno = 1;
5COMMIT;
6ROLLBACK;

SessionA和SessionB各开启了一个事务,SessionB中的事务先将studentso列为1的记录的name更新为‘李四’,然后SessionA中的事务接着又把这条studentno列为1的记录的name列更新为‘张三’。如果之后SessionB中的事务进行了回滚,那么SessionA中更新也将不复存在,这种现象就称之为脏写。这时SessionA中的事务就没有效果了,明明把数据更新了,最后也提交事务了,最后看到的数据没有变化。这里大家对事务的隔离级别比较了解的话,会发现默认隔离级别下,上面SessionA中的更新语句会处于等待状态,这里只是跟大家说明一下会出现这样现象。

2、脏读(Dirty Read)

对于两个事务SessionA、SessionB,Session A 读取了已经被Session B更新但还没有被提交的字段。之后若Session B回滚,Session A 读取的内容就是临时且无效的。如图所示:

发生时间编号SessionASessionB
1Begin;
2Begin;
3UPDATE student SET name = ‘张三’ WHERE studentno = 1;
4SELECT * FROM student WHERE studentno = 1;(如果读取到列name的值为’张三’,则意味着发生了脏读)
5COMMIT;
6ROLLBACK;

SessionA和SeesionB各开启了一个事务,SessionB中的事务先将studentno列为1的记录的name列更新为‘张三’,然后SessionA中的事务再去查询这条studentno为1的记录,如果读取到列name的值为’张三‘,而Session B中的事务稍后进行了回滚,那么SessionA中的事务相当于读取到了一个不存在的数据,这种现象就称之为脏读

3、不可重复读(Non-Repeatable Read)

对于两个事务SessionA、SessionB,Session A读取了一个字段,然后SessionB更新了该字段,之后Session A再次读取同一个字段,值就不同了,那就意味着发生了不可重复读。

发生时间编号SessionASessionB
1Begin;
2SELECT * FROM student WHERE studentno = 1;(此时读到的列name的值为’王五‘)
3UPDATE student SET name= ‘张三’ WHERE studentno = 1;
4SELECT * FROM student WHERE studentno = 1;(如果读到列name的值为’张三‘,则意味着发生了不可重复读)
5UPDATE student SET name = ‘李四’ WHERE studentno = 1;
6SELECT * FROM student WHERE studentno = 1;(如果读到列name的值为’李四‘,则意味着发生了不可重复读)

我们在Session B中提交几个隐式事务(注意是隐式事务,意味着语句结束事务就提交了),这些事务都修改了studentno列为1的记录的列name的值,每次事务提交之后,如果Session A中的事务都可以查看到最新的值,这种现象就称之为不可重复读

4、幻读(Phantom)

对于两个事务Session A、Session B,SessionA从一个表中读取了一个字段,然后SessionB在该表中插入 了一些新的行。之后,如果Session A再次读取同一个表,就会出多几行。那就意味着发生了幻读

发生时间编号SessionASessionB
1Begin;
2SELECT * FROM student WHERE studentno>0;(此时读取到的列name的值为’张三‘)
3INSERT INTO student VALUES (2,‘赵六’,‘2班’);
4SELECT * FROM student WHERE studentno>0;(如果读取到了列name的值为’张三‘、’赵六‘的记录,则意味着发生了幻读)

SessionA中的事务先根据条件studentno >0这个条件查询表student,得到了name的值为’张三‘的记录;之后SessionB中提交了一个隐式事务,该事务向表student中插入了一条新的记录;之后SessionA中的事务再根据相同的条件studentno > 0 查询表student,得到的结果集中包含Session B中的事务新插入的那条记录,这种现象也被称之为幻读。我们把新插入的那些记录称之为幻影记录

注意1:

有的同学会产生疑问,那如果SessionB中删除了一些符合studentno > 0的记录而不是插入新记录,那Session A之后再根据studentno > 0的条件读取的记录变少了,这种现象算不算幻读呢?这种现象不属于幻读,幻读强调的是一个事务按照某个相同条件多次读取记录时,后读取时读到了之前没有读到的记录

注意2:

那对于先前已经读到的记录,之后又读取不到这种情况,算啥呢?这相当于对每一条记录都发生了不可重复读的现象。幻读只是重点强调了读取到了之前读取没有获取到的记录。

4、SQL中的四种隔离级别

上面介绍了几种并发事务执行过程中可能遇到的一些问题,这些问题有轻重缓急之分,我们给这些问题按照严重性来排一下序:

脏写 > 脏读 > 不可重复读 > 幻读

我们愿意舍去一部分隔离性来换取一部分性能在这里就体现在:设立一些隔离级别,隔离级别越低,并发问题发生的就越多。SQL标准中设立了4个隔离级别:

  • READ UNCOMMITTED:读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。不能避免脏读,不可重复读,幻读。
  • READ COMMITTED:读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读,幻读问题仍然存在。
  • REPEATABLE READ:可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读,不可重复读,但幻读问题仍然存在。这是MySQL的默认隔离级别。
  • SERIALIZABLE:可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入,更新和删除操作。所有的并发问题都可以避免,但性能十分底下。能避免脏读、不可重复读和幻读。

SQL标准中规定,针对不同的隔离级别,并发事务可以发生不同严重程度的问题,具体情况如下:

隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
READ UNCOMMITTEDYesYesYesNo
READ COMMITTEDNoYesYesNo
REPEATABLE READNoNoYesNo
SERIALIZABLENoNoNoYes

Yes:表示会出现的可能性,No:表示不会出现的可能性。

脏写没有涉及到?因为脏写这个问题太严重了,不论是哪种隔离级别,都不允许脏写的情况发生。

不同的隔离级别有不同的现象,并有不同的锁和并发机制,隔离级别越高,数据库的并发性能就越差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/12084.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何让机器理解人类语言?Embedding技术详解

如何让机器理解人类语言?Embedding技术详解 文章目录 如何让机器理解人类语言?Embedding技术详解介绍什么是词嵌入?什么是句子嵌入?句子嵌入模型实现句子嵌入的方法值得尝试的句子嵌入模型 句子嵌入库实践Step 1Step 2Step 3 Doc2…

GBJ3510-ASEMI室内空调机GBJ3510

编辑:ll GBJ3510-ASEMI室内空调机GBJ3510 型号:GBJ3510 品牌:ASEMI 封装:GBJ-4 最大重复峰值反向电压:1000V 最大正向平均整流电流(Vdss):35A 功率(Pd):中小功率 芯片个数:4…

股东那些事儿:解锁企业背后的权力玩家与盈利秘籍

Hello,大家好啊,今天咱们要聊的主角,是每个企业背后不可或缺的隐形巨擘——股东。他们是谁?他们怎样从公司的经营中分一杯羹?又如何在商业棋盘上运筹帷幄?搬好小板凳,咱们这就开启股东世界的探秘…

Node.js 学习笔记 express框架

express express 使用express下载express 初体验 express 路由什么是路由1路由的使用验证的方法 2获取请求报文参数3获取路由参数4响应设置响应报文 express 中间件5中间件全局中间件路由中间件 6静态资源中间件注意事项案例 7请求体数据8防盗链实现防盗链 9路由模块化router E…

【python】文件操作(持续更新)

1.替换文件名后缀 from pathlib import Pathpdf_path "example.pdf" docx_path Path(pdf_path).with_suffix(.docx) print(docx_path) # 输出: example.docx

亚信安慧AntDB:软硬兼施,创造更多可能

亚信安慧AntDB是一款备受推崇的数据库系统,其极具适配能力使其在软硬件融合方面具备出色表现。无论是与国产硬件还是软件系统配合,AntDB都能实现高效稳定的运行状态,为用户提供优质的数据库服务。从上游到下游的领域,AntDB都展现出…

流量分析利器arkime的学习之路(四)---注意点

用了几天之后会出现系统问题,有些服务器启动不了了,一看原来硬盘满了 [rootc79 ~]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G…

Java——类和对象第二节——封装

1.什么是封装 封装是面向对象程序的三大特性之一,面向对象程序的三大特性分别是封装,继承,多态 而封装简单来说就是套壳隐藏细节 打个比方: 在一些电脑厂商生产电脑时,仅对用户提供开关机键,键盘输入&a…

Ubuntu20.04中的Pyqt4

如何在ubuntu20.04中安装Pyqt4 我已经尝试了所有的命令: sudo apt-get install python-qt4 sudo apt-get install libqt4-dev sudo apt-get install pyqt4-dev-tools sudo apt-get install pyqt4.qsci-dev sudo apt install python3-pyqt4 尽管pyqt5运行得很流畅…

瑞友科技质量改进服务事业部总经理张力受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 北京瑞友科技股份有限公司质量改进服务事业部总经理张力先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“PMO如何对接战略成为企业IT投资成功的有效保障”。大会将于6月29-30日在北京举办,敬请关注&#x…

一个不知名的开源项目可以带来多少收入

起源 2020 年新冠疫情开始蔓延,当时我在同时经营 3 个不同的公司。除了其中的体育赛事平台因为疫情关门大吉之外,另外两个公司并没有受影响,营收和利润反而都持续增加。但是连续几个月不能出远门,也不能随便见朋友和客户&#xff…

软件测试到了35岁,真的就干不动了吗?

摘要:随着年龄的增长,很多人担心软件测试岗位是否存在技术瓶颈。本文将从零到一,详细且规范地探讨软件测试岗位在35岁后的发展前景,并提供一些建议以应对可能的挑战。 引言:软件测试作为软件开发生命周期中至关重要的…

基于PySpark进行去哪儿网数据分析

基于PySpark进行去哪儿网数据分析 本文介绍了如何使用PySpark对去哪儿网的数据进行分析,从而洞察用户偏好、热门目的地以及销售趋势。 1.数据加载 我们需要确保已经准备好了PySpark的开发环境,并且准备好了去哪儿网的数据集。可以通过创建SparkSessio…

SpringCloudAlibaba:5.1Sentinel的基本使用

概述 简介 Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。 官网 https://sentinelguard.io/zh-cn/ Sentinel的历史 2012 年,Sentinel 诞生,主要功能为入口流量控制。 2013-2017 年…

三维奇境:Processing中的3D建模与动画探索

前言: 🌌 欢迎踏入该系列的第五篇章。在前几期的旅程中,我们共同绘制了静态的画卷,编织了动态的影像,甚至让数据跳起了舞。今天,我们将跨越二维的界限,进入一个更加神秘和广阔的领域——三维世界。Processing不仅是一个二维绘图工具,它同样能够让我们在三维空间中自由…

中北机械有限公司将参加2024长三角快递物流供应链与技术装备展览会

参展企业介绍 浙江中北机械有限公司总部位于浙江杭州,生产基地位于浙江桐乡。是一家有着十几年金属制品及仓储物流设施设备生产经验,专业设计、生产、制造各类物流钢制托盘,物流手推车,仓储货架及门店展架,宣传展架等物…

第十一周学习笔记DAY.1-MySQL

一、下载、安装MySQL数据库 二、启动/停止MySQL服务 方式一: 右击“计算机”-->“管理”-->“服务和应用程序”-->“服务”-->“MySQL”-->选择相应的服务操作 方式二: 启动服务: Windo…

Pytorch读取自己的数据集

数据集 流程图 导包设置tfs创建datasets.ImageFolder创建torch.utils.data.DataLoader() import time import os from tqdm import tqdm import pandas as pd import numpy as np import torch import torchvision import torch.nn as nn import torch.nn.functional as F im…

7天精通Web APIs——正则阶段案例(理论+实战)(第六天)

正则表达式的定义和使用 定义:是一种匹配模式,用于匹配字符串中字符组合 作用:表单验证(匹配)、过滤敏感词(替换)、字符串中提取我们想要的部分(提取) 使用分为两步&…