携手创作,共同成长!这是我参与「掘金日新计划 · 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, 可进行注解配置。