This document describe one of the most troblesome configuration I have ever set up.
It took me almost two days to figure out how to properly set everything to make it works so I'm writing this documentation to spare a headache to other sysadmins/DBA who wish to achieve the same.
I divided the process in three steps:
First and third points have been the hardest since my knowledge of DB2 is limited.
First of all install the DB2 client (for me it was DB2connect 7.1) and register it with the proper license (using db2licm).
Now you are ready to register your remote database.
I'll need to provide:
hostname,
port,
database name,
authentication method.
For every DB I need three registrations: tcp/ip node, database and DCS.
Let's start from the tcp/ip node.
Connect to your db2 user (by default db2inst1):
db2inst1@brepredbls01:~> db2
(c) Copyright IBM Corporation 1993,2001
Command Line Processor for DB2 SDK 7.2.0
db2 =>
Now from the db2 client command prompt:
catalog tcpip node <nodename> remote <hostaname> server <port>
where nodename is an alias you choose, hostname is the DB2 remote hostname and the port is the DB2 listening port.
example:
catalog tcpip node RIHEP remote rihep.rit server 5023
to unregister it:
uncatalog node RIHEP
and to list the register nodes:
db2 => list node directory
Node Directory
Number of entries in the directory = 3
Node 1 entry:
Node name = AMDSPT
Comment =
Protocol = TCPIP
Hostname = amdahlsvil.ras
Service name = 5023
Node 2 entry:
Node name = AMSVIL
Comment =
Protocol = TCPIP
Hostname = amdahlsvil.ras
Service name = 6021
Node 3 entry:
Node name = RIHEP
Comment =
Protocol = TCPIP
Hostname = rihep.rit
Service name = 5023
Now you need to catalog your remote DB2 database:
catalog database <DBname> as <DBalias> at node <nodename> authentication DCS
Where DBname is the name of the remote database, DBalias is the name you are going to use in your connection and nodename is the node alias you registered above.
The chosen authentication has been DCS for my environment.
Example:
catalog database ITFINDB2 as ITFINDB2 at node RIHEP authentication DCS
If you wish to unregister the DB:
uncatalog database ITFINDB2
for the list:
db2 => list db directory
System Database Directory
Number of entries in the directory = 3
Database 1 entry:
Database alias = ITFINDB2
Database name = ITFINDB2
Node name = RIHEP
Database release level = 9.00
Comment =
Directory entry type = Remote
Authentication = DCS
Catalog node number = -1
Database 2 entry:
Database alias = DB2PROD
Database name = DB2PROD
Node name = AMSVIL
Database release level = 9.00
Comment =
Directory entry type = Remote
Authentication = DCS
Catalog node number = -1
Database 3 entry:
Database alias = DB2DSPT
Database name = DB2DSPT
Node name = AMDSPT
Database release level = 9.00
Comment =
Directory entry type = Remote
Authentication = DCS
Catalog node number = -1
Last registration step: the DCS.
catalog dcs database <DBname> as <DBalias>
example:
catalog dcs database ITFINDB2 as ITFINDB2
to unregister:
unregister dcs ITFINDB2
For the list:
db2 => list dcs directory
Database Connection Services (DCS) Directory
Number of entries in the directory = 3
DCS 1 entry:
Local database name = DB2DSPT
Target database name = DB2DSPT
Application requestor name =
DCS parameters =
Comment =
DCS directory release level = 0x0100
DCS 2 entry:
Local database name = DB2PROD
Target database name = DB2PROD
Application requestor name =
DCS parameters =
Comment =
DCS directory release level = 0x0100
DCS 3 entry:
Local database name = ITFINDB2
Target database name = ITFINDB2
Application requestor name =
DCS parameters =
Comment =
DCS directory release level = 0x0100
Now you can check if your configuration is correct:
db2 => connect to ITFINDB2 user sisbanc
Enter current password for sisbanc:
Database Connection Information
Database server = DB2 OS/390 7.1.1
SQL authorization ID = SISBANC
Local database alias = ITFINDB2
This indicate a succesful connection.
An error or a command prompt without output indicates a failure.
ex:
db2 => connect to ITFINDB2 user sisbanc
Enter current password for sisbanc:
db2 => db2 =>
If the DB2 client is set correctly you can step forward.
Now you need to configure your odbc.
I installed on my SLES9 the unixODBC package using yast (the operation is really simple).
Now in /etc/unixODBC I'm going to store all my configuration files (basically odbcinst.ini and odbc.ini).
This is my odbcinst.ini
db2inst1@brepredbls01:~> cat /etc/unixODBC/odbcinst.ini
[DB2]
Description = ODBC for DB2
Driver = /usr/IBMdb2/V7.1/lib/libdb2.so
FileUsage = 1
DontDLClose = 1
Here I simply configured a generic entry called DB2 which uses the driver (library) of the DB2 client installed and set above.
The important part is the driver. Make sure the location of the libdb2.so is correct on your system.
For the odbc.ini:
db2inst1@brepredbls01:~> cat /etc/unixODBC/odbc.ini
[DB2PROD]
Description = DB2PROD for Prevint
Driver = DB2
Database = DB2PROD
#DMEnvAttr = SQL_ATTR_UNIXODBC_ENVATTR={DB2INSTANCE=db2inst1}
[ITFINDB2]
Description = ITFINDB2 for Prevint
Driver = DB2
Database = ITFINDB2
[DB2DSPT]
Description = DB2DSPT for Prevint
Driver = DB2
Database = DB2DSPT
I have three entries like the three databases I configured in my systems.
All has the driver set to DB2 which indicates they have to take the entry in your odbcinst.ini and using the settings there (so the libdb2.so).
I'm going to discuss the SQL_ATTR_UNIXODBC_ENVATTR later.
To check if the configuration is working properly use the unixODBC client: isql.
brepredbls01:/etc/unixODBC # isql ITFINDB2 SISBANC SISBANC
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> select count(*) FROM TRAS.POL_ELEN_ELET
+------------+
| |
+------------+
| 493318 |
+------------+
SQLRowCount returns -1
1 rows fetched
This is the last step. You are going to configure oracle HS in order to be able to access a DB2 via DB link.
Three are the files used for the configuration: listener.ora, tnsnames.ora and initDBNAME.ora.
Let's start from the latter.
In $ORACLE_HOME/hs/admin you need a init file for the HS service you are creating.
The information inside this file are related to the ODBC DSN you configured in setp 2.
Here is the content of a file of mine:
oracle@brepredbls01:/u01/app/oracle/product/10.1/db_1/hs/admin> cat initITFINDB2.ora
# This is a sample agent init file that contains the HS parameters that are
# needed for an ODBC Agent.
set ODBCINI=/etc/unixODBC/odbc.ini
HS_FDS_SHAREABLE_NAME=/usr/lib/libodbc.so
HS_FDS_CONNECT_INFO = ITFINDB2
HS_FDS_TRACE_LEVEL = 0
HS_FDS_TRACE_FILE_NAME = ITFINDB2.trc
HS_DB_NAME = ITFINDB2
HS_LANGUAGE= ITALIAN_ITALY.WE8MSWIN1252
Two entries are imports:
set ODBCINI=/etc/unixODBC/odbc.ini tells which odbc.ini files needs to be used in this way you can go for a non-global one (for example one editable from your oracle user).
HS_FDS_SHAREABLE_NAME=/usr/lib/libodbc.so indicates which ODBC (library) to use.
The one I pointed is the unixODBC basic library.
Later you needs to configure your listener.ora. Here is mine:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = brepredbls01.ras)(PORT = 1521))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/product/10.1/db_1)
(PROGRAM = extproc)
)
(SID_DESC=
(SID_NAME=DB2PROD)
(ORACLE_HOME= /u01/app/oracle/product/10.1/db_1)
(PROGRAM=hsodbc)
(ENVS=DB2INSTANCE=db2inst1)
)
(SID_DESC=
(SID_NAME=DB2DSPT)
(ORACLE_HOME= /u01/app/oracle/product/10.1/db_1)
(PROGRAM=hsodbc)
(ENVS=DB2INSTANCE=db2inst1)
)
(SID_DESC=
(SID_NAME=ITFINDB2)
(ORACLE_HOME= /u01/app/oracle/product/10.1/db_1)
(PROGRAM=hsodbc)
(ENVS=DB2INSTANCE=db2inst1)
)
(SID_DESC=
(SID_NAME=UNS)
(ORACLE_HOME= /u01/app/oracle/product/10.1/db_1)
)
)
The entry:
(SID_DESC=
(SID_NAME=ITFINDB2)
(ORACLE_HOME= /u01/app/oracle/product/10.1/db_1)
(PROGRAM=hsodbc)
(ENVS=DB2INSTANCE=db2inst1)
Indicates which service to look for. In this case an HOODBC calles ITFINDB2 (so looking for $ORACLE_HOME/hs/admin/initITFINDB2.ora).
The (ENVS=DB2INSTANCE=db2inst1) is discussed later.
The listener is listening for the HS services:
lsnrctl status
LSNRCTL for Linux: Version 10.1.0.4.0 - Production on 13-OCT-2005 10:25:46
Copyright (c) 1991, 2004, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=brepredbls01.ras)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 10.1.0.4.0 - Production
Start Date 12-OCT-2005 16:27:11
Uptime 0 days 17 hr. 58 min. 34 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/10.1/db_1/network/admin/listener.ora
Listener Log File /u01/app/oracle/product/10.1/db_1/network/log/listener.log
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=brepredbls01.ras)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=brepredbls01.ras)(PORT=8080))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "DB2DSPT" has 1 instance(s).
Instance "DB2DSPT", status UNKNOWN, has 1 handler(s) for this service...
Service "DB2PROD" has 1 instance(s).
Instance "DB2PROD", status UNKNOWN, has 1 handler(s) for this service...
Service "ITFINDB2" has 1 instance(s).
Instance "ITFINDB2", status UNKNOWN, has 1 handler(s) for this service...
Service "PLSExtProc" has 1 instance(s).
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "UNS" has 2 instance(s).
Instance "UNS", status UNKNOWN, has 1 handler(s) for this service...
Instance "UNS", status READY, has 1 handler(s) for this service...
Service "UNSXDB" has 1 instance(s).
Instance "UNS", status READY, has 1 handler(s) for this service...
The command completed successfully
Last file:
DB2PROD =
(DESCRIPTION =
(ADDRESS=(PROTOCOL=tcp)
(HOST= brepredbls01.ras)
(PORT=1521))
(CONNECT_DATA=(SID=DB2PROD))
(HS=OK)
)
DB2DSPT =
(DESCRIPTION =
(ADDRESS=(PROTOCOL=tcp)
(HOST= brepredbls01.ras)
(PORT=1521))
(CONNECT_DATA=(SID=DB2DSPT))
(HS=OK)
)
ITFINDB2 =
(DESCRIPTION =
(ADDRESS=(PROTOCOL=tcp)
(HOST= brepredbls01.ras)
(PORT=1521))
(CONNECT_DATA=(SID=ITFINDB2))
(HS=OK)
)
To make the oracle client able to point toward your listener.
Create a DBlink inside your database:
CREATE PUBLIC DATABASE LINK "ITFINDB2" CONNECT TO SISBANC IDENTIFIED by PASSWORD USING 'ITFINDB2';
and you are done... almost...
My main problem has been with this error:
[unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed
Googling I found that the possible reason was that the env variable DB2INSTANCE was not set.
And it was so.
But how to do it?
1.
I found four different ways (and I applied two).
Insert into odbc.ini the line:
DMEnvAttr = SQL_ATTR_UNIXODBC_ENVATTR={DB2INSTANCE=db2inst1}
This didn't worked for me and prevented even the connections with isql.
2.
Set it directly in your oracle environemt.
Since I'm using suse and the package orarun I simply added the line:
export DB2INSTANCE=db2inst1
in my /etc/profile.d/oracle.sh
3.
Place the line:
set DB2INSTANCE=db2inst1
in your $ORACLE_HOME/hs/admin/initITFINDB2.ora
4.
in your listener.ora insert:
(ENVS=DB2INSTANCE=db2inst1)
for the SID_DESC of your DB2 service.
Personally I used the solutions 2 and 4.
After this last configuration my DBlinks where fully operational and my datawarehouse where able to retrieve data directly from DB2.
(What a hard day...)
Ok, I met another error on one of my dblink.
I started debugging from the db2 client (the lower layer) and found this error:
db2 => select * from portaf.alcommin
SQL0332N There is no available conversion for the source code page "1140" to
the target code page "1208". Reason Code "1". SQLSTATE=57017
This was due to codepage incompatibility.
I solved it by changing my LANG (locale) env variable in the oracle user shell.
I did it by editing the file:
/etc/SuSEconfig/profile
switching from UTF8 to iso8859-15.
Contact information:
fabrizio.magni _at_ gmail.com