2、关于数据库事务那些事

news2024/12/25 12:01:46

目录

1、什么是事务?

2、介绍下数据库事务?

3、并发事务会带来什么问题?

3.1、不可重复读和幻读有什么区别?

4、数据库隔离级别有哪几种?

5、MySQL默认使用隔离级别是啥?

6、如何控制并发事务?

6.1、锁

6.2、MVCC


1、什么是事务?

事务指的是逻辑上的一组操作,这组操作要么都执行,要么都不执行。最典型的就是转账的例子:

老板每个月给你发工资(500元)转账的操作必然会经历两个操作,一个是从老板账户扣减-500元,另一个是从你的账户增加500元。这个操作必须都成功,或者必须都失败。如果只是一部分成功,那么可能老板的账户扣减了,你的账户却没有增加,或者你的账户增加了,老板的账户却没扣减。这显然都是不允许的,因此事务会把这两个操作看作一个逻辑的整体,这组整体包含的状态必须是一致的。

2、介绍下数据库事务?

数据库事务同样的道理,是将一组数据操作打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。MySQL中可以使用start transaction开启一个事务,然后要么使用commit提交事务将数据持久化,要么使用rollback撤销所有的步骤。事务SQL示例如下:

START TRANSACTION;
update account set money=money-500 where name = '老板';
update account set money=money+500 where name = '我们自己';
COMMIT;

事务仅仅如此还是不够的,还应该遵循4大特性(ACID)。

  1. 原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中一部分操作。
  2. 一致性(Consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。也就是说在执行事务前后,数据都应该保持一致性。比如前面的余额操作,不管哪一步失败了,前后的账户都不应该多出或少掉500,因为最终事务如果没有提交,事务中所做的修改也不会保存到数据库中。
  3. 隔离性(Isolation):这个特性通常适用在并发中。一个事务所作的修改在最终提交前,对其他事务是不可见的。如前面第2条SQL从老板账户扣钱500元的时候,如果事务还没提交,此时另一个线程查询老板的账户,其看到的账户余额是没有减去500的。
  4. 持久性(Durability):指一旦事务提交,则所作的修改就会永久保存到数据库中。就算此时系统崩溃,变更的数据也不会丢失。

事务的ACID特性可以确保数据不会出错,银行不会弄丢你的钱。但是在实际应用逻辑中,要实现这一点却很难,甚至可以说是不可能完成的任务。

这里的ACID,A、I、D都是为了保证最后的C。因此C(一致性)才是最终目的,不然谈A、I、D也就没了目的。《Designing Data-Intensive Application(数据密集型应用系统设计)》一书中提到:原子性,隔离性和持久性是数据库的属性,而一致性(在 ACID 意义上)是应用程序的属性。应用可能依赖数据库的原子性和隔离属性来实现一致性,但这并不仅取决于数据库。因此,字母 C 不属于 ACID 。

3、并发事务会带来什么问题?

如果多事务并发运行,可能会导致脏读,幻读,不可重复读,丢失更新的问题。

  • 脏读(Dirty read):指一个事务读取到了另一个事务修改后还未提交的数据。一般在READ UNCOMMITTED(未提交读)隔离级别中会出现。在此隔离级别中,事务中的修改,即使没有提交,对其他事务也是可见的。

举个例子:

表中有一条数据,ID=1 Salary=1000

事务A:修改ID=1的Salary=Salary-200

事务B:读取ID=1的Salary值,此时读取到的值为800(由于事务A的操作对于事务B可见)

事务A:系统异常,进行回滚,Salary=1000

此时对于事务B读到的就是未被真正持久化的脏数据。因此被称为脏读。

  • 幻读(Phantom read):幻读指的是当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,而之前的事务再次读取该范围内的记录时,会多读取到几行记录,有点像产生了幻觉。

举个例子:

表中有关于部门员工的数据,dept='研发部',原始员工数量=10

事务A:查询部门员工的数据,select * from xx where dept='研发部'

事务B:新增了一名员工,此时员工数量=11

事务A:再一次查询部门员工的数据,select * from xx where dept='研发部'

此时对于事务A来说前后两次读取到的员工数据不一致,第二次读取到了11条数据,多出来的一条像是产生了幻觉。因此被称为幻读。

  • 不可重复读(Unrepeatable read):指在一个事务内,多次读取同一数据时,得到的结果不一致。当一个事务两次读取数据的中间,另一个事务对该数据进行了修改,那么将导致之前的事务前后两次读取到的数据不一致。

举个例子:

表中有一条数据,ID=1 Salary=1000

事务A:读取ID=1的Salary,此时读取到的值为1000

事务B:修改ID=1的Salary=Salary-200

事务A:读取ID=1的Salary值,此时读取到的值为800

此时对于事务A两次读取到的值不一致。

幻读和不可重复读,有点类似,其实可以看成幻读是不可重复读的一种场景。

  • 丢失更新(Lost to modify):指一个事务在读取了一个数据后,另一个事务也读取了该数据。此时两个事务都对这个数据进行了修改,那么其中一个事务的修改就可能被另一个事务的修改所覆盖,导致另一个事务的修改丢失。

举个例子:

表中有一条数据,ID=1 Salary=1000

事务A:读取ID=1的Salary,此时读取到的值为1000

事务B:读取ID=1的Salary,此时读取到的值为1000

事务A:修改ID=1的Salary=Salary-200

事务B:修改ID=1的Salary=Salary-300

假如事务A先修改完,事务B的修改也提交了,那么此时Salary=700,而对事务A来说,Salary=800的修改丢失了。

3.1、不可重复读和幻读有什么区别?

简单来说,不可重复读是针对同一条数据的,而幻读是针对一组数据的。

  • 不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;
  • 幻读的重点在于记录新增比如多次执行同一条查询语句(DQL)时,发现查到的记录增加了。

4、数据库隔离级别有哪几种?

  1. 未提交读(READ UNCOMMITTED):在此隔离级别中,事务中的修改,即使没有提交,其他事务也都是可见的。事务可以读取未提交的数据,此时就会产生脏读。性能上,READ UNCOMMITTED级别不会比其他级别的好太多,但却缺乏其他级别的好处。因此除非是有很必要的理由,不然实际项目中尽量不要使用。
  2. 提交读(READ COMMITTED):该级别是大多数数据库系统默认的级别,但是MySQL却不是。READ COMMITTED是一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读,因为两次执行同样的查询,可能会得到不一样的结果。
  3. 可重复读(REPEATABLE READ):可重复读是 MySQL 的默认事务隔离级别。REPEATABLE READ解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决幻读的问题。
  4. 可串行化(SERIALIZABLE):SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁竞争的问题。实际应用中很少用到这个隔离级别,只有在非常需要确保数据一致性且可以接受没有并发的情况下,才考虑使用他。

隔离级别

脏读

不可重复读

幻读

加锁读

未提交读

×

提交读

×

×

可重复读

×

×

×

可串行化

×

×

×

MySQL的隔离级别是通过MVCC和加锁共同实现的。其中SERIALIZABLE是通过加锁来实现的,而READ-COMMITTED 和 REPEATABLE-READ 隔离级别是基于 MVCC 实现的。REPEATABLE-READ在当前读的情况下,需要加锁来保证不会出现幻读。

5、MySQL默认使用隔离级别是啥?

MySQL默认使用的是可重复读(REPEATABLE READ),可以通过SQL查询:

-- mysql 8.0以前的版本
SELECT @@tx_isolation

-- mysql 8.0之后的版本
SELECT @@transaction_isolation

结果:

6、如何控制并发事务?

MySQL是通过加锁和MVCC两种方式来控制并发事务的。加锁是悲观模式,而MVCC可以看成是乐观 锁模式。而MySQL的大多数事务性存储实现都不是简单的行级锁。基于提升并发性能的考虑,一般同时实现了多版本控制MVCC。

MVCC可以看成是行级锁的变种,但是在很多情况下避免了加锁操作,因此开销相比加锁更低。

6.1、锁

MySQL中锁分为共享锁(S锁)和排他锁(X锁)。其中主要是通过读写锁来实现并发事务控制。

  • 共享锁(S 锁):又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
  • 排他锁(X 锁):又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条记录加任何类型的锁(锁不兼容)。

读写锁可以做到读读并行,但是无法做到写读、写写并行。另外,根据根据锁粒度的不同,又被分为 表级锁(table-level locking) 和 行级锁(row-level locking) 。InnoDB 不光支持表级锁,还支持行级锁,默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。不论是表级锁还是行级锁,都存在共享锁(Share Lock,S 锁)和排他锁(Exclusive Lock,X 锁)这两类。

6.2、MVCC

MySQL中的MVCC则是通过保存数据在某个时间点的快照来实现的。不管SQL执行需要的时间多长,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。当然每个存储引擎实现的MVCC是不一样的,下面以InnoDB引擎来详细展开。

InnoDB的MVCC是通过在每行的记录后面保存两个隐藏的列来实现,其中一个列保存了行的创建时间,一个保存了行的过期时间(或)删除时间。当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,版本号都会自动递增,事务开始时的版本号会作为事务的版本号,用于和查询到的每行记录的版本号进行比较。

正是因为保存了这两个额外的系统版本号,使得大多数的都操作都不用加锁,性能也得到了提高,但是缺点就是每行记录都需要额外的存储空间,以及版本号的维护工作。

注:MVCC只在可重复读和提交读两个隔离级别下工作,其他的隔离级别和MVCC不兼容。因为未提交读总是读取最新的数据行,而不是符合当前事务版本的数据行,而串行化本身就会对所有的操作进行加锁。

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

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

相关文章

TCP 协议特性

1. TCP 基本认识 TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的; 可靠的:无论的网络链…

论文笔记:Time-LLM: Time Series Forecasting by Reprogramming Large Language Models

iclr 2024 reviewer 评分 3888 1 方法 提出了 Time-LLM, 是一个通用的大模型重编程(LLM Reprogramming)框架将 LLM 轻松用于一般时间序列预测,而无需对大语言模型本身做任何训练 为什么需要时序数据和文本数据对齐:时…

【信号处理】基于CNN的心电(ECG)信号分类典型方法实现(tensorflow)

关于 本实验使用1维卷积神经网络实现心电信号的5分类。由于数据类别不均衡,这里使用典型的上采样方法,实现数据类别的均衡化处理。 工具 方法实现 数据加载 Read the CSV file datasets: NORMAL_LABEL0 , ABNORMAL_LABEL1,2,3,4,5 ptbdb_abnormalpd.…

C语言练习——上三角矩阵

前言 今天我们来看看如何使用代码实现上三角矩阵吧。首先我们来了解一下上上三角矩阵是什么,上三角矩阵就是在矩阵从左上到右下的对角线之下的数组元素都为0的数组方矩阵,例如: 以一个三阶矩阵为例,在对角线元素之下,就…

江西智博环境| 邀您参加2024全国水科技大会暨技术装备成果展览会

展位号:A28 企业介绍 江西智博环境技术有限公司始创于2008年初,总部位于江西省域副中心城市-赣州。公司主要从事一体化净水设备、单村供站、泵船、无负压供水设备自动化控制系统、低配电系统、工艺设备及智慧水务的设计研发、生产、销售、安装、调试等业…

基于深度学习的脑部肿瘤检测系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 当大脑中形成异常细胞时,就会发生脑肿瘤。肿瘤主要有两种类型:癌性(恶性)肿瘤和良性肿瘤。恶性肿瘤可分为原发性肿瘤和继发性肿瘤,前者始…

Redis中的慢查询日志(一)

慢查询日志 概述 Redis的慢查询日志功能用于记录执行时间超过给定时长的命令请求,用户可以通过这个功能产生的日志来 监视和优化查询速度。服务器配置有两个和慢查询日志相关的选项: 1.slowlog-log-slower-than选项指定执行时间超过多少微妙(1秒1000 000微妙)的命…

The C programming language (second edition,KR) exercise(CHAPTER 4)

E x c e r c i s e 4 − 1 Excercise\quad 4-1 Excercise4−1&#xff1a; #include <stdlib.h> #include <stdio.h> #include <string.h> int strindex(char s[],char t[]); int strrindex(char s[],char t[]);int main(void) {char s[100]"qwoulddf…

【Linux驱动层】iTOP-RK3568学习之路(四):杂项设备驱动框架

一、杂项设备驱动简介 在 Linux 中&#xff0c;把无法归类的五花八门的设备定义成杂项设备。相较于字符设备&#xff0c;杂项设备有以下两个优点: (1)节省主设备号:杂项设备的主设备号固定为 10&#xff0c;而字符设备不管是动态分配还是静态分配设备号&#xff0c;都会消耗一…

AlDente Pro for mac最新激活版:电池长续航软件

AlDente Pro是一款专为Mac用户设计的电池管理工具&#xff0c;旨在提供电池安全和健康管理的一站式解决方案。它具备实时监控电池状态的功能&#xff0c;让用户随时了解电池的电量、充电次数、健康状态等信息。 AlDente Pro for mac最新激活版下载 同时&#xff0c;AlDente Pro…

【蓝桥杯2025备赛】集合求和

集合求和 题目描述 给定一个集合 s s s&#xff08;集合元素数量 ≤ 30 \le 30 ≤30&#xff09;&#xff0c;求出此集合所有子集元素之和。 输入格式 集合中的元素&#xff08;元素 ≤ 1000 \le 1000 ≤1000&#xff09; 输出格式 s s s 所有子集元素之和。 样例 #1 …

Docker搭建项目管理软件禅道

文章目录 一、简介二、部署三、使用 一、简介 禅道是以项目管理为核心的协作平台&#xff0c;旨在帮助团队高效地进行项目管理和协作。 禅道提供了项目管理、任务管理、团队协作、文档管理、报告统计等功能。 禅道官网 二、部署 操作系统&#xff1a;22.04.4 创建文件夹 …

ARM与单片机有啥区别?

初学者必知&#xff1a;ARM与单片机到底有啥区别&#xff1f;1、软件方面这应该是最大的区别了。引入了操作系统。为什么引入操作系统&#xff1f;有什么好处嘛&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「ARM的资料从专业入门到高级教…

【OpenHarmony-NDK技术】简单将cJson移植到OpenHarmony中,并在c层修改参数值再返回json

1、cJson的简单介绍 cJson - github网址 概述 一般使用cJson是&#xff0c;需要将json文本转化为json对象–编码&#xff0c;将json对象转化为json文本–解析。 git clone https://github.com/DaveGamble/cJSON.git 后留意cJSON.h和cJSON.h两个文件。 1、cJson的介绍 cJso…

使用FPGA实现比较器

介绍 比较器就是通过比较输入的大小&#xff0c;然后输出给出判断。 在这个比较器中&#xff0c;有两个输入&#xff0c;三个输出。根据输出就可以判断出哪个输入值大了。 设计文件 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity compa…

JAVA----Thread

Thread 这里写目录标题 Thread线程Thread 第 1 种写法此外, t.start()的作用 Thread 第 2 种写法Thread 第 3 种写法Thread 第 4 种写法Thread 第 5 种写法 线程 本身是操作系统提供的, 操作系统提供了 API 以让我们操作线程, JVM 就对操作系统 API 进行了封装. 线程这里, 则提…

verilog变量类型wire、reg和Memory的介绍和用法

目录 wire型 reg型 Memory型 wire型 wire 类型变量&#xff0c;也叫网络类型变量&#xff0c;用于结构实体之间的物理连接&#xff0c;如门与门之间&#xff0c;不能储存值&#xff0c;用连续赋值语句 assign 赋值&#xff0c;定义为 wire [n-1:0] a ; 其中 n 代表位宽&…

OCT2Former: A retinal OCT-angiography vessel segmentationtransformer论文总结

论文(COMPUT METH PROG BIO)&#xff1a;OCT2Former: A retinal OCT-angiography vessel segmentation transformer 源码&#xff1a;https://github.com/coreeey/OCT2Former 一、摘要 背景与目的&#xff1a;视网膜血管分割在视网膜疾病自动筛查与诊断中起着重要作用。如何分…

面试高频:HTTPS 通信流程

更多大厂面试内容可见 -> http://11come.cn 面试高频&#xff1a;HTTPS 通信流程 HTTPS 的加密流程 接下来说一下 HTTPS 协议是如何进行通信的&#xff1a; HTTPS 通信使用的 对称加密 非对称加密 两者结合的算法 HTTPS 通信时&#xff0c;会先使用 非对称加密 让通信双…

大sql mysql执行

先把sql 拆分 太大的执行失败 使用 SQLDumpSplitter3 拆分sql 执行拆分的sql 拆分的sql 打开发现很多 ; 开头的空行 替换掉 正则 ^; 修改数据库 my.cnf my,ini 执行可能会提示 [ERR] 2006 - Server has gone away 错误 在 [mysqld] 添加以下几行 wait_timeout2880000 inter…