1. 程式人生 > >Oracle 實用技巧之不知道密碼情況下 dblink 的遷移

Oracle 實用技巧之不知道密碼情況下 dblink 的遷移

在 Oracle 資料庫的運維過程中,常常會有一些特殊場景,需要我們靈活運用知識去解決問題,今天,就和大家一起探討分析一種情況。我們需要將一個數據庫從一個環境遷移到另外一個,但因為種種限制因素,只能採用資料匯入匯出的方式來進行。在梳理環境編寫遷移方案的時候,遇到了一個難題,資料庫裡有大量的 dblink,大家知道這些 dblink 是在使用的,但是沒有人知道密碼。下面,我們使用模擬環境來表達分析解決過程。

資料庫版本:


資料庫連結:


知識點:當 GLOBAL_NAMES 引數設定為 TRUE 時,使用 DATABASE LINK 時,DATABASE LINK 的名稱必須與被連線庫的 GLOBAL_NAME 一致。有興趣的同學可以詳細參考老熊的部落格文章

http://www.laoxiong.net/database_link_global_names.html

在模擬環境中共有3資料庫連結,我們以 source 這個為例。首先,我們確定這個 dblink 是可用的:


這個時候,很多同學可能就想到了,既然資料庫連結 source 可以用,那就說明本地庫(9i,服務名 firefox)是知道訪問遠端庫(11g,服務名 source)時用到的使用者名稱和密碼的,那麼 Oracle 會把它存在哪裡呢?難道是 dba_db_links 的其它列?我們一起來看看:


owner 列儲存 dblink 的所有者,值 public 代表是公共的;

db_link 列儲存 dblink 的名字;

username 列儲存 dblink 訪問遠端庫的使用者名稱;

host 列儲存 dblink 遠端庫的連線字串,或者本地服務名;

create 列儲存列 dblink 的建立時間;

dba_db_links 中對於 dblink 以哪個使用者訪問哪個庫都做了詳細的儲存,但就是沒有密碼資訊。到這裡我們不要失望,因為我們知道所有的資料字典其實都不是真正的表格,而是基於內部表的一系列檢視。我們去看看 dba_db_links 的定義:


知識點:其實資料字典嚴格的名字應該叫資料字典檢視,它提供了資料庫的一些系統資訊,資料字典是基於資料字典基表(也叫內部表,以$結尾)所建立的一系列檢視,資料字典檢視主要包括三種類型: user_xxx,all_xxx 和 dba_xxx。

原來 dba_db_links 的資料來自於 link$ 和 user$ 兩個內部表,那麼密碼會不會在這兩個表裡儲存?我們去看看它們的結構:

知識點:內部表,sys 使用者下以$結尾的一系列表,是資料庫核心的組成部分,使用者只能在上面執行查詢操作,其維護和修改是系統自動完成的,對其的不當操作可能會造成資料庫宕機、甚至永久性損壞。

在 link$ 和 user$ 中我們發現都有一個 password 欄位,那麼哪一個是我們要找的 dblink 的密碼呢?我們先來看看其中的內容:

內容太多,只選取相關的部分。


我們發現 link$ 中的密碼以明文儲存,user$ 中的密碼以加密後的字串儲存。但到底哪個才是我們要找的密碼呢?其實 Oracle 在設計內部表時每個都有明確的作用和定義,其中 link$ 是用來儲存 dblink 相關資訊的(包括密碼),user$ 是用來資料庫本地使用者相關資訊的。

那麼現在我們就找到了資料庫連結 source 的密碼:tiger,再根據其它資訊,可以很快寫出其遷移重建語句:


知識點:在 10gR1 及之前的版本里,所有 dblink 的密碼都是以明文方式在 sys.link$ 中儲存,但是在 10gR2 及之後版本,Oracle 進行了改良,以加密方式儲存。

針對 10gR2 及之後版本,我們雖然不能直接取得密碼,但也可以通過更新內部表的方式來實現遷移。Oracle 對於直接修改內部表是嚴格禁止的,因為不當操作可能會造成資料庫宕機、甚至永久性損壞。因為 dblink 是資料庫裡比較獨立關聯性小的一個功能,因此我們才有可能採取這種方式。但即便如此,也要求在做好備份後,由經驗豐富掌握相關知識的工程師進行操作。

同樣,先來看看資料庫版本:


資料庫連結

還是以資料庫連結 source 為例,我們先測試其可用性:


接下來我們看看 sys.link$ 在 10gR2 及之後的表結構變化,並直接從其中查詢密碼:


與上面的9i對比,多了兩個列,其中 PASSWORDX 列就是用來儲存加密之後的密碼。


通過查詢我們發現,password 列雖然還在,但是內容為空,passwordx 列則儲存了加密之後的密碼。

我們可以通過 pl/sql dev 之類的工具,將 sys.link$ 的內容匯出為 sql 語句,每個 insert 語句對應一個 dblink 資訊。對匯出檔案進行編輯,保留我們需要遷移的 dblink 語句,刪掉其它。


在目標環境上以 sys 身份執行指令碼,然後對遷移後的 dblink 進行測試。



至此,完成了在不知道密碼情況下對 dblink 的遷移。另外,這裡再插入個小知識點:還有另外的技巧能夠簡單快速的實現這個事情,使用 dbms_metadata 包,抽取 dblink 的 ddl,會生成包含加密密碼的建立語句,在目標庫跑這個 ddl,也能實現建立。但是這個方法,在11.2.0.4版本及以後被 Oracle 禁用了,不再支援。所以這裡就不演示啦。那個 ddl 抽取出來的樣子,基本是這樣:


因為是用加密字串表達密碼,所以比平時多了個 values 關鍵字。

最後,再談談本文的編寫思想,其實就是蓋老師推崇的學習方法:“由點及面,窮就根本”。

當遇到一個問題後,一定是深入下去,窮究根本,這樣你會發現,一個簡單的問題也必定會帶起一大片的知識點,如果你能對很多問題進行深入思考和研究,那麼在深處,你會發現,這些面逐漸接合,慢慢的延伸到 Oracle 的所有層面,逐漸的你就能融會貫通。這時候,你會主動的去嘗試全面學習 Oracle,掃除你的知識盲點,學習已經成為一種需要。由實踐觸發的學習才最有針對性,才更能讓你深入的理解書本上的知識,正所謂:"紙上得來終覺淺,絕知此事要躬行",實踐的經驗於我們是至為寶貴的。與同學們共勉