Oracle的数据一致性机制原理

2023-12-05

一、前言

在单用户环境下,在操作数据库是不需要考虑其他用户会修改同一个数据。但是在多用户的情况下,多个事务可能会修改同一个数据,最终会得到错误的数据结果。

Oracle数据库是通过 multiversion consistency model(多版本数据一致性模型)、还有不同类型的锁、事务隔离保证数据的一致性。

通过这种方式,数据库可以向多个并发用户提供在某一个时间点所对应的数据库数据。由于不同版本的数据块可以同时存在,事务可以查询所需时间点已经提交的数据版本,并返回对应时间点已提交的数据查询结果。(数据块的头部存储了历史事务信息)

提问:什么是数据一致性呢?

在数据库中,数据一致性是指在多个并发事务同时访问数据库时,确保读取操作的结果对于所有事务都是一致的。

这意味着当一个事务正在读取数据时,如果其他事务正在对相同的数据进行修改或写入操作,读取操作不应该看到未完成的或部分更改的数据。相反,读取操作应该看到已经提交的、完整的数据,以确保事务之间的数据一致性。

二、数据读一致性

数据的读一致性分为两个层面,一个是语句级别的读一致性,另外一个是事务级别的读一致性。

2.1、语句级别读一致性(Statement-Level Read Consistency)

Oracle数据库强制使用语句级别的读一致性,这样保证每次返回的数据是在这个时间节点之前已经提交的数据。

在这里插入图片描述
当进行一次查询时,发生在 SCN 10023(SCN是Oracle数据库的一种顺序标识,代表事务先后),只会看到10023之前已经提交的数据。在图中有两个大于SCN10023的数据块,是SCN1024,这时 Oracle数据库会将这两个数据块拷贝到一个缓冲区中,然后根据undo segment(撤销段)中的数据重新构建这两个数据块(CR,consistent read clones)在1024前已经提交的数据,最后正确的检索就是SCN100021->SCN100021->SCN10006->SCN10008->SCN10021->SCN10011->SCN10021,过这种机制每次查询的时候查询到的都是事务已经提交的数据,防止了脏读。

提问:那什么是SCN呢?

SCN的全称是System Change Number,它在数据库中充当时钟的角色,是数据库内部使用的一个逻辑数据,Oracle数据库可以根据它的大小来判断事务发生的先后顺序。Oracle数据库是在SGA(Sytem Global Area)中完成SCN增量操作。当事务修改数据时,数据库会将新的SCN保存到与事务相对应的撤销段中(undo segment)中。

提问:即使有了SCN机制,数据库能够知道事务的先后顺序,那数据库是怎么知道事务提交了还是没有提交?

每一个数据库块(block,Oracle数据库底层逻辑存储最小单元),都有一个数据块头(block header),里面包含了在数据库块上进行的事务活动(事务执行历史),里面记录了事务的状态(活跃 Active、提交 Commit、回滚 RollBack)。

2.2、事务级别的读一致性(Transaction-Level Read Consistency)

Oracle数据同样也可以对一个事务中的多条查询语句提供读一致性。在事务中的每条语句看到的都是同一节点(同一SCN)的已经提交的数据。

2.3、读一致性的数据存储

提问:Oracle数据库是如何给每个不同SCN对应的事务看到之前已经提交的数据呢?这些数据又是放到那里呢?

要管理多版本读取一致性模型(multiversion read consistency model),数据库必须在同时查询和更新表时创建一组读取一致性数据。

这里就涉及到了撤销段,撤销段(undo segment)是数据库的一个逻辑结构,用于管理extents(区),而 extents 是由多个数据库块(block)组成。

每当用户修改数据时,Oracle 数据库都会产生一个撤销数据实体(undo entries),之后会将这个实体写入到撤销段(undo segment)中。撤销段中包含已提交事务或者未提交事务所作更改之前数据库中的旧数据,

通过这种方式,同一个数据,在不同时间节点的不同版本数据可以存在于数据库中。这样数据库可以提供不同时间节点,不同版本的数据库快照视图,来保证读一致性。

2.4、锁机制

Oracle数据的某一条事务在修改数据时,其他事务不能在进行修改,实现这种操作就要使用到锁机制。

锁我的理解是它是一种机制,一种用于防止破坏性交互行为的机制,破坏性行为就是指并发修改某一个数据,修改后的结果是错误的,通过锁这种机制来避免错误的修改结果,保证数据库数据的一致性。

锁大致可以分为两类,一种是排他锁,另外一种是共享锁。多个资源在竞争锁时,只有一个资源能够获取到排他锁,多个资源可以获取到共享锁。只有当修改数据时,数据才会被锁定,正常情况下是锁定一行数据,而不是整张数据库表。

三、事务隔离级别

Oracle数据库提供三种事务隔离级别分别是RC(read committed)、Serializable、read-only。

在这里插入图片描述
3.1、RC隔离级别

RC隔离级别是Oracle数据库默认的隔离级别,在RC隔离级别下可以保证每次查询到的数据都是事务已经提交的数据,不会读取到事务未提交的数据,保证数据的一致性。也就说当一个查询正在查询一个表中id为2的数据时,此时另外一个事务把该数据修改了,但是查询出的结果是修改之前的结果,不会查询到事务未提交的结果。

在RC隔离级别下,可能会出现更新丢失的问题。这是一个很诡异的现象。举个例子说一下:

假设某公司要给小张涨工资1k,现在有两个财务操作员A和B,它们进行了以下操作:

1.操作员A查询出了小张现有的工资,选择了薪水修改,并输入了要提薪的1000数据,但此时有事,临时走开了,没有提交(事务未提交)。

2.操作员B查询出小张现有的工资,选择了薪水修改,并输入了要提薪的1000数据,然后提交了修改。

3.操作员A忙完事情回来了,然后提交了修改。

小张高兴坏了,自己涨了两千的工资。

在这个例子中操作员A没有提交,但是在提交的时候要重新查询一下看一下薪水有没有被修改。这样不会造成操作员B的修改丢失。

比如可以通过乐观锁的形式,给表上添加版本列进行解决,版本列可以是日期,一个递增的版本数字等。这是一种比较好的方式,当然也存在其他方式。

3.2、Serializable隔离级别

Serializable隔离级别是Oracle数据库最高级的事务隔离级别,在这个级别下,数据库确保事务之间的操作不会相互干扰(行级锁定、多版本并发控制等),从而保证了数据的一致性和完整性。

在序列化事务隔离级别下,事务只能看到在事务开始时做的更改以及事务本身所做的更改。如果某个事务开始后,其他事务已经提交了对相同数据的修改,那么这个事务就会被视为尝试修改已经被其他事务更改的数据,此时Oracle数据库会抛出ORA-08177: Cannot serialize access for this transaction异常。

3.3、Read-Only隔离级别

read-only事务隔离级别,是一个简单粗暴的事务隔离级别,它只允许事务进行读取数据,不允许修改数据,但是当用户是sys用户时将允许进行数据修改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Oracle的数据一致性机制原理 的相关文章

  • Oracle sqlldr是否并行处理多个INFILE

    我正在使用 sqlldr 将数据加载到 Oracle RAC 在 Linux 上 并且我正在尝试提高数据加载的性能 我正在使用 直接路径 并且为 sqlldr 设置了 parallel true 而且 由于我的服务器是多核的 所以默认情况下
  • 想要在Sql中获取两列的差异

    我想获取表的列的差异 我们的列名称为 Planned date 所以现在我想获取这两列的差异 A Planned Date of stop1 Planned Date of stop5 那么我如何编写查询来获取 A 的值 下面是我编写的示例
  • oracle查找两个表之间的差异

    我有两个结构相同的表 一个是临时的 另一个是产品的 每次都会加载整个数据集 有时该数据集会从先前的数据集中删除记录 我首先将数据集加载到临时表中 如果删除了任何记录 我也想从产品表中删除它们 那么如何找到prod中存在但temp中不存在的记
  • 物化视图中完全刷新和快速刷新有什么区别?

    我在自己的模式中有物化视图 物化视图源是另一个模式表 但是 这个主表有 900 行 我在这个主表上做了一些 dml 操作 之后我将刷新这个物化视图 正如你所知 我做了一些研究 我如何刷新我自己的物化视图 它说 你可以进行完全刷新或快速刷新
  • 我怎样才能等到所有调度程序作业完成?

    我是我的包裹 我正在排队多个作业 如下所示 dbms scheduler create job job name gt p job name job type gt PLSQL BLOCK job action gt p sql code
  • 在 MVC3 应用程序中使用具有表单身份验证的 Oracle 数据库

    我编写了一个简单的 MVC3 应用程序 并遵循了有关如何设置经过身份验证的用户的教程 本教程使用 SQL Server Express 数据库 是否可以使用 Oracle 数据库代替 SQL Server 这只是更改 web config
  • SQL SELECT 对值求和,不包括重复项

    我在 Oracle SQL 中遇到一个问题 我正在尝试解决这个问题 我将用一个例子来说明 我正在查询三个表 Employees EmployeeID Name 1 John Smith 2 Douglas Hoppalot 3 Harry
  • 从 all_tab_columns 中选择,其中表有 > 0 行

    我需要在大型数据库中搜索与列名匹配的表 但该表必须有超过 0 行 顺便说一句 这是查询 SELECT FROM all tab columns WHERE column name LIKE ID SUPPORT 您可以使用单个查询来过滤名称
  • 当网站停止时,Oracle 数据提供程序会固定 IIS 工作进程

    我们在 Oracle 11g 第 2 版中遇到了一个严重的问题 其中 w3wp 进程接管了整个处理器核心 并且调试显示 Oracle 数据提供程序无限地抛出 ThreadAbortException 开发人员通过执行以下操作发现了此问题 1
  • 关于pl/sql存储程序文本的问题

    我使用 TOAD 进行 PL SQL 开发 在 TOAD 中 当我输入过程名称并按 f4 时 我可以看到该过程的源代码 我认为 TOAD 从 v sqltext 视图获取源代码 为了证实我的想法 我写了一个查询 select from v
  • 使用 createNativeQuery 调用 Oracle 存储过程

    我需要使用 JPA 调用存储过程并找到这篇文章 http www oracle com technology pub articles vasiliev jpql html http www oracle com technology pu
  • 如何从 TOAD for Oracle 执行函数并将结果绑定到数据网格

    我有一个函数 它将 pl sql 对象的 VARRAY 作为其参数之一 如何执行此存储过程并将其返回的结果集绑定到 TOAD for Oracle 中的数据网格 经过一番搜索后 我找到了自己问题的答案 假设您的 varray 类型称为 va
  • Oracle存储过程使用数组作为表插入的参数

    我一直在寻找一个明显的例子 但没有运气 抱歉 如果已经回答了 我正在尝试做一些非常简单的事情 一个存储过程 它将获取输入并将它们插入到表中 我希望它获取多行数组并一次全部插入 我认为这很简单 但我还没有找到一个可以展示我的例子 在很多例子中
  • Oracle 9i:同义词表不存在?

    我创建了一个包 其中包含一个存储过程 我计划从单独的应用程序调用该存储过程 存储过程将返回架构中所有视图和表的排序列表 为此 它对 DBA TABLES 和 DBA VIEWS 同义词执行简单的选择 如下所示 CREATE OR REPLA
  • TOAD 将 &String 视为绑定变量

    我正在使用 Oracle Data Integrator 开发一些 ETL 有时会使用 TOAD 测试部分代码 今天我遇到了 TOAD 的问题 我有一行像 AND column value like DEV PROD 当我尝试运行包含上面过
  • 使用Powershell访问远程Oracle数据库

    我需要能够连接到我的网络上基于 Windows 7 的 Oracle 服务器 32 位 Oracle XE 我需要连接的机器运行 Windows 7 64 位 两台机器上都安装了 Powershell 我已在 64 位计算机上安装了 Ora
  • 分层查询

    我希望我能够解释困扰我的问题 我有以下分层数据集 这只是 34K 记录的子集 PARENT ID CHILD ID EXAM TUDA12802 TUDA12982 N TUDA12982 TUDA12984 J TUDA12984 TUD
  • Oracle TDE 能否保护数据免受 DBA 的侵害?

    甲骨文专家 我的客户想要部署一个必须在数据库中保存信用卡号的应用程序 客户显然很关心安全性 我们特别关注一个令人痛苦的问题 我们如何确保只有具有 业务需要知道 的授权用户才可以访问数据 我们如何保护数据免受 DBA 的侵害 一个明显的解决方
  • Oracle:如何确定“AFTER ALTER”触发器中对象的新名称?

    假设我有一个AFTER ALTER在我的 Oracle 数据库上触发并重命名一些数据库对象 ALTER RENAME TO 在触发器中 我如何确定new数据库对象的名称 看来ORA DICT OBJ OWNER ORA DICT OBJ N
  • Delphi 5 中的 Oracle 数据库连接

    我正在使用 Delphi 5 版本 我想连接到 Oracle 数据库 我有 TDatabase 组件 我不知道如何通过 Delphi 连接到数据库 请提供连接数据库的步骤 谢谢 The TDatabase http docwiki emba

随机推荐