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

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: 对数据库事务理解以及脏读、不可重复读以及幻读问题

引言

事务就是能够把多个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-100where name = 'A';

-- B账户增加100

update accout set money=money+100where 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。


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
SQL 关系型数据库 MySQL
乐观锁在分布式数据库中如何与事务隔离级别结合使用
乐观锁在分布式数据库中如何与事务隔离级别结合使用
306 5
|
SQL 关系型数据库 MySQL
乐观锁在分布式数据库中如何与事务隔离级别结合使用
乐观锁在分布式数据库中如何与事务隔离级别结合使用
|
12月前
|
中间件 关系型数据库 Go
Go语言数据库编程:数据迁移与事务控制
本文介绍了《Go语言实战指南》中关于数据库编程的核心内容,涵盖使用 GORM 进行数据迁移与事务控制。主要内容包括:AutoMigrate 方法自动创建或更新表结构;事务控制的自动与手动实现方式;事务隔离级别的设置;以及在 Gin 框架中统一管理事务的实践建议。适合开发阶段的数据库结构管理和事务性操作需求。
|
SQL 数据库 数据安全/隐私保护
SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
【8月更文挑战第14天】解决SQL Server事务复制Log Reader作业因数据库所有者问题无法启动的方法:首先验证数据库所有者是否有效并具足够权限;若非,使用`ALTER AUTHORIZATION`更改为有效登录名。其次,确认Log Reader使用的登录名拥有读取事务日志所需的角色权限。还需检查复制配置是否准确无误,并验证Log Reader代理的连接信息及参数。重启SQL Server Agent服务或手动启动Log Reader作业亦可能解决问题。最后,审查SQL Server错误日志及Windows事件查看器以获取更多线索。
328 0
|
存储 SQL 关系型数据库
数据库事务:确保数据完整性的关键20
【7月更文挑战第20天】事务是数据库操作的基本逻辑单位,确保数据一致性。ACID原则包括:原子性(操作全成或全败),一致性(事务前后数据合法性),隔离性(并发操作互不影响),持久性(提交后更改永久保存)。MySQL的InnoDB引擎支持事务,通过undo log实现回滚,redo log确保数据持久化。开启事务可使用`BEGIN`或`START TRANSACTION`,提交`COMMIT`,回滚`ROLLBACK`。
487 70
|
SQL 数据库 索引
【YashanDB数据库】大事务回滚导致其他操作无法执行,报错YAS-02016 no free undo blocks
大事务回滚导致其他操作无法执行,报错YAS-02016 no free undo blocks
|
数据库
什么是数据库的事务隔离级别,有什么作用
【10月更文挑战第21】什么是数据库的事务隔离级别,有什么作用
259 3
|
存储 关系型数据库 数据挖掘
什么是数据库的事务隔离级别
【10月更文挑战第21】什么是数据库的事务隔离级别
500 1
|
存储 数据库 数据库管理
数据库事务安全性控制如何实现呢
【10月更文挑战第15天】数据库事务安全性控制如何实现呢
|
存储 数据库 数据库管理
什么是数据库事务安全性控制
【10月更文挑战第15天】什么是数据库事务安全性控制

热门文章

最新文章