数据库事务隔离级别真让人头疼(数据库 事务隔离级别)
mhr18 2024-09-18 20:23 20 浏览 0 评论
事务隔离性
在阐述隔离级别之前有必要说明一下事务中隔离性的定义:
#事务隔离性#:在多个并发事务同时执行时,一个事务的修改操作,相对于其他事务是不可见的,好像串行
一样。隔离性是一个概念,表示事务之间的独立性和保护机制,以确保数据的一致性。
事务隔离级别的定义
#事务隔离级别#:隔离级别是定义和控制隔离性的标准化方法。数据库管理系统通常提供了多个隔离级别,
如读未提交、读已提交、可重复读和串行化等级别。每个隔离级别规定了事务之间的可见性和影响范围,
以及对并发问题(如脏读、不可重复读和幻读)的处理方式。隔离级别是一种标准,定义了不同级别的
隔离性要求和并发处理策略,在具体的数据库管理系统中进行实现和控制。
不同数据库中的事务隔离级别
MySQL
在 MySQL 中,定义了以下四个事务隔离级别:
1、读未提交(Read Uncommitted):最低级别的隔离级别,允许一个事务读取另一个事务尚未提交的
数据。这可能导致脏读(dirty read),即读取到尚未提交的数据。
2、读已提交(Read Committed):每个事务只能看到已经提交的数据。其他事务对数据的修改在当前
事务中不可见。这样可以避免脏读,但仍可能存在不可重复读(non-repeatable read)和幻读(phantom
read)。
3、可重复读(Repeatable Read):确保在同一事务中多次读取相同数据集时,读取结果保持一致。即使
其他事务对数据进行了修改,可重复读事务也只能看到最初读取时的数据快照。这避免了脏读和不可重复读,
但仍可能存在幻读。
4、串行化(Serializable):最高级别的隔离级别,确保每个事务在执行期间都与其他事务完全隔离。它使
用锁定机制来保证事务的顺序执行,并消除了脏读、不可重复读和幻读等问题。然而,串行化隔离级别可能
会影响并发性能。
Oracle
在 Oracle 数据库中,定义了以下的事务隔离级别:
1、读已提交(Read Committed):这是默认的隔离级别。每个事务只能看到已经提交的数据。并发事
务之间可能会出现不可重复读和幻读的问题。
2、可序列化(Serializable):这是最高级别的隔离级别。它确保每个事务在执行期间都与其他事务完全
隔离,避免了脏读、不可重复读和幻读等问题。但是,它也可能导致较低的并发性能。
在 Oracle 数据库中,可以通过设置 SET TRANSACTION ISOLATION LEVEL 或使用事务隔离级别提示来
指定特定的隔离级别。例如:
-- 设置隔离级别为读已提交
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 使用隔离级别提示设置事务隔离级别
SELECT * FROM my_table FOR UPDATE NOWAIT;
需要注意的是,Oracle 还提供了多个级别的快照隔离(Snapshot Isolation),如可重复读(Serializable)
和序列化(Serializable)。这些级别通过使用数据库的闪回查询功能提供了更高程度的隔离性。然而,随
之而来的是一些额外的开销和限制。
脏读(dirty read),不可重复读(non-repeatable read)和幻读(phantom read)
脏读:读取到尚未提交的数据,可能是无效的数据。
不可重复读:在同一个事务中,多次读取同一行数据时,结果不一致。
幻读:在同一个事务中,多次查询同一范围的数据时,结果集出现新增或减少。
不同事务隔离级别的实现原理
读未提交实现
对于读未提交隔离级别,此级别不会对记录加锁。对系统表的数据操作,是数据引擎自己发出的数据查询
操作,使用读未提交隔离级别,目的是不与其它事务因锁的存在而冲突。(无锁)。具体实现细节如下:
row_search_mvcc(...) //获取记录
{...
/* We are ready to look at a possible new index entry in the result
set: the cursor is now placed on a user record */
if (prebuilt->select_lock_type != LOCK_NONE) { //如果需要加锁,则加锁的语义来自上层
...
} else { //不需要加锁
/* This is a non-locking consistent read: if necessary, fetch a previous version of the record */
if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) { //如果是读未提交,则什么也不做
/* Do nothing: we let a non-locking SELECT read the latest version of the record */
} else if (index == clust_index) { //否则,才需要检查“rec”是否满足可见性,不满足则找出满足可见性要求的旧版本
//所以,读未提交什么也不做,就是在说当前的rec是符合的,能被读到的,根本不用到回滚段找出旧版本(所得即所“可见”)
/* Fetch a previous version of the row if the current one is not visible in the snapshot;
if we have a very high force recovery level set, we try to avoid crashes by skipping this lookup */
if (srv_force_recovery < 5 && !lock_clust_rec_cons_read_sees(rec, index, offsets, trx_get_read_view(trx))) {
rec_t* old_vers;
/* The following call returns 'offsets' associated with 'old_vers' */
err = row_sel_build_prev_vers_for_mysql(trx->read_view, clust_index, prebuilt, rec, &offsets, &heap,&old_vers, need_vrow ? &vrow : NULL, &mtr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
if (old_vers == NULL) {
/* The row did not exist yet in the read view */
goto next_rec;
}
rec = old_vers;
}
} else {
/* We are looking into a non-clustered index, and to get the right version of the record we
have to look also into the clustered index: this is necessary, because we can only get the undo
information via the clustered index record. */
...
}
}
}
...}
读已提交实现
对于读已提交隔离级别的实现方式,从逻辑上需要明确两个部分,一是加锁部分二是解锁部分。加锁,对应
的是获取数据,确保在指定的隔离级别下读取到应该读到的数据。解锁则意味着要在适当的时机释放锁且不
影响隔离级别的语义还能提高并发度。
--加锁
一是加锁的时候,读已提交隔离级别不加间隙锁,这样就能允许并发的其他事务执行插入操作因而产生幻象现象,
因为读已提交隔离级别是允许幻象异常存在的。
其次,要确定可以读取到什么样的元组,即判断是不是没有被提交的元组也可以读到。既然是读已提交级别,
则必然是只能读取到已经被提交的元组,这样才能体现“已提交”的含义。
--解锁
解锁部分,要及时释放锁,这样便于其他事务能够读取到不应当被本事务锁定的记录。
--特点
1、在一个事务块内,如果存在多条SELECT语句,则在读已提交隔离级别下,每条SELECT语句分别使用自己的
快照(Read view,即为每条SELECT生成一个Read view,每条SELECT结束后,通过调用MVCC::view_close()
方法,Read view会被关闭)。
2、 对于一个UPDATE或DELETE操作,当有页面(索引页面)因增加或删除了元组而分离或合并时,需要让新页
继承旧页的锁信息,这时继承操作是通过lock_rec_add_to_queue()函数加锁完成的,但是,加锁时会有间隙锁存在,
可重复读隔离级别的实现
Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(读已经提交的,
其实是读早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新(即晚于本事务开始的),
并且,该事务不要求与其他事务是“可串行化”的。
--那么RR隔离级别是怎么保证这一点的呢?
如果数据库并发控制引擎是单纯的封锁协议机制,则应该在读取数据的时候,判断数据项是不是其他事务更新过的。
可是InnoDB没有这么做,而是通过如下方式,在RR隔离级别下为事务设置了一个“一致性读视图(即快照)”,
之后读取数据,就是根据这个快照来获取,这样,就不能看到他晚于本事务的事务对已有记录的更新(更新生成新版本,
必然不在旧的快照所限定的范围内)。
InnoDB 的可重复读的实现,利用了实现 MVCC 技术的快照技术。这是 MVCC 和基于封锁技术这两个并非控制技术的结合之处。
相关推荐
- 甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入
-
IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...
- 甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云
-
IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...
- Spring Boot 自定义数据源设置,这些坑你踩过吗?
-
你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...
- 一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)
-
今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...
- 低代码建模平台-数据挖掘平台(低代码平台的实现方式)
-
现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...
- navicat 17.2.7连接oracle数据库提示加载oracle库失败
-
系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...
- 开源“Windows”ReactOS更新:支持全屏应用
-
IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...
- SSL 推出采用全模拟内置混音技术的模拟调音台Oracle
-
英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...
- 47道网络工程师常见面试题,看看有没有你不会的!
-
你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
-
e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...
- 36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!
-
前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...
- Linux新手入门系列:Linux下jdk安装配置
-
本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...
- 手把手教你在嵌入式设备中使用SQLite3
-
摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...
- JAVA语言基础(java语言基础知识)
-
一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...
- 再见 Navicat!一款开源的 Web 数据库管理工具!
-
大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入
- 甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云
- Spring Boot 自定义数据源设置,这些坑你踩过吗?
- 一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)
- 低代码建模平台-数据挖掘平台(低代码平台的实现方式)
- navicat 17.2.7连接oracle数据库提示加载oracle库失败
- 开源“Windows”ReactOS更新:支持全屏应用
- SSL 推出采用全模拟内置混音技术的模拟调音台Oracle
- 47道网络工程师常见面试题,看看有没有你不会的!
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)