When moving to the Oracle 12c multitenant architecture one implication is that you have to switch to using service names in your connection strings for PDBs. Even SYSDBA connects to PDBs must use SERVICE_NAME.
Well, not quite necessarily. I guess customers adopting this new technology have not all managed to update their scripts. Or, software vendors and in-house development have hard-coded connection strings that cannot be changed quickly.
So, Oracle hastily added a new listener parameter USE_SID_AS_SERVICE_listener. This will tell the listener to treat the SID in the connect descriptor as SERVICE_NAME.
As long as the SID in the client connect descriptor matches the service name registered on the listener the connection is established.
$ cat /u01/app/oracle/network/admin/listener.ora LISTENER = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP) (Host = oel6ora12cdb1.localdomain) (Port = 1521) ) ) USE_SID_AS_SERVICE_LISTENER = ON
I have two PDBs which are registered on the listener as follows.
$ lsnrctl status ... Services Summary... Service "CDB1" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service... Service "testdb1" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service... Service "testdb2" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service...
My client tnsnames.ora holds entries for both PDBs, one with SERVICE_NAME (TESTDB1) and one with SID (TESTDB2).
$ cat /u01/app/oracle/network/admin/tnsnames.ora TESTDB1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oel6ora12cdb1.localdomain)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = TESTDB1) ) ) TESTDB2 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oel6ora12cdb1.localdomain)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SID = TESTDB2) ) )
Next, I connect to both PDBs using above TNS entries.
$ sqlplus /nolog SQL> connect system/manager@PDB1 Connected. SQL> connect system/manager@PDB2 Connected.
Well, that’s all fine.
But, what’s going to happen if we set the DB_DOMAIN, then the db domain is appended to the service name. Ultimately, the SID parameter you have in the client connect descriptor does not match the service name anymore.
Since you most likely use above described feature because you cannot change the client connect descriptor this solution does not work anymore.
Back to square one.
Just for fun let’s try it anyway…but of course, for it to work I have to adjust the SID in the TNS entry for TESTDB2.
SQL> show parameter db_domain NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_domain string localdomain
On the listener there are the two services from my pluggable databases, TESTDB1 and TESTDB2.
$ lsnrctl status ... Services Summary... Service "CDB1.localdomain" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service... Service "testdb1.localdomain" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service... Service "testdb2.localdomain" has 1 instance(s). Instance "CDB1", status READY, has 1 handler(s) for this service... The command completed successfully
Now, to match the service name I change the TNS entry for TESTDB2 to following:
TESTDB2.localdomain = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oel6ora12cdb1.localdomain)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SID = TESTDB2.localdomain) ) )
At first sight it’s a bit strange to see the db domain in the SID parameter as this was never supposed to work this way. But at least we can connect again.
$ sqlplus system/manager@TESTDB2.localdomain Connected.
I thought about creating a service using DBMS_SERVICE.CREATE_SERVICE but Oracle will always append the db domain to the service on the listener. And since a service in the format “PDB_NAME.DB_DOMAIN” already exists you will not be able to create it (ORA-44303: service name exists).
I file this under half-baked solution…(Not that I think this feature should by used anyway. Go get your scripts and applications fixed!)