Thursday, November 19, 2009

Phantom TNSNAMES entries

I have a PowerShell script that uses Oracle.DataAccess. It retrieves its connection information from an existing configuration file on a server. The connection information is as basic as you can get: Data Source, User Id, Password. I had already successfully installed and executed the script on a development server but received the following error when I attempted to run the script on my test server: "ORA-12505: TNS:listener does not currently know of SID given in connect descriptor".

I was baffled. The test server is an application server that has been running in good order for a couple of years. The application that runs on it (let's call it SERVICE) successfully talks to the "missing" database almost continuously. The TNSNAMES file on the test server contains a single entry, and I knew that entry was valid because SERVICE was up and running.

I immediately started checking event logs, experimenting with case sensitivity in the connection string and the PowerShell script, and tweaking environment variables. I executed the relevant steps from the script in the PowerShell console. I scoured the server's file system for extra TNSNAMES.ORA files but found only the one that I expected. I stopped SERVICE in case it was somehow blocking my script's database calls. To make the issue even more confounding, I could specify a Data Source that wasn't even listed in the TNSNAMES file and I could then open the OracleConnection!

After several hours I gave up. I returned to the problem over a week later with a strange notion to check any mapped network drives. I've got a default mapped drive created (I assume) when my domain account was created. Looking in this drive I had a Eureka! moment: an old TNSNAMES file from my development machine that was full of entries. Suddenly it all made sense: I could connect to databases not present in the test server's TNSNAMES file because the entries were present in the 'network' TNSNAMES file. And, conversely, I couldn't connect to the test server's TNS entry because the port value had changed in the past couple of months and my 'network' TNSNAMES file had the old, invalid port.

What I had expected to be a trivial smoke test turned out to be much, much more. There's a lesson in here somewhere. The obvious one is that I probably should have initially started off configuring the script with the credentials with which it will be used in production. Another lesson is that software development can be maddeningly frustrating and that sometimes you just have to walk away. We don't all have the luxury of time that I did during this exercise, but sometimes some distance from a problem really brings clarity.