天天看點

關于ORACLE通過file_id與block_id定位資料庫對象遇到的問題的一點思考

在ORACLE中,我們可以通過file_id(file#)與block_id(block#)去定位一個資料庫對象(object)。例如,我們在10046生成的trace檔案中file#=4 block#=266 blocks=8,那麼我可以通過下面兩個SQL去定位對象

SQL 1:此SQL效率較差,執行時間較長。

SQL 2:此SQL效率較快(ORACLE 10g 中沒有CACHEHINT字段)

下面通過一個例子來示範一下,詳情如下所示

<a href="http://images2015.cnblogs.com/blog/73542/201703/73542-20170319001642932-2057321319.png"></a>

昨天在群裡讨論一個關于空閑塊的問題時,我驗證測試時,發現一個奇怪的現象,使用下面SQL找到了一個最大空閑塊。

然後我發現使用上面兩個SQL查不到對應的對象。如下截圖所示:

<a href="http://images2015.cnblogs.com/blog/73542/201703/73542-20170319001643979-790884983.png"></a>

後面查了一下資料,發現在Oracle Database 10g引入了資源回收筒功能後,會将資源回收筒(RECYCLEBIN$)中的空間計算為自由空間,加入到dba_free_space字典中。在$ORACLE_HOME/rdbms/admin/catspace.sql中,你可以找到視圖DBA_FREE_SPACE的定義,腳本如下:

ORACLE 10g中DBA_FREE_SPACE的定義:

ORACLE 11g中DBA_FREE_SPACE的定義:

那麼在DBA_FREE_SPACE中找到的最大空閑塊是否很有可能就是資源回收筒中曾經的一個對象呢?那麼我們來測試看看。

<a href="http://images2015.cnblogs.com/blog/73542/201703/73542-20170319001644979-285874004.png"></a>

如上所示,清空資源回收筒對象後,你會發現X$KTFBFE中多了一條記錄,KTFBFEFNO 和 KTFBFEBNO分别為97 ,113025, 這個值顯然就是删除對象TTT曾經的FILE_ID(97)和BLOCK_ID(113025)值。

另外,在測試過程中發現,并不是每次的測試結果都是在X$KTFBFE中多一條記錄,有時候記錄不會變化,但是X$KTFBFE中某條記錄的KTFBFEBNO會變化,而這個變化跟清空資源回收筒是有關系的。如下案例所示:

<a href="http://images2015.cnblogs.com/blog/73542/201703/73542-20170319001645901-374508706.png"></a>

如上所示,在清空資源回收筒的表以後,你查詢X$KTFBFE,就會發現其中一條記錄的KTFBFEBNO的變化了,它們的關系為

1280 -1152 = 128

是以,你會看到KTFBFEBNO的值從1280變為了128了。此時你檢視DBA_FREE_SPACE,就會看到這樣的情況。是以當清空資源回收筒時,有可能是資料庫将這個表的空間标記為了空閑塊,也有可能是将這個空閑塊合并到其它空閑塊去了。

參考資料:

<a href="http://www.cnblogs.com/princessd8251/p/3868487.html">http://www.cnblogs.com/princessd8251/p/3868487.html</a>

<a href="http://dbzone.iteye.com/blog/1020219">http://dbzone.iteye.com/blog/1020219</a>