(轉)ORACLE中SID和SERVICE_NAME的區別


背景:之前一直分不清plsql和程序中配置文件url之間的連接,想當然的認為service_name 和jdburl后面的實例相對應,直到出錯的這一天,通過這篇博客,徹底掃除了盲點。

1 問題

1.1 問題描述

plsql的tnsnames.org中的數據源是這么配置的

應用程序中的配置文件是這么配置的:

啟動程序,報錯:

Caused by: oracle.net.ns.NetException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor

 這里我只是單純的將 “”:“” 后面的名稱和service_name 對應上去,完全是想當然的做法。

1.2 問題解決

這個問題同事首先給我的解決方案是,將url后面的sjjdb 改為sjjdb1,這個不是數據庫的實例名嗎,我雖然不相信,但是改完后確實能夠正常啟動程序,百思不得其解啊。

於是,我在網上找到了查看數據庫sid_name 的方法

例如:jdbc:oracle:thin:@192.168.0.58:1521:ORCL
最后的ORCL就是sid_name

附:
察看數據庫中當前的sid的方法:

SQL> select INSTANCE_NAME from v$instance;

 

INSTANCE_NAME

----------------
hasl

然后,我就在plsql中執行了一遍命令,發現:

我擦,我的sid_name 居然是sjjdb2,我去修改程序中的配置文件為connection.url=jdbc:oracle:thin:@168.33.131.19:1521:sjjdb2  

非常6,程序跑起來了。這時候我在想,sid_name和service_name之間到底是個什么關系呢?

於是就有了第二章的終極解決方案,茅塞頓開的感覺!

2 徹底明白sid_name和service_name之間的區別

2.1 頓悟

ps:RAC,全稱real application clusters,譯為“實時應用集群”, 是Oracle新版數據庫中采用的一項新技術,是高可用性的一種,也是Oracle數據庫支持網格計算環境的核心技術。

先來講一個小故事,2015年6月份,有個客戶遷移了數據庫,由單實例數據庫變成了RAC。Java應用程序出現了無法連接數據庫的情況,但是PL/SQL能連接上數據庫(我就是的)。

由於項目比較龐大,雖然在半夜切換的,但是也不能接受長時間的業務停頓。當時,我對Oracle技術也只是略知皮毛。在咨詢過公司研發后,他們給我的建議是:

參考PL/SQL的連接參數,將spring中jdbc連接的url由jdbc:oracle:thin:@10.2.0.2:1521:orcl改為jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 10.2.0.2)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = orcl))),結果問題解決了,當時我挺佩服公司研發的。

現在看來,這個並不是最佳的解決方案,下面通過講解SID和SERVICE_NAME的區別,我將給出更佳的解決方案。

        在講解SID和SERVICE_NAME之前,先說一下實例。實例是操作系統中訪問數據庫所需要的一系列的進程和內存的集合。即使沒有任何數據文件,實例也可以啟動。但是要想訪問數據庫,必須把數據庫文件加載進實例中。

實例和數據庫的區別可以簡單概括為:實例是臨時的,它只在相關的進程和內存集合存在時存在,而數據庫是永久的,只要文件存在它就存在。一個實例只能對應一個數據庫,但是一個數據庫可以由多個實例對應(如RAC)。RAC就是多個實例同時打開一個數據庫文件的系統,在結構上是多台機器,每台機器運行一個實例,每個實例都打開同一個數據庫 (這個是用磁盤共享技術實現的),這些實例之間需要同步高速緩存,這樣保證多個實例是完全一致的,不會相互沖突乃至覆蓋。

       SID即INSTANCE_NAME是用來唯一標示實例的。SERVICE_NAME是oracle8i新引進的,8i之前,一個數據庫只能由一個實例對應,但是隨着高性能的需求,並行技術的使用,一個數據庫可以由多個實例對應了,比較典型的應用如RAC。為了充分利用所有實例,並且令客戶端連接配置簡單,ORACLE提出了SERVICE_NAME的概念。該參數直接對應數據庫,而不是某個實例。

      了解了SID和SERVICE_NAME之后,我突然覺得前面故事中使用的解決方案並不是最佳的解決方案,因為SERVICE_NAME的出現就是為了應對並發技術,簡化客戶端連接配置。通過SERVICE_NAME應該能找到更好的解決方案。通過查找JDBC幫助得知JDBC連接ORACLE的方法由三種:

格式一:jdbc:oracle:thin:@//<host>:<port>/<service_name>
格式二:jdbc:oracle:thin:@<host>:<port>:<SID> 
格式三:jdbc:oracle:thin:@<TNSName> 

       不難看出,故事中使用RAC之前,JDBC是使用格式二連接的,使用RAC后實例增多了,SID已經不唯一,格式二已經無法完全利用所有資源。研發參考PL/SQL的連接方法剛好碰巧使用了格式三。(這不是直接將數據源搞上去嗎,low啊)因為java應用服務器跟數據庫服務器是分離的,應用服務器上沒有oracle的服務端以及客戶端。雖然解決方案中沒有使用TNSName,但是使用了TNSName的連接描述,效果是一樣的。既然JDBC有三種連接方案,我們不妨再看一下第一種方案。

再加上前面的講解內容,我想大家已經都知道故事中的問題該怎么修改了,只要改成jdbc:oracle:thin:@//10.2.0.2:1521/orcl就可以了,而且這種格式也支持單實例數據庫。這也是ORACLE在8i之后增加SERVICE_NAME的初衷。

       通過這個故事,我們可以看到,只有充分了解了ORACLE的知識,才能更好的使用ORACLE技術。

so,最后的的問題解決方案就是通過加 /解決的:

connection.url=jdbc:oracle:thin:@168.33.131.19:1521/sjjdb

 2.2 引申

oracle中的service_name 是什么?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM