Oracle 慢 SQL,怎么找到真正的客户端 IP?

举报
Lucifer三思而后行 发表于 2026/10/08 17:02:37 2026/10/08
【摘要】 平时排查 Oracle 慢 SQL,一般我都是先找到 SQL_ID,再看执行计划、等待事件、逻辑读和物理读。不过有时候,SQL 找到了,问题也基本定位了,业务却反过来问一句:这个 SQL 到底是哪个客户端发起的?最近正好接管一套 Oracle 11g 数据库时,就遇到了这种情况。数据库里有一条 SQL 执行比较慢,客户端程序显示为 JDBC Thin Client,但仅凭这个信息,还没办法确...

平时排查 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

这里要注意连接方向:

  1. 第一条是数据库服务器本地临时端口 44130,连接远端 10.245.40.104:1521。
  2. 第二条则是数据库服务器的监听端口 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,这套方法比较直接,基本几条命令就能把数据库会话和客户端连接对应起来。

不过,写到这里还有两个问题。

  1. 如果 SQL 已经执行结束,甚至会话都断开了,没有 SID、SPID 和 TCP 连接,还能不能查到当时的客户端 IP?
  2. 如果数据库前面还有连接池、NAT 或代理,查出来的只是应用服务器 IP,又该怎么找到真正发起请求的客户端?

这两种情况在生产环境里其实也很常见,而且排查起来比今天这个案例复杂得多。

下一篇准备继续研究这个问题,从 Oracle 历史会话、监听日志、审计记录,一直查到应用连接池和网络代理,看看不同场景下到底能追溯到哪一步。

也顺便验证一下:一条已经执行结束的 Oracle 慢 SQL,究竟还能不能找到它的来源 IP?

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。