前几天,论坛上的同行在讨论SELECT语句的元数据,动态取样和读一致性导致的一致性读和递归问题,今天有时间,就试着进行了测试,本人测试环境如下:
win7_64+Oracle11.2.0.4_64
那么,下面就说下测试过程:
1、元数据:当用户向数据库发出SELECT语句后,在解析和执行过程中,肯定是需要读取SELECT相关的元数据,这样,SELECT的统计数据中就会包含递归操作,做这个测试的前提是要把其他因素排除掉(动态取样,一致性读):
session1:
session2:
由上可见,在表没有任何数据块分配和取样的前提下,SELECT语句解析执行过程中,还是发生了递归,而且期间产生的读取,并未计入该语句的统计数据中。
2、读一致性:当我们往表里插入数据后,表分配了一些数据块,在没有动态取样情况下,发生了读一致性,发生的一致性读的数量等于需要读取的表的数据块和undo块的数量。
session1:
session2:
这里,为什么说cr的数量等于表数据块加上undo数据块呢?因为当session1中提交时,session2中的cr数量要少很多,那时,在没有其他并发修改操作的情况下,就不再需要读取undo块,大家有时间可以测试下,这里不再贴出测试过程。
3、动态取样:在表数据量不变和发生动态取样的情况下,当有动态取样发生时,cr和无动态取样发生时有较大差别,这说明动态取样虽然导致了递归的发生,但其中发生的cr也被计入了查询语句的统计数据中。
session2:
以上我们通过hint强制查询语句在解析运行时发生level为8的动态取样,可见发生了递归操作,而cr也有相应增加,而当我们再次运行该语句时,因为不需要再次解析,所以,也就没有了动态取样,因此,此时cr有所降低。
4、redo:我们还注意到,在session1中往表中插入数据但没提交的情况下,session2中select该表时,会产生redo数据,并且,经过进一步测试,这些redo数据也确实写入了redo log file中。
那么,这个redo size是怎么产生的呢?也许有人会说延迟块清除,但是,这里session1中插入的数据并未提交,而且,每次执行select语句,都会有几乎等量的redo产生,这和延迟块清除不同。延迟块清除只有在数据提交后,第一次查询时会产生redo数据,再次查询就不会发生,而且产生的redo也不会这么多。仔细想想,唯一的可能就是,在利用undo数据构造cr块的过程中,也记录了对这些db block的redo数据,并写入了redo log file中,目的就是万一系统此时发生崩溃,再次重启时,通过redo log file中的redo数据重构内存中的这些cr块。
以上为个人测试和临时的想法,仅供大家参考。
原文地址:https://www.cnblogs.com/lhdz_bj/p/9054680.html