Oracle 慢 SQL,怎么找到真正的客户端 IP?
平时排查 Oracle 慢 SQL,一般我都是先找到 SQL_ID,再看执行计划、等待事件、逻辑读和物理读。
不过有时候,SQL 找到了,问题也基本定位了,业务却反过来问一句:
这个 SQL 到底是哪个客户端发起的?
最近正好接管一套 Oracle 11g 数据库时,就遇到了这种情况。数据库里有一条 SQL 执行比较慢,客户端程序显示为 JDBC Thin Client,但仅凭这个信息,还没办法确定是哪台应用服务器。
最后通过 Oracle 会话、数据库服务端进程和操作系统网络连接,找到了对应的客户端 IP。
记录一下过程,下次遇到可以直接照着查。
1. 先通过 SQL_ID 找到会话
当时定位到的慢 SQL:
fq5vvra6z6rt7
先查询它当前对应的会话:
SELECT sid,
serial#,
username,
sql_id,
status,
event,
machine,
program
FROM v$session
WHERE sql_id = 'fq5vvra6z6rt7';
其中一个会话的信息是:
| 字段 | 结果 |
|---|---|
| SID | 3117 |
| SERIAL# | 63851 |
| SQL_ID | fq5vvra6z6rt7 |
| PROGRAM | JDBC Thin Client |
| EVENT | read by other session |
通过这些信息,已经能够确定执行 SQL 的 Oracle 会话。
但 JDBC Thin Client 只能说明使用的是 JDBC 驱动,并不能直接告诉我们实际的客户端 IP。
2. 根据 SID 找到 Oracle 服务端进程
Oracle 专用服务器连接模式下,可以通过 V$SESSION 和 V$PROCESS 找到会话对应的操作系统进程。
SELECT s.sid,
s.serial#,
s.username,
s.machine,
s.program,
p.spid
FROM v$session s
JOIN v$process p
ON s.paddr = p.addr
WHERE s.sid = 3117;
查到对应的操作系统进程号:SPID:27410。
到这里,我们就把数据库中的 SID 和 Linux 上的 PID 对应起来了。
3. 到 Linux 上查看进程
登录数据库服务器,执行:
ps -fp 27410
结果显示:
oracle 27410 ... oraclerepdb (LOCAL=NO)
说明这是一个 Oracle 数据库服务端进程,接下来就可以通过网络连接反查客户端。
4. 使用 netstat 找到客户端 IP
执行:
netstat -tnp | grep 27410
当时查到了两条连接:
10.245.40.113:44130 10.245.40.104:1521 ESTABLISHED 27410/oraclerepdb
10.245.40.113:1521 10.245.40.123:45036 ESTABLISHED 27410/oraclerepdb
这里要注意连接方向:
- 第一条是数据库服务器本地临时端口
44130,连接远端10.245.40.104:1521。 - 第二条则是数据库服务器的监听端口
1521,连接远端10.245.40.123:45036。
所以这次定位到的客户端 IP 是:10.245.40.123,至于 10.245.40.104:1521,它是同一个进程建立的另一条数据库网络连接,可能涉及数据库链路等操作,但仅凭这条网络记录还不能直接认定其用途。
5. 整个排查过程
慢 SQL
SQL_ID = fq5vvra6z6rt7
↓
V$SESSION
SID = 3117
SERIAL# = 63851
↓
V$PROCESS
SPID = 27410
↓
Linux:ps -fp 27410
确认 Oracle 服务端进程
↓
Linux:netstat -tnp | grep 27410
↓
客户端 IP:10.245.40.123
最后
这次排查没有用什么复杂工具,核心就是把三个信息关联起来:
SQL_ID → SID → SPID → 客户端 IP
V$SESSION 负责找到数据库会话,V$PROCESS 负责关联 Linux 进程,最后通过 netstat 查看该进程建立的 TCP 连接。
对于还在执行的慢 SQL,这套方法比较直接,基本几条命令就能把数据库会话和客户端连接对应起来。
不过,写到这里还有两个问题。
- 如果 SQL 已经执行结束,甚至会话都断开了,没有 SID、SPID 和 TCP 连接,还能不能查到当时的客户端 IP?
- 如果数据库前面还有连接池、NAT 或代理,查出来的只是应用服务器 IP,又该怎么找到真正发起请求的客户端?
这两种情况在生产环境里其实也很常见,而且排查起来比今天这个案例复杂得多。
下一篇准备继续研究这个问题,从 Oracle 历史会话、监听日志、审计记录,一直查到应用连接池和网络代理,看看不同场景下到底能追溯到哪一步。
也顺便验证一下:一条已经执行结束的 Oracle 慢 SQL,究竟还能不能找到它的来源 IP?
- 点赞
- 收藏
- 关注作者
评论(0)