Oracle的数据并发与一致性详解(上)
今天想了解下oracle中事务与锁的原理,但百度了半天,发现网上介绍的内容要么太短,要么版本太旧,而且抄袭现象严重,所以干脆查官方帮助文档(oracle 11.2),并将其精华整理成中文,供大家一起学习。
本篇将从数据并发与一致性概念开始,依次介绍事务隔离级别、锁机制、自动锁、手动锁、用户自定义锁的相关内容。
请尊重作者劳动成果,转载请标明原文链接:
https://www.cnblogs.com/jpcflyer/p/9164100.html
一、Oracle数据并发与一致性概念
在以前单用户的数据库环境中,我们根本就不需要关心数据一致性的问题,因为根本就不会有多个用户在同一时间修改同一数据。但在现在的多用户数据库环境中,必须允许同时发生多个事务,而且这些事务可能会访问同一数据,此外,还要保证这些事务的一致性。因此多用户数据库必须提供以下两个基本功能:
- 数据并发:即允许多用户同时访问同一数据
- 数据一致性:即每个用户看到的数据都是一致的
为了描述事务并发运行时的一致性行为,研究人员定义了一种事务隔离模型,称之为serializability(序列化)。这种可串行化事务操作使得它看起来似乎没有其它用户在操作数据。虽然这种序列化机制在一般情况下是可用的,但在并发要求高的场景,它会严重影响系统的吞吐能力。一般情况下,需要在事务隔离级别与性能间作一个取舍。
Oracle通过使用multiversion consistency model(多版本一致性模型)、以及各种锁和事务来维护数据一致性,下面介绍下相关概念。
1.Multiversion Read Consistency(多版本读一致性)
多版本指的是同时存在数据的多个版本,意味着oracle有以下两个特性:
- read-consistent queries(读一致性查询)
查询返回的数据是已提提交的,在某一时间点是一致的。(注意:oracle中是不会有脏读的,为什么呢?原因是第一条会话插入一条记录不提交,第二个会话再查询时发现这个事务没有commit,从而会找到这个事务的事务槽,事务槽中记录着该行未修改前的值存放在undo的位置,然后把该undo块加载到内存构造出CR块,查询会读取CR块中的值返回给客户。)
- nonblocking queries(非阻塞查询)
数据的读和写不会相互阻塞。
2.Statement-Level Read Consistency(声明级读一致性)
Oracle总是强制保证声明级的读一致性,确保查询返回的数据在同一时间点是已提交的(原因已在上面提及)。
3.Transaction-Leval Read Consistency(事务级读一致性)
Oracle可以提供事务中所有查询的一致性,即事务中每个声明看到的数据都是某一点的数据,这个点指的是事务开始的点。在序列化事务中的查询只能看到自己本事务发生的修改。事务级读一致性产生了可重复读,且不会产生幻影读。
4.Read Consistency and Transaction Table(读一致性和事务表)
Oracle使用了事务表来确定当数据库开始修改一个块时,是否有未提交的事务,这个事务表也称为interested transaction list(ITL)。事务表中描述了哪个事务有行锁、哪一行包含已提交或未提交的修改。
5.Locking Mechanisms(锁机制)
一般来说,多用户数据库会使用多种数据锁的形式来解决数据的并发与一致性问题,本文后面会有锁的详细介绍。
6.ANSI/ISO Transaction Isotation Levals(ANSI/ISO事务隔离级别)
ANSI和ISO都采纳的SQL标准中,定义了四个级别的事务隔离。这些不同级别对事务吞吐量有不同影响。这些隔离级别定义是为了预防两个并发事务会产生的一些现象,这些现象包括:
- 脏读:一个事务读取了另一个事务没有提交的数据
- 不可重复读:一个事务重复读取刚才已读过的数据,结果两次数据不一致,在此期间,其它事务对此数据已修改并提交
- 幻影读:一个事务重复读取满足查询条件的记录数,结果两次数据不一致,在此期间,其它事务插入了符合此查询条件的数据
SQL标准中根据隔离级别允许发生的现象,定义了四种隔离级别:
Oracle数据库提供了read committed(默认级别)和serializable两种隔离级别,同时还支持只读模式。
二、事务隔离级别
上面已经提到ANSI的四种事务隔离级别,下面来详细介绍oracle数据库提供的三种事务隔离级别:read committed, serializable,read-only。
1.Read Committed事务隔离级别
在此级别中,事务中查询到的数据都是在此查询前已经提交的。这种隔离级别避免了读取脏数据。然而数据库并不阻止其它事务修改一个所读取的数据,其它事务可能会在查询执行期间修改。因此 ,一个事务运行同样的查询两次,可能会遇到不可重复读和幻影读。
- read committed隔离级别中的读一致性
每个查询都会提供一个一致性的结果集,其中不需要用户做什么(这里的查询也包含像update中where这样的隐式查询)。
- read committed隔离级别中的写冲突
在一个read committed事务中,当事务要更改一行,而这行已经被另外一个未提交事务修改了(有时称之为blocking transaction),这里会发生写冲突。此时这个事务会等待blocking transaction结束,并有以下两个选项:
- 如果blocking transaction回滚,那么waiting transaction会修改之前被locked的行
- 如果blocking transaction提交然后释放锁,那么waiting transaction会在改变后的数据基础上,进行更新
下表显示了事务1(可以是read committed或serializable)与事务2(read committed)的典型交互,称之为lost update(丢失更新)。
事务1 | 事务2 | 说明 |
---|---|---|
SQL> SELECT last_name, salary |
||
SQL> UPDATE employees SET salary |
事务1用的是默认隔离级别 |
|
SQL> SET TRANSACTION ISOLATION |
||
SQL> SELECT last_name, salary |
事务2通过使用oracle的读一致性得到了事务1更新前的数据 |
|
SQL> UPDATE employees SET salary = |
||
SQL> INSERT INTO employees |
事务1插入了employee Hintz,但并没有提交 |
|
SQL> SELECT last_name, salary |
事务2看不到事务1未提交的Hintz信息 |
|
SQL> UPDATE employees SET salary = |
事务2尝试去更新被事务锁住的Banda信息,产生了写冲突,此时事务2要等到事务1结束后再执行 |
|
SQL> COMMIT; |
||
1 row updated. SQL> |
事务1提交,结束了事务,事务2继续处理 |
|
SQL> SELECT last_name, salary |
||
COMMIT; |
||
SQL> SELECT last_name, salary |
关于丢失更新的问题,后面有时间再讨论。
2.Serializable事务隔离级别
在序列化隔离级别中,事务可以看到的是事务开始时已经提交的或事务自己做的修改。此隔离级别适合下面的场景:
- 超大数据库并且事务很小,每个事务只更新几行
- 在两个并发事务修改相同行的几率相对比较低的场景
- 有较长的事务,但主要是只读事务的时候
在序列化隔离级别中,读一致性从通常的语句级扩展成整个事务级。事务中读取的任何行,再次读时保证是相同的。序列化事务不会遇到脏读、不可重复读、幻影读的问题。
Oracle允许序列化事务修改数据,不过如果有其它事务修改,那么这个事物必须在序列化事务开始之前就提交。当一个序列化事务企业修改一行,而该行被别的事务修改,且在序列化事务开始之后才提交,这时候会报ORA-08177:Cannot serialize access for this transaction。此时,应用可以采取以下动作:
- 提交事务
- 执行其它不同的语句,也许会回滚到之前的savepoint
- 回滚整个事务
下面显示一个序列化事务是如何与其它事务交互的。如果一个序列化任务不去尝试修改其它事务在序列化事务开始后提交的数据,那么serialized access问题可以避免。
事务1 | 事务2 | 事务3 |
---|---|---|
SQL> SELECT last_name, salary |
||
SQL> UPDATE employees SET salary |
事务1是默认的 |
|
SQL> SET TRANSACTION ISOLATION |
||
SQL> SELECT last_name, salary |
||
SQL> UPDATE employees SET salary = |
||
SQL> INSERT INTO employees |
||
SQL> COMMIT; |
||
SQL> SELECT last_name, salary |
SQL> SELECT last_name, salary |
注意:oracle的读一致性使得事务2的前后读取是一致的,即事务1的插入和更新操作对事务2来说是不可见的 |
COMMIT; |
||
SQL> SELECT last_name, salary |
SQL> SELECT last_name, salary |
|
SQL> UPDATE employees SET salary |
||
SQL> SET TRANSACTION ISOLATION |
||
SQL> UPDATE employees SET salary = |
||
SQL> COMMIT; |
||
UPDATE employees SET salary = 7200 |
报错原因在于事务3的提交是在事务4开始之后,没有满足序列化 |
|
SQL> ROLLBACK; |
事务2回滚以结束事务 |
|
SQL> SET TRANSACTION ISOLATION |
||
SQL> SELECT last_name, salary |
||
SQL> UPDATE employees SET salary = |
||
SQL> COMMIT; |
3.Read-Only事务隔离级别
只读隔离级别和序列化隔离级别很像,只是在只读事务中,不允许有修改操作,除非是用sys用户。因此只读事务不会有ORA-08177错误,只读事务在产生一个报告时很有效。
——限于精力,今天先写到这里,明天继续更新下篇——锁机制、手动锁、用户自定义锁。
参考资料:《Oracle官网在线帮助文档》
Oracle的数据并发与一致性详解(上)的更多相关文章
- Oracle的数据并发与一致性详解(下)
上篇介绍了数据并发与一致性的相关概念.以及oracle的事务隔离级别等内容,本篇继续介绍锁机制.自动锁.手动锁.用户自定义锁的相关内容. 请尊重作者劳动成果,转载请标明原文链接: https://ww ...
- Oracle中用exp/imp命令参数详解【转】
Oracle中用exp/imp命令参数详解 [用 exp 数 据 导 出]:1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中 exp sy ...
- Java并发关键字Volatile 详解
Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ...
- Oracle GoldenGate中HANDLECOLLISIONS参数使用详解
Oracle GoldenGate中HANDLECOLLISIONS参数使用详解 HANDLECOLLISIONS 是一个 replicat 进程参数,主要在 initial load 中使用.在 ...
- Oracle Database 12c Release 2安装详解
第1章 Oracle Database 12c Release 2安装详解 1.1 下载方法 oracle官网https://www.oracle.com 1)打开官方网站,找到下载连接 2)选择更多 ...
- java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock
原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...
- oracle入坑日记<三>用户详解(角色理解)
1 用户是什么 1.1.权限管理是Oracle的精华,不同用户登录到同一数据库中,可能看到不同数量的表,拥有不同的权限.Oracle 的权限分为系统权限和数据对象权限,共一百多种.如果把Oracl ...
- oracle数据库定时任务dbms_job的用法详解
本文来源:Ruthless <oracle数据库定时任务dbms_job的用法详解> 一.dbms_job涉及到的知识点 1.创建job: variable jobno number; ...
- Oracle10g数据泵impdp参数详解--摘自网络
Oracle10g数据泵impdp参数详解 2011-6-30 12:29:05 导入命令Impdp • ATTACH 连接到现有作业, 例如 ATTACH [=作业名]. • C ...
随机推荐
- 统计百分比的一个SQL脚本
统计一个表中一个百分比的SQL脚本,不过这个是个万分比,这个数据类型要调一调 ),) declare @num3 decimal,@num4 decimal declare @percent deci ...
- atom编辑器使用“apm install”无法响应的解决方案
工具:shadowsocks 利用ss建立代理服务,之后apm --help,得到apm的配置命令: apm - Atom Package Manager powered by https://ato ...
- Maven学习 一 概念介绍
一 Maven是什么 Maven是一个Apache公司的开源项目,主要有两个作用:(1)是项目构建工具.(2)是用来管理java程序中jar包的依赖. 它包含了一个项目对象模型(Project Obj ...
- (转)Flex 布局教程:
这个博客的内容比较新,多看看 http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html [语法篇] http://www.ruanyifeng. ...
- Oracle DBLINk的使用
Oracle中自带了DBLink功能,它的作用是将多个oracle数据库逻辑上看成一个数据库,也就是说在一个数据库中可以操作另一个数据库中的对象,例如我们新建了一个数据database1,我们需要操作 ...
- veri HDL modeisim仿真:test bench文件编写
预编译指令: verilog HDL预编译指令是以" ' "字符开头,而且不需要以";"结尾. 作用:指示在编译verilog hdl源代码前,需要执行哪些操作 ...
- JDBC几种常见的数据库连接
JDBC的URL=协议名+子协议名+数据源名.a 协议名总是“jdbc”.b 子协议名由JDBC驱动程序的编写者决定.c 数据源名也可能包含用户与口令等信息:这些信息也可单独提供.几种常见的数据库连接 ...
- ReactNative学习笔记(二)基础进阶
一个最简单的HelloWorld页面 先不多解释,直接上代码: import React, { Component } from 'react'; import {AppRegistry, Style ...
- 设计模式,Let's “Go”! (上)
code[class*="language-"], pre[class*="language-"] { background-color: #fdfdfd; - ...
- Elastic-search在linux上的安装
今天是我装第四次 ES ,之前装好用了一段时间,后面莫名其妙爆炸了,炸出一堆异常... 安装环境: JDK1.8 centos ElasticSearch-6.2.4 jdk1.8以上,所以 ...