逻辑IO及当前模式读和一致性读的总结杂记
逻辑IO
逻辑读(确切是指db get之read不是consistentget之read):就是服务器进程从SGA上的buffercache(高速缓存)区域(先)根据SQL语句解析过程所获得的要操作的数据块的地址找到相关的数据块(后,再)读取这些相关的数据块上的相关数据行,到该服务器进程的PGA内存上,这就是一次逻辑读。简单地说,就是一次从buffer cache读取内容到PGA内存上的过程。
注释:
首先,这些数据块指的是在buffer cache上的数据块,也就是在内存上的数据块。若是服务器进程发现在buffercache上找不到服务器进程想要的数据块,服务器进程就会根据该数据块的地址从磁盘的数据文件上将之读取到buffercache上来,这就是一次物理读,然后再从buffercache上将该数据块读取到该服务器进程的PGA内存上,这就是一次逻辑读(这个不算做一次逻辑读,一次逻辑读特指一次从buffercache读取内容到PGA内存上的过程)。
接着,逻辑读过程中,如果服务器进程从SGA上的buffer cache(高速缓存)区域上找到的某一个数据块上有很多行要读取时,可能就会一次读取不完,要多次逻辑读,这个取决于参数arrysize(即一次逻辑读读取几行数据行)。物理读不知道有这个限制否?
最后一点是,select操作要使用逻辑读,它从buffer cache读取内容到PGA内存上自己的结果集中,再发给客户端。
(姑且认为有一种逻辑写的概念,那么)逻辑写(确切是指db get之write,不是consistent get之write):就是服务器进程从SGA上的buffercache(高速缓存)区域(先)根据SQL语句解析过程所获得的要操作的数据块的地址找到相关的数据块(后,再)修改这些相关的数据块上的相关数据行的内容,这就是一次逻辑写。
注释:
DML操作要使用逻辑写,它在buffer cache上修改相关的数据块上的相关数据行的内容。
逻辑读和逻辑写共同一步骤:
都是要根据SQL语句解析过程所获得的要操作的数据块的地址找到相关的数据块。
逻辑读和逻辑写不同一步骤:
之后,逻辑读是读取这些相关的数据块上的相关数据行到该服务器进程的PGA内存上,而逻辑写是修改这些相关的数据块上的相关数据行的内容。
或者另外一种理解是说,
逻辑读就是根据SQL语句解析过程所获得的要操作的数据块的地址找到相关的数据块的过程。
姑且认为有一种逻辑写的概念,那么逻辑写就是是修改这些找到的相关的数据块上的相关数据行的内容的过程。
注释:
逻辑读包括当前模式读( current read)和一致性读(consistent read)两种情况。
在oracle中,没有所谓逻辑写的概念。逻辑读既是读数据块也是写数据块的意思。见于《oracle性能诊断艺术》2.4读写数据块。
======================================================================================
什么是当前模式(Current Mode)?或者说什么是当前模式读( current read)?
当发生修改数据操作时,Oracle从buffer cache中,找到被修改数据行所在的数据块的过程,就是所谓的当前模式读 的过程。也就是说当前模式读的前提是发生在修改数据(DML)操作的情况下的。由当前模式读出来的数据块就是为了被修改的。而修改数据(DML)操作的第一步是一致性读的过程,第二步才是当前模式读的过程。
总之,DML操作(即修改数据的操作)的第二步过程才是当前模式读(过程),当前模式读(过程)就是DML操作(即修改数据的操作)的第二步过程。
强调下,当前模式读,它是操作中的一步过程。
统计信息里的db block gets的就是由当前模式读而得到的块的读取次数(该读取次数不等于块的个数,因为一次逻辑读不会读取完块里的所有数据,而是一次N数据行,这个N值就是客户端的变量arraysize),这些块包括DML操作要修改的数据行所在数据块(还有该要修改数据行的所在的表的段头块)以及用于保留该表原数据信息的undo块和undo块所在undo段的undo段头块。
至于DML操作的一致性读过程是以全表扫描的方式(全表扫描会读取表的所有数据块,这样consistent gets 的值自然就会高很多,也就意味着该DML操作的执行过程花的时间要长一些)还是其他访问方式取决于优化器(比如,优化器会根据DML操作语句里where的限制条件的具体形式来决定用什么访问方式)。
至于DML操作的当前模式读过程是应该是和DML操作的一致性读过程用同样的访问方式吧,不然set autotrace on后的执行计划里只有一份执行计划,而不是两个过程两份执行计划。(?)亦是或者,只是读取DML操作要修改的数据行所在数据块。
什么是一致性读(consistent read)?
一致性读(和普通的读之间最大的区别就在于),它会根据操作语句开始执行时本身事务的 SCN 从UNDO段(或说UNDO表空间)中(的undo块((来自buffer cache))上)读取 undo 内容并应用到需要进行一致性读的数据块(来自buffer cache)上,以保证数据的一致性。
统计信息里的consistent gets的就是由一致性读而得到的块的读取次数(该读取次数不等于块的个数,因为一次逻辑读不会读取完块里的所有数据,而是一次N数据行,这个N值就是客户端的变量arraysize),这些块包括操作(包括DML操作和select操作)要读取的数据行所在数据块(还有该要读取数据行的所在的表的段头块)以及因为有些读取来得数据块需要进行一致性读过程而要用到undo块故而读取(之前修改过有些读取来得数据块的其他事务所对应)的undo块和undo块所在undo段的undo段头块。
至于操作(包括DML操作和select操作)的一致性读过程是以全表扫描的方式(全表扫描会读取表的所有数据块,这样consistent gets 的值自然就会高很多,也就意味着该DML操作的执行过程花的时间要长一些)还是其他访问方式取决于优化器(比如,优化器会根据DML操作语句里where的限制条件的具体形式来决定用什么访问方式)。
当前模式读( current read),读的对象就是SGA上的buffercache(高速缓存)区域里的数据块。CR块则是由当前块通过undo块的配合构造出的副本。
注释:
select操作(即读操作)开始执行时,它会以自己开始执行的时间SCN为准对它所要操作的表的所有数据内容进行一次一致性读模式的读取过程来回滚以获得select操作开始执行时的那一刻表的内容,接着再根据过滤条件(即where后的限制条件)过滤出select语句的结果,最后将这些结果显示在屏幕上。
DML操作(即写操作)开始执行时,它也会以自己开始执行的时间SCN为准对它所要操作的表的所有数据内容进行一次一致性读模式的读取过程来回滚以获得DML操作开始执行时的那一刻表的内容,接着再根据过滤条件(即where后的限制条件)过滤出DML操作的所要操作的那些数据行,最后DML操作根据这些数据行的地址以当前读模式找到在buffer cache上的相关数据行,对它们进行修改操作。
select操作(即读操作)和DML操作(即写操作)两个操作有一个共同点就是都有一个一致性读模式的读取过程,而DML操作(即写操作)还有一个当前读模式的修改过程(不带有order by字句的select操作是没有这一步过程)。所以,执行select操作时所得的统计信息里的db block gets 总是为0的。而执行DML操作时所得的统计信息里的db block gets 当然是不为0的。如下例子所示:
12. HELLODBA.COM>select * from bigtab;
13.
14. 529517 rows selected.
15.
16.
17. Statistics
18. ----------------------------------------------------------
19. 0 recursive calls
20. 0 db block gets
21. 42118 consistent gets
22. 7301 physical reads
12. HELLODBA.COM>update tt set x=1;
13.
14. 2 rows updated.
15.
16. Statistics
17. ----------------------------------------------------------
18. 0 recursive calls
19. 4 db block gets
20. 7 consistent gets
21. 8 physical reads
当然,无论什么类型的操作(select操作也是不例外的)里若是有order by即用于排序的字句存在的话,则db block gets 是不为0的,也就是说带有order by字句的select操作便也会有一个当前读模式的修改过程。例如,
12. HELLODBA.COM>select * from t_test2 order by table_name;
13.
14. 2072 rows selected.
15.
16. Statistics
17. ----------------------------------------------------------
18. 7 recursive calls
19. 21 db block gets
20. 65 consistent gets
21. 201 physical reads
22. 0 redo size
23. 131049 bytes sent via SQL*Net to client
24. 1903 bytes received via SQL*Net from client
25. 140 SQL*Net roundtrips to/from client
26. 0 sorts (memory)
27. 1 sorts (disk)
28. 2072 rows processed
这是由于获得的结果集的值要排序,其实质的操作就是修改存放结果集的各个数据块里的内容,比如本来在未排序前,数据行a放在数据块w上,经过排序后,数据行a放在了数据块y上了,这个过程其实就是修改了数据块w和y的内容,所以是按db block gets来统计的。
这样,我们修正下当前模式读的定义:
当发生修改数据过程时,Oracle从buffer cache中,找到被修改数据行所在的数据块的过程,就是所谓的当前模式读 的过程。也就是说当前模式读的前提是发生在修改数据过程的情况下的。由当前模式读出来的数据块就是为了被修改的。像DML操作的第一步是一致性读的过程,第二步才是当前模式读的过程;像order by字句对应的执行过程就是当前模式读的过程。
总之,修改数据的过程,包括order by字句对应的执行过程和DML操作的第二步过程,才是当前模式读(过程),当前模式读(过程)就是修改数据的过程,包括order by字句对应的执行过程和DML操作的第二步过程。
附加:
1、逻辑读的 db block gets 和 consistent gets 是被分别统计的,也就是说 SQL Trace 中的统计数据要
将两者相加才得到该语句的逻辑读的数量;而(DML操作时)物理读则是将两者被合并统计的(也就是说db block gets 和 consistent gets两个读取的相同的数据块(即数据块的地址相同)部分(这部分是两者重合的)不做两次计数,而是当做一次);
2、数据文件上空的数据块也是要先被读取到内存上后,才能被比如DML操作使用的。数据文件上空的数据块也是要先被读取到内存上,相当于该DML操作在数据文件上占用了该空的数据块。数据文件上空的数据块也是要先被读取到内存上,是因为空的数据块虽然存储数据行的那一层是空的,但是块的块头里还是存在一些关于块本身的信息的,如块地址,大小,块的类型等。
3、物理读的次数不是等于其读取的块的次数。其受参数db_file_multiblock_read_count等的影响。
注释:
Oracle DB_FILE_MULTIBLOCK_READ_COUNT是Oracle比较重要的一个全局性参数,可以影响系统级别及sessioin级别。主要是用于设置最小化表扫描时Oracle一次按顺序能够读取的数据块数。通常情况下,我们看到top events中的等待事件db file scattered read时会考虑到增加该参数的值。
参考:
http://blog.csdn.net/leshami/article/details/8985734
http://blog.itpub.net/23135684/viewspace-749200/
======================================================================================================================
(数据库实例启动后,)所有的操作(DML和select)针对的对象都是内存上的数据块,如果操作所要的数据块不在内存上,就会从数据文件上读取到内存上来。
说一下两个DML操作针对的是同一个数据块上的不同数据行这种情况:
假设会话1上的A操作先开始的,会话2上的B操作后开始的。A操作执行的过程如下:会话1的服务器进程先锁住(用闩锁)buffercache上整条LRU链表,此时其他进程不可访问链表的,接着,会话1的服务器进程找到链表上所要的数据块(之后还是在没锁住链表之前就先在该数据块对应的表上加上TM锁,具体就是,内存上在TM resource上加入一个加什么锁和加锁的表等信息构成的数据结构的节点 ),并pin住它,之后释放掉锁住在整条LRU链表上的闩锁,这样其他进程就可访问该链表了。会话1的服务器进程pin住所要的数据块后,就先用行级锁锁住块上相关的数据行,接着释放pin在该数据块上的pin锁,此时其他进程就可访问该数据块了,之后就是修改这些数据行。假设在会话1的服务器进程释放pin在该数据块上的pin锁后,会话2的服务器进程(代表B操作)来pin住了该数据块,如果会话2的服务器进程所要修改的数据行中是其他进程(如A操作)锁住的数据行,则此时B操作整个就会被阻塞住的,直到那个进程提交之后锁在的数据行上的锁才会被释放掉。如果会话2的服务器进程所要修改的数据行都是没有被其他进程(如A操作)锁住的数据行,那会话2的服务器进程是可以执行的,即使此时如A操作针对的数据行还没有提交。这个就是平时我们看到的多用户并发(比如)更新(同一个表)同一个数据块上的不同行而不相互阻塞的过程,他们操作的是同一个数据块(不是一个数据块的两个副本),他们操作的是在buffer cache上的同一个数据块,也就是所谓的当前模式数据块。
从上述过程,可以看到加锁的过程都是在内存上的数据块上完成的,数据文件上的表上一般是没有锁存在的,除非内存上没有提交的脏块写入到数据文件中,不过实例恢复回滚时这些脏块都会被撤销从数据文件上。
转载:http://blog.csdn.net/haiross/article/details/17008867
逻辑IO及当前模式读和一致性读的总结杂记的更多相关文章
- ORACLE 物理读 逻辑读 一致性读 当前模式读总结浅析
在ORACLE数据库中有物理读(Physical Reads).逻辑读(Logical Reads).一致性读(Consistant Get).当前模式读(DB Block Gets)等诸多概念,如果 ...
- [MySQL] 一致性读分析
MySQL MVCC MySQL InnoDB存储引起实现的是基于多版本的并发控制协议---MVCC(Multi-Version Concurrency Control),基于锁的并发控制,Lock- ...
- MySQL 一致性读 深入研究
一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文档:http://dev.mysql.com/doc/refman/5.6/en/innod ...
- MySQL 一致性读 深入研究 digdeep博客学习
http://www.cnblogs.com/digdeep/p/4947694.html 一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文 ...
- ORACLE 一致性读原理记录
什么是一致性读? 一致性读指的是在从查询那一刻起,中间的变化不予理会. 举例说明 比如我有两个帐户A,B. A 有1000块,B有1000快.我查询的时候查询速度比较慢.中间A转500到B账户. 已经 ...
- UNDO三大作用与一致性读机制浅析
UNDO三大作用1.一致性读(consistent read)2.事务回滚(Rollback Transaction)3.实例恢复(Instance Recovery) 一致性读当会话发出一条SQL查 ...
- 初谈SQL Server逻辑读、物理读、预读
前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...
- SQL Server逻辑读、预读和物理读
SQL Server数据存储的形式 预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存 ...
- SQL Server 中的逻辑读与物理读
首先要理解逻辑读和物理读: 预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存再次去读 ...
随机推荐
- c++下基于windows socket的服务器客户端程序(基于UDP协议)
前天写了一个基于tcp协议的服务器客户端程序,今天写了一个基于UDP协议的,由于在上一篇使用TCP协议的服务器中注释已经较为详细,且许多api的调用是相同的,故不再另外注释. 使用UDP协议需要注意几 ...
- 几种常见的微服务架构方案——ZeroC IceGrid、Spring Cloud、基于消息队列、Docker Swarm
微服务架构是当前很热门的一个概念,它不是凭空产生的,是技术发展的必然结果.虽然微服务架构没有公认的技术标准和规范草案,但业界已经有一些很有影响力的开源微服务架构平台,架构师可以根据公司的技术实力并结合 ...
- R︱Yandex的梯度提升CatBoost 算法(官方述:超越XGBoost/lightGBM/h2o)
俄罗斯搜索巨头 Yandex 昨日宣布开源 CatBoost ,这是一种支持类别特征,基于梯度提升决策树的机器学习方法. CatBoost 是由 Yandex 的研究人员和工程师开发的,是 Matri ...
- 用前序和中序重建二叉树 python
程序实现了用二叉树的前序遍历序列和中序遍历序列重建二叉树,代码用python实现. 首先定义二叉树节点的类: class TreeNode: def __init__(self, x): self.v ...
- iOS中数组遍历的方法及比较
数组遍历是编码中很常见的一种需求,我们来扒一拔iOS里面都有什么样的方法来实现,有什么特点. 因为ios是兼容C语言的,所以c语言里面的最最常见的for循环遍历是没有问题的. 本文中用的数组是获取的系 ...
- Django:牛刀小试
牛刀小试 简谈Django 搭建开发环境 做一个简单的博客网站 写在开始之前: 要求:python基础.HTML基础.浏览器上网的基本原理 以下环境为:windows10专业版 64位 .Djan ...
- socket创建TCP服务端和客户端
看情况选择相对应的套接字*面向连接的传输--tcp协议--可靠的--流式套接字(SOCK_STREAM)*面向无连接的传输--udp协议--不可靠的--数据报套接字(SOCK_DGRAM) 在liun ...
- altium常用快捷键记录
选中一个网络的点和线ctrl+h: 翻转器件的层 鼠标拖动+L: 镜像器件 鼠标拖动+x: 查看单一层shift+s: 隐藏/查看某些器件ctrl+d:
- consul 几个方便使用的类库
consul 几个方便使用的类库 1. java https://github.com/OrbitzWorldwide/consul-client <dependency> < ...
- Python 函数-max()
max( x, y, z, .... )max() 方法返回给定参数的最大值,参数可以为序列.返回给定参数的最大值.x.y.z数值表达式. 实例 #!/usr/bin/python print &qu ...