เป็นอาทิตย์ที่ยากลำบากมากช่วงหนึ่งแต่ก็ผ่านมาได้ จนต้อง blog ไว้เผื่อมีประโยชน์กับ ตัวเองและคนอื่น :)
กว่าสองเดือนที่ผมได้เขียน Server สำหรับการทำ Semi-Realtime transaction processing server (ตั้งชื่อให้มันยากๆ ไปงั้นแหละ) โดยใช้ Erlang ในการพัฒนา โจทย์ก็คือต้องเก็บ transaction ที่ส่งผ่านเข้ามาเป็น XML จากนั้น Encode XML เก็บเข้า Oracle แล้ว Archive XML ไว้ใน Document Base สักตัว (ผมเลือกใช้ MongoDB)
แรกๆ ใช้ Erlang OCI (Oracle Call Interface) ก็ดูดี แต่พบว่า มีปัญหาหลายส่วน จึงตัดสินใจเปลี่ยนจากการ code โดยการ generate SQL statement ใน Erlang แล้วยิง Statement ผ่าน OCI มาเป็นการเรียกน Stored Procedure ผ่าน ODBC แทน
Code เสร็จแล้ว ถึงเวลาต้อง Deploy แล้ว... ผมเลือก Debian 7.4 ที่ต้องติดตั้งเพิ่มก็มี
- Erlang (ใช้ R16B03-1) ติดตั้ง package เพิ่มเติมตามนี้
- sudo apt-get install build-essential libncurses5-dev m4
- sudo apt-get install openssl libssl-dev
- sudo apt-get install unixodbc-dev
- git
- mongodb (ใช้ repo ของ 10 gen : http://docs.mongodb.org/manual/tutorial/install-mongodb-on-debian/ )
- และ ODBC
ปัญหาก็คือ Instance Client ของ Oracle (download จาก http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html ) support .rpm ผมใช้ alien แปลง .rpm เป็น .deb ซึ่งก็ติดตั้งได้ แต่ไม่สามารถ connect กับ server ได้ เลยเปลี่ยนไปจาก Debian ไปเป็น CentOS แทน เพราะไม่รู้ว่า ปัญหาจริงๆ คืออะไร
ย้ายบ้านมา CentOS (ขั่วคราว)
ข้อดีของ VMWare คือตรงนี้แหละ อยากลอง Distro ไหนง่ายนิดเดียว
ติดตั้ง CentOS เสร็จ ไม่ต้องคิดมาก download rpm จาก Oracle's instance-client site page มาเลย ไม่ต้องเยอะเอาแค่
- oracle-instantclient12.1-basic-12.1.0.1.0-1.x86_64.rpm
- oracle-instantclient12.1-sqlplus-12.1.0.1.0-1.x86_64.rpm
- instantclient-odbc-linux.x64-12.1.0.1.0.zip
แล้ว $sudo rpm -ivh oracle-instanceclient12.1-basic-12.1.0.1.0-1.x86_64.rpm ไปก่อน ตากด้วย $unzip instantclient-odbc-linux.x64-12.1.0.1.0.zip แล้ว copy libsqora.so.12.1 ที่ได้จากการ unzip ไปไว้ที่ /usr/lib/oracle/12.1/client64/lib
จากนั้นติดตั้ง unixODBC
$sudo yum install unixODBC
export environment
$ export ORACLE_HOME=/usr/lib/oracle/12.1/client64
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
$ export TWO_TASK=//xxx.xxx.xxx.xxx:1521/listener
(note : listener ต้องตรงกับ server นะครับ)
note : ผมสร้าง oracle.conf ที่มี
/usr/lib/oracle/12.1/client64/lib
หนึ่งบรรทัด ไว้ที่ /etc/ld.so.conf.d แล้วเรียก
$ sudo ldconfig
หนึ่งที ด้วย :D
จากนั้นก็ไป copy tnsnames.ora มาจาก server (server ผมเป็น windows 7) เอามาจาก c:/app/[username]/product/11.2.0/dbhome_1/network/admin (ลองไล่ๆ ดูนะครับ แต่ละเครื่องไม่เหมือนกัน อยู่ที่การติดตั้ง)
ผมแก้ tnsnames.ora นิดหน่อยครับ เหลือแต่
_SID_NAME_ =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)
(HOST = xxx.xxx.xxx.xxx)
(PORT = 1521)
)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = _SID_NAME_)
)
)
_SID_NAME_ ตรงกับ SID ที่ server
ไปตามอ่านใน oracle document พบว่าให้สร้าง tnsnames.ora ไว้ที่ $ORACLE_HOME/network/admin ก็ไปสร้างไว้ตรงนั้นตามเอกสาร
จากนั้นสร้าง ODBC's drive profile ใน /etc/odbcinst.ini
ตามนี้ครับ
[OracleODBC-12g]
Description = Oracle ODBC driver for Oracle 12g
Driver64 = /usr/lib/oracle/12.1/client64/lib/libsqora.so.12.1
FileUsage = 1
Driver Logging = 7
เน้นนะครับ : Driver64 เพราะผมลง x86_64 ถ้า google จะเจอแต่ Driver เฉยๆ (งมตั้งนาน)
แล้วชี้ไปที่ libsqora.so.12.1 ที่ได้จากตอนที่เรา unzip ตอนต้นๆ
จากนั้นสร้าง DSN ใน /etc/odbc.ini ตามนี้ครับ
[simple]
Driver = OracleODBC-12g
DSN = OracleODBC-12g
ServerName = _SID_NAME_
UserID = _USER_
Password = _PASSWORD_
Note : Driver ต้องตรงกับที่เรากำหนดไว้ใน odbcinst.ini, ServerName ตรงกับ _SID_NAME_ ใน tnsnames.ora ส่วน _USER_ _PASSWORD_ ก็ตรงกับ oracle server ที่เราตั้งไว้
ทดสอบ....
ทดสอบ DSN ที่ส้รางขึ้นด้วย
$ isql simple
simple คือชื่อ DSN ที่เราสร้างขึ้นใน odbc.ini
ผลลัพท์
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
ผมเจอ error ไม่ต่ำกว่า 4-5 ตัว (แต่ละตัวทำเอามึน) เช่น
Error ORA-12154 : TNS:could not resolve the connect identifier specified
อันนี้ตำแหน่ง tnsnames.ora อยู่ผิดที่
Debug ด้วย Log
หากพบปัญหาตอนเรียก isql ให้ใส่ -v เพื่อดู ORA error number แล้ว google error number ดู ถ้ายังไม่ได้อีก ผมใช้ strace ตามนี้
$ strace -fac -o isql.log isql -v simple
เช่นตอนกำหนดตำแหน่ง tnsnames.ora ผิด ผมเปิด isql.log พบว่า นั่นไง by default isql จะเปิด tnsnames.ora จาก
"/home/[user]/.tnsnames.ora"
"/etc/tnsnames.ora"
"/usr/lib/oracle/12.1/client64/lib/network/admin/tnsnames.ora"
เป็นต้น
การใช้ sqlplus64 ตามด้วย custom tns connect ORA server ได้ ไม่ได้หมายความว่า ODBC จะ connect ได้ เช่น
$ sqlplus64 user/password@//XXX.XXX.XXX.XXX/_SID_NAME_
connect ได้ query ได้ แต่ isql ไม่ works
การติดตั้ง sqleveloper Connect ORA server ได้ ไม่ได้หมายความว่า ODBC จะ connect ได้ เช่นกัน
อาจไม่ cover ทุก error ที่เจอ แต่ใคร install Oracle ODBC Driver บน Linux แล้วพบปัญหาลองแลกเปลี่ยนกันดูครับ
ผมยังใหม่กับ Oracle มาก :D