2009年12月11日 星期五

ORA12514 TNS監聽器目前不知道連線描述區中要求的服務

先描述一下筆者所在的情況:

Client: windows 7

Server : 任一Linux主機, 上面有裝Oracle任一軟體.

由於通常是在Linux上建立Oracle, 所以在Client常要連線Server.

目前筆者較常使用的是PL/SQL DEVELOPER 這套軟體.

至於要怎樣連線Server, 請參閱筆者其他文章.

—————————————————————————————–

問題描述:

由於Linux常會改寫主機名字, 所以會導致PL/SQL DEVELOPER無法連線.

ORA-12514: TNS: 監聽器目前不知道連線描述區中要求的服務.

主要是因為Client下的tnsnames.ora設定的問題.

先查詢一下Linux主機名稱

[root ~ ]#vi /etc/hosts

…..

127.0.0.1 localhost.localdomain localhost

……

之後在tnsnames.ora

將service更改為完整的sid+domainname

舉例如下:

orcl =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl.localdomain)
)
)

這樣就可以了.

這個問題的原因是因為client連線時server無法分辨真正要連線的SID Name(Service Name)所造成的。

原文出處:

http://tw.myblog.yahoo.com/database995/article?mid=812&prev=813&next=-1

開機時自動執行ORACLE11GR2

1. 建立一個稱為oracledb的Shell Script,讓開機的時候自動執行它

[root@localhost bin]# pwd
/u01/app/oracle/product/11.2.0/dbhome_1/bin
[root@localhost bin]$ vi oracledb

2.檔案內容如下:

#!/bin/bash
export JAVA_HOME=/opt/jdk1.6.0_17
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1

(筆者: ORACLE_HOME 應改用絕對路徑, 用變數表是似乎不會正確執行SCRIPT)

export ORACLE_SID=orcl
export ORACLE_TERM=xterm
export TNS_ADMIN=$ORACLE_HOME/network/admin
export ORACLE_OWNR=oracle

#NLS_LANG=”TRADITIONAL CHINESE_TAIWAN”.ZHT16BIG5;export NLS_LANG
export NLS_LANG
#LC_CTYPE=zh_TW.Big5; export LC_CTYPE
export LC_CTYPE
#LC_ALL=zh_TW.UTF8; export LC_ALL
export LC_ALL
#LANG=zh_TW.Big5; export LANG
export LANG

export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
export PATH=$JAVA_HOME/bin:$ORACLE_HOME/bin:$PATH:$HOME/bin

if [ ! -f $ORACLE_HOME/bin/dbstart -o ! -d $ORACLE_HOME ]
then

echo “Oracle startup: cannot start”
exit 1
fi

case “$1″ in
start)
# Oracle listener and instance startup
echo -n “Starting Oracle: “
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/lsnrctl start”
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/dbstart $ORACLE_HOME”
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/emctl start dbconsole”

su oracle -c “/u01/app/oracle/product/11.2.0/dbhome_1/bin/emctl start dbconsole”

touch /var/lock/oracle
echo “OK”
;;
stop)
# Oracle listener and instance shutdown

echo -n “Shutdown Oracle: “
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/lsnrctl stop”
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/dbshut $ORACLE_HOME”
su $ORACLE_OWNR -c “$ORACLE_HOME/bin/emctl stop dbconsole”
rm -f /var/lock/oracle
echo “OK”
;;
reload|restart)
$0 stop
$0 start
;;
*)
echo “Usage: `basename $0` start|stop|restart|reload”
exit 1
esac

exit 0

3.執行這程式

[root@localhost bin]# ./oracledb start
(如果執行不成功, 請檢查設置路徑地方是否正確)

4.看一下記憶體中oracle相關程序

[root@oracle db_1]# ps aux | grep oracle

5.編輯開機自動執行設定檔/etc/rc.local

root@lu-desktop:~# vi /etc/rc.local

加入一行

/u01/app/oracle/product/11.2.0/dbhome_1/bin/oracledb start

然後重新啟動 (在全藍色畫面會花些時間)

編輯 /etc/oratab,
將 orcl:/u01/app/oracle/product/11.2.0/dbhome_1:N
改成 orcl:/u01/app/oracle/product/11.2.0/dbhome_1:Y
(改成Y)
代碼:
root@lu-desktop:~# reboot

再用ps aux | grep oracle檢查

代碼:
[root@oracle db_1]# ps aux | grep oracle

如果有出現類似下面的訊息,表示emctl仍在啟動中 ,請再等等

代碼:
root 5688 0.3 0.1 4888 1232 ? S 09:49 0:00 su oracle -c /u01/app/oracle/product/11.1.0/db_1/bin/emctl start dbconsole
oracle 5689 11.3 0.1 4484 1224 ? Ss 09:49 0:00 /bin/sh -f /u01/app/oracle/product/11.1.0/db_1/bin/emctl start dbconsole
oracle 6101 0.0 0.2 6072 2396 ? R 09:49 0:00 /u01/app/oracle/product/11.1.0/db_1/perl/bin/perl /u01/app/oracle/product/11.1.0/db_1/bin/emctl.pl start dbconsole

確認啟動完成後,再用瀏覽器連到 Oracle 的管理介面看看

代碼:

[root@oracle db_1]# firefox https://localhost:1158/em &

停止oracle服務-簡易流程

Stopping Oracle Services

● Stop isqlplusctl

oracle> isqlplusctl stop

在11gR2

it is deprecated……囧>

● Stop EM

oracle> emctl stop dbconsole

● Stop Database

oracle> sqlplus -S /nolog << ENDSQL
connect / as sysdba
shutdown immediate
exit
ENDSQL

● Stop Listener
oracle> lsnrctl stop

開啟oracle服務-簡易流程

Starting Oracle Services

● Start Listener

oracle> lsnrctl start

● Start Database

oracle> < span style="color: rgb(255, 0, 0);" >sqlplus -S /nolog << ENDSQL
connect / as sysdba
startup
exit
ENDSQL < /span>

● Start EM(Enterprise Manager)

oracle> emctl start dbconsole

● Start isqlplusctl

oracle> isqlplusctl start

在11gR2

it is deprecated……囧>

出處: http://forums.oracle.com/forums/thread.jspa?messageID=3877207&tstart=0

oc4j-configuration-issue

先決條件: 注意我的主機名稱是localhost.localdomain

當測試 emctl (Enterprise Manager Control是Oracle的Web管理介面)

出現以下的訊息時….
代碼:

[oracle@oracle ~]$ emctl start dbconsole
OC4J Configuration issue. /u01/app/oracle/product/11.1.0/db_1/oc4j/j2ee/OC4J_DBConsole_oracle_ORCL not found.

發現無法啟動….Q__Q , 解決方法如下

[oracle@localhost j2ee]$ pwd
/u01/app/oracle/product/11.2.0/dbhome_1/oc4j/j2ee

[oracle@localhost j2ee]$ cp -rf OC4J_DBConsole_localhost_orcl OC4J_DBConsole_loc alhost.localdomain_orcl

對!主要就是新增一個檔案…讓oracle使用,再開一次, 發現

EM Configuration issue. /u01/app/oracle/product/11.2.0/dbhome_1/localhost.locald

方法類似, 解法如下:

[oracle@localhost dbhome_1]$ pwd
/u01/app/oracle/product/11.2.0/dbhome_1
[oracle@localhost dbhome_1]$ cp -rf localhost_orcl localhost.localdomain_orcl

在CENTOS5.4安裝ORACLE11GR2

本篇主要是參照以下兩篇文章與其他網路文章加以修改而成:

http://forum.icst.org.tw/phpbb/viewtopic.php?f=21&t=16411&start=0&sid=866700eee479d130d126967c3160e7f4

http://www.oracle.com/technology/pub/articles/smiley-11gr1-install.html

1. 先裝好CentOS5.4

注意:

A.記得裝好後要先關閉SELinux

B. oracle 需要有1G以上的實體記憶體(VM中建議1100MB)

C. 建議2GB(或2倍以上的實體記憶體)的SWAP空間

D.安裝必須套件 (這全部是同一行)

[root@oracle ~]# yum -y install binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc-common glibc-devel glibc-headers libaio libaio-devel libgcc libstdc++ libstdc++-devel make sysstat unixODBC unixODBC-devel

以及

[root@oracle ~]#yum install pdksh-5.2.14

E.由於考量日後還要繼續新增ORACLE的database大小

所以建議主硬碟為10G + 2G的SWAP +1G實體記憶體(建議是1100MB)

用VM時,假設掛載上的硬碟為/dev/sdb , 掛載目錄設為 /u01

掛載方法請參照筆者網誌上的另一篇文章.

F.建立oracle帳戶, 使用第二步驟建立, 此帳戶將用來開啟與管理ORACLE所有設定(不一定要給予ROOT權限)

G.下載下來的oracle安裝檔,必須解壓縮在同一目錄, 如:

unzip linux_11gR2_database_1of2.zip
unzip linux_11gR2_database_2of2.zip
cd database
./runInstall

2.用root執行

# groupadd oinstall (建立oinstall 群組,安裝程序那邊會用到)
# groupadd dba (建立dba群組,安裝程序那邊會用到)

# useradd -g oinstall -G dba oracle
# passwd oracle

# mkdir -p /u01/app/oracle/product/

為了使以上的設定變更到另一磁碟, ex: /dev/sdb, 請先將/dev/sdb掛載成/u01

# chown oracle:oinstall /u01/app/oracle (之後軟體安裝的路徑)

#mkdir -p /u01/app/oracle/product/

#chmod -R 775 /u01

把/u01給oracle使用

#chown -R oracle:oinstall /u01

(這段要執行, 不然之後安裝程序要回來改權限)

3. 改用oracle登入, 這邊是希望之後以oracle就執行與管理這項服務, 不要被其他帳戶混淆.(盡可能由單一用戶執行單一服務, 也盡量不要用root開啟服務)

並改寫oracle 的 .bash_profile 部分如下

export JAVA_HOME=/opt/jdk1.6.0_17
export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=orcl
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1
export ORACLE_TERM=xterm
export TNS_ADMIN=$ORACLE_HOME/network/admin
#NLS_LANG=”TRADITIONAL CHINESE_TAIWAN”.ZHT16BIG5;export NLS_LANG
export NLS_LANG
#LC_CTYPE=zh_TW.Big5; export LC_CTYPE
export LC_CTYPE
#LC_ALL=zh_TW.UTF8; export LC_ALL
export LC_ALL
#LANG=zh_TW.Big5; export LANG
export LANG
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
export PATH=$JAVA_HOME/bin:$ORACLE_HOME/bin:$PATH:$HOME/bin

4.用root修改下面參數:

修改核心參數:

Add the following lines to /etc/sysctl.conf

32位元的設定

rnel.shmall=2097152
kernel.shmmax=552599552——half the size of physical memory(一半的記憶體, 以1gRAM來說, 會是552599552 )
kernel.shmmni=4096
kernel.sem=250 32000 100 128
net.core.rmem_default = 262144
net.core.wmem_default = 262144
fs.file-max = 6815744
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
fs.aio-max-nr = 1048576
net.ipv4.ip_local_port_range = 9000 65500

64位元的

kernel.shmall=2097152
kernel.shmmax=552599552
kernel.shmmni=4096
kernel.sem=250 32000 100 128
net.core.rmem_default = 262144
net.core.wmem_default = 262144
fs.file-max = 6815744
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
fs.aio-max-nr = 1048576
net.ipv4.ip_local_port_range = 9000 65500

讓設定生效, 改完核心參數之後, 一定要執行, 使設定生效!!!!

[root@oracle ~]# /sbin/sysctl –p

為oracle用戶設置Shell限制,

Add the following lines to /etc/security/limits.conf

oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536

修改/etc/pam.d/login

Add the following lines to /etc/pam.d/login

session required pam_limits.so

如果使用bash Shell,修改/etc/profile

Add the following lines to /etc/profile

if [ \$USER = "oracle" ]; then
if [ \$SHELL = "/bin/ksh" ]; then
ulimit -p 16384
ulimit -n 65536
else
ulimit -u 16384 -n 65536
fi
umask 022
fi

5. 進入解壓縮後產生的database資料夾, 執行:

[oracle@oracle database]$ ./runInstaller

6.依照以下步驟開始安裝:

Step1:

Step2:

Step3:

Step4a: 這邊會改設定!!!請看下一張圖

Step4b:

注意為了日後編碼問題, 使用ALU32UTF8字元集

同時要注意,OSDBA群組為dba.

Step5:

在步驟五中, 要注意oraInventory群組名稱為: oinstall

Step8a:

Step8b:

Step8c:

Step9:

在-oracle-中實作自動遞增欄位-oracle-auto_increment

在 MySQL 的資料庫中,有一種方便的欄位型態 AUTO_INCREMENT,有自動遞增的功能,多半使用於 ID 欄位,作為 PRIMARY KEY。類似自動遞增的功能,在 MSSQL 有 Identity,甚至連 MS Access 都有個 AutoNumber 都可以很方便的去宣告使用。

人沒有完美的,資料庫同樣也是。功能強大的 Oracle 卻沒有內建這樣方便的功能欄位,從我開始接觸 Oracle 以來,一直覺得遺憾與不解的,幾年下來,看起來原廠是沒去 implement 這樣的功能欄位的打算,是令人有些扼脕。但是,我們還是有機會用拼拼湊湊的方式,搞一個那樣子的欄位出來。

Step1. 建立 Table:

CREATE TABLE tbl (
id NUMBER PRIMARY KEY,
val VARCHAR2(30)
);

Step2. 建立 Sequence:




CREATE SEQUENCE tbl_id_seq;




完成這兩步,我們就已經有了 INCREMENT (遞增)的功能了!

  1. -- 新增紀錄

  2. INSERT INTO tbl (id, val) VALUES (tbl_id_seq.nextval, 'row1_value');

  3. INSERT INTO tbl (id, val) VALUES (tbl_id_seq.nextval, 'row2_value');

  4. -- 撈出資料

  5. SELECT * FROM tbl;

  6. /**

  7. 輸出結果為:

  8. ID VAL

  9. ---------- ------------------------------

  10. 1 row1_value

  11. 2 row2_value

  12. */



那,怎麼做到 AUTO (自動)呢?是的,就是用 Trigger!
Step3. 建立 Trigger:


  1. CREATE OR REPLACE TRIGGER tbl_trg

  2. BEFORE INSERT ON tbl

  3. FOR EACH ROW

  4. BEGIN

  5. IF :new.id IS NULL THEN

  6. SELECT tbl_id_seq.nextval INTO :new.id FROM dual;

  7. END IF;

  8. END;



這樣,AUTO_INCREMENT 都具備了,大功告成了!

  1. -- 新增紀錄

  2. INSERT INTO tbl (val) VALUES ('row3_value');

  3. INSERT INTO tbl (id, val) VALUES (null, 'row4_value');

  4. -- 撈出資料

  5. SELECT * FROM tbl;

  6. /**

  7. 輸出結果為:

  8. ID VAL

  9. ---------- ------------------------------

  10. 1 row1_value

  11. 2 row2_value

  12. 3 row3_value

  13. 4 row4_value

  14. */



但是,如果就這樣結束,那本篇介紹的,不過是台兩光的三輪拼裝車。

這種欄位,有極大機率 在實作情況下,需要即時取回剛剛新增那筆紀錄的 id 資料。在 MySQL 中有個 LAST_INSERT_ID() 來取得同一個連線 Session 中 AUTO_INCREMENT 所得到的 ID。那 Oracle 怎麼實作這功能?直接跟 Sequence 要它當時的值?如果在多人存取的環境下,這樣的做法能保證跟 Sequence 要到的那個數字,是你的還是後面又有人塞資料時候拿到的!?

INSERT ... RETURNING ... 是我們要的解答:

  1. DECLARE

  2. i NUMBER;

  3. BEGIN

  4. INSERT INTO tbl (val) VALUES ('row5_value') RETURNING id INTO i;

  5. DBMS_OUTPUT.put_line('id : ' || i);

  6. FOR rec IN (SELECT id, val FROM tbl)

  7. LOOP

  8. DBMS_OUTPUT.put_line('rec.id = ' || rec.id ||

  9. '; rec.val = ' || rec.val);

  10. END LOOP;

  11. /**

  12. 輸出結果為:

  13. id : 5

  14. rec.id = 1; rec.val = row1_value

  15. rec.id = 2; rec.val = row2_value

  16. rec.id = 3; rec.val = row3_value

  17. rec.id = 4; rec.val = row4_value

  18. rec.id = 5; rec.val = row5_value

  19. */

  20. INSERT INTO tbl (id, val) VALUES (NULL, 'row6_value') RETURNING id INTO i;

  21. DBMS_OUTPUT.put_line('id : ' || i);

  22. FOR rec IN (SELECT id, val FROM tbl)

  23. LOOP

  24. DBMS_OUTPUT.put_line('rec.id = ' || rec.id ||

  25. '; rec.val = ' || rec.val);

  26. END LOOP;

  27. /**

  28. 輸出結果為:

  29. id : 6

  30. rec.id = 1; rec.val = row1_value

  31. rec.id = 2; rec.val = row2_value

  32. rec.id = 3; rec.val = row3_value

  33. rec.id = 4; rec.val = row4_value

  34. rec.id = 5; rec.val = row5_value

  35. rec.id = 6; rec.val = row6_value

  36. */

  37. END;



這做法雖然是輛拼裝車的,但是還不是太難使,倒也堪用。
不過,如果有機會能官方內建,總比建這建那拼拼湊湊的好!
難道,像人生一樣,就是要有那麼點遺憾,才是人生嗎?XD

原文出處:

http://abu.tw/2008/06/oracle-autoincrement.html