对数据库事务理解以及脏读、不可重复读以及幻读问题

news/2024/9/22 22:19:15/

引言

事务就是能够把多个SQL给打包在一起,变成一个整体。因为有些操作是需要作为一个整体来完成的,比如转账操作,A给B转账100,那么A的账户余额就会减100,B的账户余额就会加100。如果在A转账的过程中,因为某些原因只执行到一半,那么A的账户减100,B的账户却没有加100,显然这种是不正确的状态。事务就是要保证避免出现这种不科学的状态,把整个转账操作打包成一个整体,要么全部执行,要么一个都不执行。关于事务把操作打包成一个整体,就叫做“原子性”,这也是事务最核心的特性。

关于在执行过程中出错,就一条都不执行,这里并不代表一条都没有执行,而是出错之后,自动恢复到执行之前的样子,在外界看来就是一条都没执行的样子。这里面涉及到了一个关键操作,“回滚”。回滚就是把执行过的操作逆向恢复回去,类似于ctrl+Z。数据库会把执行的每个操作都记录下来,如果某个操作出错,就会把事务中前面的操作进行回滚。根据之前进行的操作,进行逆向操作,前面是插入,回滚就删除,前面是删除,回滚就插入,前面是修改,回滚就改回去。关于保存操作记录是有很大开销的,一般地就把正在执行的事务的操作给记录下来。

事务的使用

1.开启事务:start transaction;

2.执行多条SQL语句

3.回滚或提交:rollback/commit; (开启事务之后,中间的这些sql不会立即就执行,而是先等commit再统一执行,保证原子性,rollback主动进行回滚)

rollback即是全部失败,commit即是全部成功。

示例:

start transaction;

-- A账户减少100

update accout set money=money-100 where name = 'A';

-- B账户增加100

update accout set money=money+100 where name = 'B';

commit;

数据库的事务主要有四大特征:

1.原子性:这是事务的初心,⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执⾏过程中发⽣错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执⾏过⼀样。

2.一致性:事务执行前执行后都必须是数据合法的状态。一致性是事务要解决的问题,也是要依赖原子性来实现的,在事务开始之前和事务结束以后,数据库的完整性没有被破坏

3.持久性:事务产生的修改,都是会写入硬盘的,即使程序重启或主机重启或掉电,事务都是可以正常工作的,保证修改是有效的。

4.隔离性:一个数据库服务器同时执行多个事务的时候,事务之间的相互影响程度。数据库允许多个并发事务同时对其数据进⾏读写和修改的能⼒,隔离性可以防⽌多个事务

并发执⾏时由于交叉执⾏⽽导致数据的不⼀致。事务隔离分为不同级别,包括读未提交(

Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串⾏化

(Serializable)。

谈谈脏读、不可重复读以及幻读问题

关于MySQL提供的四个隔离级别:

mysql服务器要同时给多个客户端提供服务,此时多个客户端之间,可能会同时发起事务,尤其是这多个事务在操作同一个数据库的同一个表的时候,就很有可能引起一些麻烦。如果隔离性越高,就意味着事务之间的并发程度越低,执行效率是越慢,但是数据的准确性是越高的。如果隔离性越低,就意味着事务之间的并发程度越高,执行效率是越快,但是数据的准确性是越低的。

MySQL提供的四个隔离级别,根据实际需求选择不同的隔离级别。

1.如果事务B正在写数据,然而事务A也在读取数据,因为针对的是同一份数据,那么这种情况就属于“脏读”问题,在这个场景下,事务间是完全并发的,没有任何限制,这个级别就是read uncommitted。为了解决“脏读”问题,就是降低并发性,提高隔离性,也就是给“写操作”加锁。比如事务B在写数据的时候,事务A是不能读取的。

2.为了解决“脏读”问题,给“写操作”加锁了,所以A只能在B写入完成之后才能读取,这个级别就是read committed。但是又引入了新的问题,当A正在读取数据的时候,这个时候B又开始写入数据了,导致A读取数据一半的时候后面的数据就变了。在一个事务中,连续两次读取的数据的结果不一致,这就是“不可重复读”问题。为了解决“不可重复读”问题,那么给“读操作”也加锁了,在A读取数据的时候,是不能写入数据的。这两个事务之间的并发程度被进一步降低了,隔离性进一步的提高了,运行速度进一步降低了,但是数据准确性进一步提高了。

3.为了解决“不可重复读”问题,给“写操作”和“读操作”都加锁了,这个级别就是repeatable read,针对同一个代码文件来说,事务B在写入数据的时候,事务A不能进行读取,同样,事务A在进行读取数据的时候,事务B也是不能进行写入数据的。但是随着又引入了新的问题,既然B在写入数据的时候,A不能进行读取,同样A在读取数据的时候,B不能写入数据,但是他们都不是一直傻等着的,他们各自也会去做其他的事情,比如新增或删除其他文件。此时,虽然读取的代码内容没有变,但是会发现文件的数量有变化,例如这种情况,在同一个事务中,两次读到的结果集不相同,这就是“幻读”问题。为了解决“幻读”问题,就只有实现串行化,完全舍弃并发,比如B在写入数据的时候,A什么都不干,就干等着,这个级别就是serializable。

总结:MySQL提供的四个隔离级别

1.read uncommitted(读未提交):不做任何限制,事务之间都是随意并发执行的,并发程度最高,隔离性最低,会产生脏读+不可重复读+幻读。

2.read committed(读已提交):对写操作加锁了,并发程度降低了,隔离性提高了。解决了脏读问题,仍然存在不可重复读+幻读。

3.repeatable read(可重复读):对写和读都加锁了,并发程度又降低了,隔离性又提高了.解决了脏读+不可重复读,可能存在幻读问题。

4.serializable(串行化):严格串行化,并发程度最低(串行执行的)隔离性最高。解决了脏读+不可重复读+幻读问题,执行速度最慢的。

MySQL的隔离级别是通过MySQL的配置文件来进行调整的,在开发中,根据实际问题的需求场景来决定选用哪一个级别。其中MySQL的默认级别是repeatable read。


http://www.ppmy.cn/news/4556.html

相关文章

Dijkstra迪杰斯特拉算法

1.场景 用于计算一个节点到其他节点的最短路径,特点是由其实点位中心向外层扩展(BFS思想),直至扩展到终点为止 2.认识 https://blog.csdn.net/weixin_57128596/article/details/126982769?ops_request_misc%257B%2522request%…

RK3588平台开发系列讲解(GPIO篇)配置GPIO需要了解的概念

平台内核版本安卓版本RK3588Linux 5.10Android12🚀返回专栏总目录 文章目录 一、 GPIO(通⽤输⼊输出)二、IOMUX(输⼊输出复⽤)三、PULL(端口上下拉)四、DRIVE-STRENGTH(端口驱动强度)五、 SMT(端口斯密特触发器)沉淀、分享、成长,让自己和他人都能有所收获!😄 …

Linux学习:多线程

一、shell脚本创建 1、创建一个文件夹,放所有文件,命名为test_shell 2、在文件中创建main.c与CMakeLists.txt 3、创建run.sh gedit run.sh 4、在run.sh中编写以下代码 #!/bin/bashrm bulid -rmkdir build cd build cmake .. make ./main 第一行&a…

java------JVM之类加载和双亲委派机制

类加载器:加载.class文件。 将新建的对象放入堆里面,而对象的引用(地址)放到栈,其中引用指向堆里面对应的对象。 1-启动类加载器,负责加载jre\lib目录下的rt.jar包c编写,加载java核心库 java.*,构造ExtClassLoader和A…

教程!!!!!

使用门槛:需要自行准备能开全局代理的科学工具 好评赠送免费科学工具,也可以自己准备科学工具。 下单以后,我们会发送一串账号密码给您。如图: 其中卡号就是chatgpt的账号,密码就是chatgpt密码。 第一步&#xff1…

「C#」异步编程玩法笔记-WinForm中的常见问题

目录 1、异步更新界面 1.1、问题 1.2、解决问题 1.3、AsyncOperationManager和AsyncOperation 1.4、Invoke、BeginInvoke、EndInvoke及InvokeRequired Invoke InvokeRequired BeginInvoke EndInvoke 2、死锁 2.1、问题 2.2、 解决方法 2.2.1、不要await 2.2.2、用…

OWASP API安全Top 10

文章目录API1-失效的对象级授权API2-失效的用户认证API3-过度的数据暴露API4-缺乏资源和速率控制API5-失效的功能级授权API6-批量分配API7-安全性配置错误API8-注入API9-资产管理不当API10-日志记录和监控不足在API安全发展的过程中,除了各大安全厂商和头部互联网企…

Windows系统编译Wireshark

编译环境 操作系统Windows 10 Wireshark版本3.6.10或3.0.0 Qt版本5.15.2或5.12.12 Python版本3.8 cmake版本3.19.2(64位) Strawberry版本5.22 安装 Microsoft Visual Studio 2019 Visual Studio 2019 版本 16.11 发行说明 | Microsoft Learn 安装 Microsoft Visual S…