Java Mybatis SqlSession如何绑定&Kill Oracle Session

967 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

笔者最近项目新增新业务模块,通过jdbc直连Oracle 服务,其中有大量慢SQL(数据量限制,无法优化),需要对过程中执行的SQL进行监控,并在某些时候需要某些执行中的慢sql, 进行kill。当然dba也可以通过sql脚本进行查询和kill, 但由于业务需求,为了更好契合业务需要,便在系统中实现。

Mybatis session 与 Oracle session

探究过程就先不赘述,直接描述结论。

Mybatis的Connection对应的是Oracle的session。

Mybatis的一个connection对应一个数据库的长链接,就是oracle的session,基于connection的一次会话占用。

opensession过程,就是从连接池中获取connection, 使用完之后,归还连接。

实现方案

oracle中 v$session,是基础信息视图,每一个连接到数据库实例中的session都拥有一条记录,包含用户session相关信息,如sid, saddr, 为dba提供了一个查询和管理session的窗口。

部分字段如下:

| SADDR             | RAW(4 | 8)  | Session address                                                                                                                                            
| SID               | NUMBER       | Session identifier                                                                                                                                         
| SERIAL#           | NUMBER       | Session serial number. Used to uniquely identify a session's objects. Guarantees that session-level commands are applied to the correct session objects if the session ends and another session begins with the same session ID. 
| 。。。。              | 。。。。         | 。。。                                               
| CLIENT_IDENTIFIER | VARCHAR2(64) | Client identifier of the session                           

如需要详细了解全部字段,可到oracle官网查看:docs.oracle.com/en/database…

通过V$session的用法有很多,比如

  • 查询用户当前的等待信息.以查看当前的语句为什么这么慢/在等待什么资源.
    select * from v$session_wait where sid=:sid;

  • 查询用户在一段时间内所等待的各种事件的信息.以了解这个 session所遇到的瓶颈^_^
    select * from v$ session_event wheresid=:sid;

  • 当我们想kill当前 session的时候可以通过sid,serial#来处理.
    alter system kill session':sid,:serail#';

从上面v$sesion视图的一些字段来看,我们可以利用client_identifier字段,当我们执行某个慢sql前,给c字段client_identifier赋唯一值sessionid(功能+sqlid)等, 执行完慢sql之后,将字段设置为'', 那么在慢sql执行过程中,我们可以用过client_identifier =sessionid 找到Oracle Session, 也就可以精准kill处理。

begin
dbms_session.set_identifier('select_001');
end;

select client_identifier from v$session where  status in ('INACTIVE','ACTIVE')  and client_identifier = ''

begin
dbms_session.set_identifier('');
end;

下一步,优化调整代码, 开发对应的注解+拦截器,做到有需要监控的慢sql访问的service, 可进行注解配置。