Are you fishing or catching? – Server-side SQL*Net tracing for specific clients

SQL*Net tracing on the database server is all or nothing (sqlnet.ora):
TRACE_LEVEL_SERVER=support

On a busy system this quickly gets out of hand. More often than not I find myself in need of enabling SQL*Net trace on the server for a particular database client.
The first step is to setup a separate TNS_ADMIN location that we want the sever process for our client connections to pick up:

$ mkdir /u01/app/oracle/network/admin-trc
$ copy /u01/app/oracle/network/admin/sqlnet.ora /u01/app/oracle/network/admin-trc/.

Then enable SQL*Net tracing in the new TNS_ADMIN location:

vi /u01/app/oracle/network/admin-trc/sqlnet.ora

...
TRACE_LEVEL_SERVER=support

If you can modify the client’s connection string things are easy. All we need is a separate service on the existing listener that the client then connects to:
vi /u01/app/oracle/network/admin/listener.ora

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = pdbdev1_trc.localdomain)
      (ORACLE_HOME = /u01/app/oracle/product/ora12201)
      (SID_NAME = DEV1)
      (ENVS="TNS_ADMIN=/u01/app/oracle/network/admin-trc")
    )
  )

Line 4: Defines our new service name
Line 7: This makes server processes for connections through that service read our sqlnet.ora in the “admin-trc” directory and, therefore enable SQL*Net tracing.

Now, change the client’s connection string to use “pdbdev_trc” service and we’re done.
But, what if for some reason you cannot easily change the client’s connect string. That’s when I like to resort to port-forwarding using firewalld.

First, we spin up an additional listener on another port. Let’s assume our original listener runs on port 1521.
vi /u01/app/oracle/network/admin/listener.ora

LISTENER_TRC =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ol7ora122dev1.localdomain)(PORT = 1522))
    )
  )

SID_LIST_LISTENER_TRC =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = pdbdev1.localdomain)
      (ORACLE_HOME = /u01/app/oracle/product/ora12201)
      (SID_NAME = DEV1)
      (ENVS="TNS_ADMIN=/u01/app/oracle/network/admin-trc")
    )
  )

Line 4: listening on new port
Line 11: the service name is the same as on the original listener (where the client connects to)
Line 14: Again, this sets the TNS_ADMIN location for the server process to pick up our sqlnet.ora with SQL*Net tracing enabled.

Secondly, add the port forwarding rule:

firewall-cmd --zone=oradb-server \
  --add-rich-rule='rule family="ipv4" source address="<client-IP>" forward-port port=1521 protocol=tcp to-port=1522'

Now, every connection request from the client we want to have a server-side SQL*Net trace from gets forwarded to our new listener and picks up our modified sqlnet.ora.
Obviously, this is assuming you have firewalld configured and running already. If not, await my next blog post on basic firewalld configuration for Oracle database servers.

Enjoy!

P.s. when you have all the traces you need you can remove the port forwading rule like this:

firewall-cmd --zone=oradb-server \
  --remove-rich-rule='rule family="ipv4" source address="<client-IP>" forward-port port=1521 protocol=tcp to-port=1522'

6 thoughts on “Are you fishing or catching? – Server-side SQL*Net tracing for specific clients

  1. s234blog

    This is extremely interesting. In fact what you are doing is to use a service specific sqlnet.ora – this could be useful for many other cases, not only tracing. Have service specific encryption settings, authentication settings, SDU sizes, …. in particular in multitenant.
    Only concern – doing this in the listener.ora means you need to have static service registration. DId you come across by chance on any way to set similar environment for dynamic registration ? There was something in earlier versions – srvctl setenv -service but this doesn’t seem to exist anymore.

    Best,
    Chris

    Reply
    1. son Post author

      Hi Chris,

      Thanks for your comment! Indeed, it can be handy for other use cases, too.
      Unfortunately, I’m not aware of any way to do this with dynamically registered services. Searched for a solution myself but couldn’t find anything. “srvctl setenv” is not applicable to services – that would be a nice feature…

      Btw., glad you left a comment so I came across your blog – just added to my reading list!

      Thanks,
      Beat

      Reply
  2. Pingback: Multitenant and SQL*Net config – Oracle, Exadata, Multitenant and related

  3. Pingback: Follow-up: SQL*Net tracing | Spot on Oracle

  4. Julian

    Hi

    Great idea.
    Do you know if there is a possiblity to define the ENVS in a GI environment for the service?
    Accoring to my knowledge there is only the possiblity to modify the listener with:
    srvctl setenv listener -listener listener_trc -env “TNS_ADMIN=/u01/app/oracle/network/admin-trc”

    Greetings
    Julian

    Reply
    1. son Post author

      Hi Julian,
      No, I don’t think there is a way to configure the ENVS in GI for services. It would be a nice addition if we could configure it in GI, though.
      Generally, it cannot be done for dynamically registered services, only static ones.
      Thanks for stopping by, old friend! 🙂

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.