mirror of https://gitee.com/y_project/RuoYi.git
feat(all): add killDeadLockSession
parent
4eee5b3310
commit
e7576af430
|
@ -9,7 +9,7 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>ruoyi-admin</artifactId>
|
||||
<artifactId>ruoyi-admin-neuhisutools</artifactId>
|
||||
|
||||
<description>
|
||||
web服务入口
|
||||
|
|
|
@ -1,32 +1,12 @@
|
|||
package com.neuhis.his.domain.dto;
|
||||
|
||||
public class DeadLock {
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class DeadLock {
|
||||
private String sid;
|
||||
private String serial;
|
||||
private String sessionStr;
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
public String getSerial() {
|
||||
return serial;
|
||||
}
|
||||
|
||||
public void setSerial(String serial) {
|
||||
this.serial = serial;
|
||||
}
|
||||
|
||||
public String getSessionStr() {
|
||||
return sessionStr;
|
||||
}
|
||||
|
||||
public void setSessionStr(String sessionStr) {
|
||||
this.sessionStr = sessionStr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package com.neuhis.his.domain.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class DeadLockRac {
|
||||
private String 数据库服务器;
|
||||
private String 登录用户名;
|
||||
private String 锁的对象;
|
||||
/**
|
||||
* 进程id
|
||||
*/
|
||||
private Integer 本进程号SID;
|
||||
/**
|
||||
* 情况1:(SID:2009)会话 SQL已跑完 ==>忽略
|
||||
* 情况2:(SID:4017)会话 正执行SQL:delete xx ==>忽略
|
||||
* 情况3:根锁为此会话杀我KILL ME or igore==> 杀我,或者忽略
|
||||
* 情况4:<根锁会话>4903 【SID=4903】的SQL阻塞了本语句[5728]杀掉他==> 杀掉这个:【SID】
|
||||
*/
|
||||
private String 阻塞SID;
|
||||
private String STATUS;
|
||||
private String SQL_TEXT;
|
||||
private String CLIENT_INFO;
|
||||
private String program;
|
||||
private String REQUEST;
|
||||
private String STATE;
|
||||
private String EVENT;
|
||||
/**
|
||||
* 电脑ip
|
||||
*/
|
||||
private String MACHINE;
|
||||
private String LOGON_TIME;
|
||||
private String INST_ID;
|
||||
/**
|
||||
* 等待时间
|
||||
*/
|
||||
private String 等待时间;
|
||||
private String BLOCKING_SESSION;
|
||||
private String PROGRAM;
|
||||
private String sessionStr;
|
||||
private String norac_KILL;
|
||||
/**
|
||||
* 杀锁SQL,形如:
|
||||
* ALTER SYSTEM KILL SESSION '6439,1899,@2' immediate ;
|
||||
*/
|
||||
private String rac_KILL;
|
||||
|
||||
public DeadLockRac() {
|
||||
}
|
||||
|
||||
public DeadLockRac(Integer 本进程号SID, String 阻塞SID) {
|
||||
this.本进程号SID = 本进程号SID;
|
||||
this.阻塞SID = 阻塞SID;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,36 @@
|
|||
package com.neuhis.his.mapper;
|
||||
|
||||
import com.neuhis.his.domain.dto.DeadLock;
|
||||
import com.neuhis.his.domain.entity.MetMrsBase;
|
||||
import com.neuhis.his.domain.dto.DeadLockRac;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface OracleSysMapper {
|
||||
|
||||
List<DeadLock> getDeadLockSession();
|
||||
/**
|
||||
* 简版: 获取死锁进程
|
||||
* 主要用途是识别出那些已经处于等待锁状态超过5分钟并且当前是活跃的数据库会话,
|
||||
* 这对于诊断和解决数据库死锁或长时间运行的事务问题非常有用
|
||||
*/
|
||||
List<DeadLock> getDeadLockSessionV1();
|
||||
|
||||
/**
|
||||
* RAC方式,获取死锁对象
|
||||
* --查询跟踪卡顿的阻塞锁会话进程SQL(集群RAC),速度很快
|
||||
* --解释:从 RAC(Real Application Clusters)环境中获取当前存在锁争用(blocking locks)的会话信息。查询结果提供了关于阻塞会话的各种细节,包括锁定的对象、会话状态、等待时间和可能的解锁命令等
|
||||
* --查杀步骤:查看【等待时间】最长,【RAC_KILL】 != 的进行 杀进程
|
||||
* --查询跟踪卡顿的阻塞锁会话进程SQL
|
||||
*/
|
||||
List<DeadLockRac> getDeadLockSessionV2Rac();
|
||||
/**
|
||||
* Slow版本
|
||||
*/
|
||||
List<DeadLock> getDeadLockSessionV3Slow();
|
||||
|
||||
/**
|
||||
* 形如:ALTER SYSTEM KILL SESSION '4150,14295,@1' immediate ;
|
||||
* @param sessionStr '4150,14295,@1'
|
||||
*/
|
||||
void killSession(String sessionStr);
|
||||
|
||||
}
|
|
@ -1,12 +1,24 @@
|
|||
package com.neuhis.his.service;
|
||||
|
||||
import com.neuhis.his.domain.dto.DeadLock;
|
||||
import com.neuhis.his.domain.dto.DeadLockRac;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IOracleSysService {
|
||||
|
||||
List<DeadLock> getDeadLockSession();
|
||||
/**
|
||||
* 简易版查询,速度很快
|
||||
*/
|
||||
List<DeadLock> getDeadLockSessionV1();
|
||||
/**
|
||||
* RAC版本,速度很快
|
||||
*/
|
||||
List<DeadLockRac> getDeadLockSessionV2Rac();
|
||||
/**
|
||||
* slow版本
|
||||
*/
|
||||
List<DeadLock> getDeadLockSessionV3Slow();
|
||||
|
||||
void killSession(String sessionStr);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
package com.neuhis.his.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import com.neuhis.his.domain.dto.DeadLockRac;
|
||||
import com.ruoyi.common.annotation.DataSource;
|
||||
import com.ruoyi.common.enums.DataSourceType;
|
||||
import com.neuhis.his.domain.dto.DeadLock;
|
||||
import com.neuhis.his.mapper.MetMrsBaseMapper;
|
||||
import com.neuhis.his.mapper.OracleSysMapper;
|
||||
import com.neuhis.his.service.IOracleSysService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@DataSource(value = DataSourceType.SLAVE)
|
||||
public class OracleSysServiceImpl implements IOracleSysService {
|
||||
|
@ -19,16 +26,93 @@ public class OracleSysServiceImpl implements IOracleSysService {
|
|||
private OracleSysMapper oracleSysMapper;
|
||||
|
||||
@Override
|
||||
public List<DeadLock> getDeadLockSession() {
|
||||
return oracleSysMapper.getDeadLockSession();
|
||||
public List<DeadLock> getDeadLockSessionV1() {
|
||||
return oracleSysMapper.getDeadLockSessionV1();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeadLockRac> getDeadLockSessionV2Rac() {
|
||||
List<DeadLockRac> deadLockRacs = oracleSysMapper.getDeadLockSessionV2Rac();
|
||||
return this.findV2DeadLockRacSessionId(deadLockRacs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeadLock> getDeadLockSessionV3Slow() {
|
||||
return oracleSysMapper.getDeadLockSessionV3Slow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killSession(String sessionStr) {
|
||||
try {
|
||||
oracleSysMapper.killSession(sessionStr);
|
||||
if (StringUtils.isNotEmpty(sessionStr)) {
|
||||
log.info("查杀进程id:" + sessionStr);
|
||||
oracleSysMapper.killSession(sessionStr);
|
||||
}
|
||||
}catch (Exception e){
|
||||
System.out.println("数据库啥死锁异常:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从进程列表找到,死锁的进程
|
||||
*/
|
||||
private List<DeadLockRac> findV2DeadLockRacSessionId(List<DeadLockRac> deadLockRacs) {
|
||||
//找到有问题的进程
|
||||
DeadLockRac problematicSession = DeadlockResolver.findProblematicSession(deadLockRacs);
|
||||
if (problematicSession != null) {
|
||||
return ListUtil.of(problematicSession);
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
//进程列表:本进程号SID、阻塞id 三列
|
||||
//1、“阻塞id”有四种情况,先找:“的SQL阻塞了本语句”的取得:“【SID=”的取值
|
||||
//2、找到:“本进程号SID” = “【SID=”的一行,如果本行:“阻塞id”是 情况3,结束,否则继续递归。
|
||||
private static class DeadlockResolver {
|
||||
public static final String BLOCK_FIND_TXT = "的SQL阻塞了本语句";
|
||||
public static final String BLOCK_ROOT_TXT = "根锁为此会话杀我KILL ME or igore";
|
||||
public static DeadLockRac findProblematicSession(List<DeadLockRac> deadlockList) {
|
||||
Map<Integer, DeadLockRac> sidMap = new HashMap<>();
|
||||
|
||||
// First pass: build a map for quick lookup by SID
|
||||
for (DeadLockRac deadlock : deadlockList) {
|
||||
sidMap.put(deadlock.get本进程号SID(), deadlock);
|
||||
}
|
||||
|
||||
// Second pass: look for entries that match the criteria
|
||||
for (DeadLockRac deadlock : deadlockList) {
|
||||
if (deadlock.get阻塞SID().contains(BLOCK_FIND_TXT)) {
|
||||
// Extract the blocking SID
|
||||
int blockingSID = extractBlockingSID(deadlock.get阻塞SID());
|
||||
DeadLockRac blockingSession = sidMap.get(blockingSID);
|
||||
|
||||
// Check if the blocking session's 阻塞SID is of case 3
|
||||
while (blockingSession != null && !isRootBlock(blockingSession.get阻塞SID())) {
|
||||
// If not case 3, recursively check the blocker of this session
|
||||
String sqlText = blockingSession.get阻塞SID();
|
||||
if (sqlText.contains(BLOCK_FIND_TXT)) {
|
||||
blockingSID = extractBlockingSID(sqlText);
|
||||
blockingSession = sidMap.get(blockingSID);
|
||||
} else {
|
||||
break; // Exit loop if it doesn't match case 4 anymore
|
||||
}
|
||||
}
|
||||
if (blockingSession != null && isRootBlock(blockingSession.get阻塞SID())) {
|
||||
return blockingSession; // Found problematic session
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // No problematic session found
|
||||
}
|
||||
|
||||
private static boolean isRootBlock(String sqlText) {
|
||||
return sqlText.contains(BLOCK_ROOT_TXT);
|
||||
}
|
||||
|
||||
private static int extractBlockingSID(String sqlText) {
|
||||
// Assuming format is like "...【SID=4903】..."
|
||||
String sidStr = sqlText.substring(sqlText.indexOf("【SID=") + 5, sqlText.indexOf("】"));
|
||||
return Integer.parseInt(sidStr.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.neuhis.quartz.task;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.neuhis.his.domain.dto.DeadLock;
|
||||
import com.neuhis.his.domain.dto.DeadLockRac;
|
||||
import com.neuhis.his.push.OracleSlaveDataAutoPushService;
|
||||
import com.neuhis.his.service.IOracleSysService;
|
||||
import com.neuhis.quartz.task.common.JobService;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.neuhis.quartz.task.common.JobSwitchConstant;
|
||||
|
@ -9,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务调度
|
||||
*
|
||||
|
@ -20,9 +25,10 @@ public class HisTask {
|
|||
|
||||
@Autowired
|
||||
JobService jobService;
|
||||
|
||||
@Autowired
|
||||
OracleSlaveDataAutoPushService oracleSlaveDataAutoPushService;
|
||||
@Autowired
|
||||
private IOracleSysService oracleSysService;
|
||||
|
||||
public void pushData()
|
||||
{
|
||||
|
@ -38,6 +44,7 @@ public class HisTask {
|
|||
log.info("数据推送结束" + DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
}
|
||||
|
||||
public void pushDataByCompareId(String apicode)
|
||||
{
|
||||
if (RuoYiConfig.isQuzrtzTask() && jobService.isEnable(JobSwitchConstant.comPatientinfo)) {
|
||||
|
@ -47,6 +54,21 @@ public class HisTask {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 杀oracle死锁
|
||||
*/
|
||||
public void killDeadLockSession() {
|
||||
if (RuoYiConfig.isQuzrtzTask()) {
|
||||
log.info("杀oracle死锁开始" + DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
|
||||
///List<DeadLock> deadLocks = oracleSysService.getDeadLockSessionV1();
|
||||
///deadLocks.forEach(deadLock -> HisTask.this.oracleSysService.killSession(deadLock.getSessionStr()));
|
||||
|
||||
List<DeadLockRac> sessionV2Rac = oracleSysService.getDeadLockSessionV2Rac();
|
||||
sessionV2Rac.forEach(deadLock -> HisTask.this.oracleSysService.killSession(deadLock.getSessionStr()));
|
||||
log.info("杀oracle死锁结束" + DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 定时删除日志表数据
|
||||
* */
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: password
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置连接超时时间
|
||||
connectTimeout: 30000
|
||||
# 配置网络超时时间
|
||||
socketTimeout: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: ruoyi
|
||||
login-password: 123456
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
|
@ -10,7 +10,7 @@ ruoyi:
|
|||
# 版本
|
||||
version: 1.0.1
|
||||
# 版权年份
|
||||
copyrightYear: 2023
|
||||
copyrightYear: 2025
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||
|
@ -56,8 +56,8 @@ spring:
|
|||
enabled: true
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@20.0.0.40:1521/hisdb
|
||||
username: crbsb
|
||||
password: crbsb
|
||||
username: hit_app
|
||||
password: hit
|
||||
db1:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: true
|
||||
|
@ -65,41 +65,6 @@ spring:
|
|||
url: jdbc:oracle:thin:@10.10.10.31:1521/dzbl
|
||||
username: winlis
|
||||
password: lis0928
|
||||
db2:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@10.10.13.10:1521/pacs
|
||||
username: pacs50
|
||||
password: pacs600718
|
||||
db3:
|
||||
# 从数据源开关/默认关闭,
|
||||
enabled: false
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@192.168.1.1:1521/ydsynew
|
||||
username: crbsb
|
||||
password: crbsb
|
||||
db4:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@192.168.1.1:1521/ydsynew
|
||||
username: crbsb
|
||||
password: crbsb
|
||||
db5:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@192.168.1.1:1521/ydsynew
|
||||
username: crbsb
|
||||
password: crbsb
|
||||
hitapp:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
driverClassName: oracle.jdbc.OracleDriver
|
||||
url: jdbc:oracle:thin:@20.0.0.40:1521/hisdb
|
||||
username: hit_app
|
||||
password: hit
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.neuhis.his.mapper.OracleSysMapper">
|
||||
<select id="getDeadLockSession" resultType="com.neuhis.his.domain.dto.DeadLock">
|
||||
<select id="getDeadLockSessionV1" resultType="com.neuhis.his.domain.dto.DeadLock">
|
||||
SELECT
|
||||
S.SID as sid,
|
||||
s.SERIAL# as serial,
|
||||
|
@ -13,6 +13,161 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
and s.lockwait is not null and s.status='ACTIVE'
|
||||
and s.PREV_EXEC_START < sysdate-5/(60*24)
|
||||
</select>
|
||||
|
||||
<select id="getDeadLockSessionV2Rac" resultType="com.neuhis.his.domain.dto.DeadLockRac">
|
||||
<![CDATA[
|
||||
SELECT DISTINCT decode(s.inst_id, 1, 'DB1', 2, 'DB2' ,s.inst_id) "数据库服务器",
|
||||
decode(s.BLOCKING_SESSION,'',S.USERNAME,'--'||s.USERNAME) "登陆用户名",
|
||||
O.OWNER || '.' || O.OBJECT_NAME "锁的对象",
|
||||
S.SID "本进程号SID",
|
||||
decode(S.BLOCKING_SESSION,
|
||||
'',
|
||||
'根锁为此会话' || '杀我KILL ME or igore',
|
||||
'<根锁会话>:' || S.BLOCKING_SESSION || ' 【SID=' || S.BLOCKING_SESSION || '】的SQL阻塞了本语句 [' || S.SID || '] 杀掉他<根锁会话>' ) "阻塞SID",
|
||||
S.BLOCKING_SESSION_STATUS "STATUS",
|
||||
(CASE
|
||||
WHEN SQL_TEXT IS NULL THEN
|
||||
'(SID:' || S.SID || ')会话 SQL已跑完'
|
||||
ELSE
|
||||
'(SID:' || S.SID || ')会话 正执行SQL:' || SQL_.SQL_TEXT
|
||||
END) "SQL_TEXT",
|
||||
s.CLIENT_INFO,
|
||||
s.program,
|
||||
LO.REQUEST,
|
||||
S.STATE,
|
||||
S.EVENT,
|
||||
S.MACHINE,
|
||||
S.LOGON_TIME,
|
||||
S.INST_ID,
|
||||
decode(S.WAIT_TIME,-2,'不确定',-1,'<0.1s',0,to_char(S.SECONDS_IN_WAIT)||'s',to_char(S.WAIT_TIME)||'s') AS "等待时间",
|
||||
S.BLOCKING_SESSION,
|
||||
s.PROGRAM,
|
||||
S.SID || ',' || S.SERIAL# ||',@'||S.inst_id as sessionStr,
|
||||
DECODE(S.BLOCKING_SESSION,
|
||||
'',
|
||||
'ALTER SYSTEM KILL SESSION ''' || S.SID || ',' ||
|
||||
S.SERIAL# ||''' immediate ;','') AS norac_KILL,
|
||||
DECODE(S.BLOCKING_SESSION,
|
||||
'',
|
||||
'ALTER SYSTEM KILL SESSION ''' || S.SID || ',' ||
|
||||
S.SERIAL# ||',@'||S.inst_id||''' immediate ;','') rac_KILL
|
||||
FROM GV$SESSION S
|
||||
LEFT JOIN GV$SQL SQL_
|
||||
ON SQL_.SQL_ID = S.SQL_ID
|
||||
AND SQL_.INST_ID = S.INST_ID
|
||||
JOIN GV$LOCKED_OBJECT L
|
||||
ON L.SESSION_ID = S.SID
|
||||
AND L.INST_ID = S.INST_ID
|
||||
JOIN ALL_OBJECTS O
|
||||
ON L.OBJECT_ID = O.OBJECT_ID
|
||||
JOIN GV$LOCK LO
|
||||
ON (LO.BLOCK != 0 OR LO.REQUEST != 0)
|
||||
WHERE LO.SID = L.SESSION_ID
|
||||
AND LO.SID = S.SID
|
||||
AND LO.INST_ID = L.INST_ID
|
||||
AND LO.INST_ID = S.INST_ID
|
||||
ORDER BY s.inst_id, S.BLOCKING_SESSION,s.SID DESC
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<select id="getDeadLockSessionV3Slow" resultType="com.neuhis.his.domain.dto.DeadLock">
|
||||
<![CDATA[
|
||||
select distinct t.sid_serial,t.* from (
|
||||
Select '节点 ' || a.INST_ID || ' session ' || a.sid || ',' || a_s.SERIAL# ||
|
||||
' 阻塞了 节点 ' || b.INST_ID || ' session ' || b.SID || ',' ||
|
||||
b_s.SERIAL# blockinfo,
|
||||
('alter system kill session '''||a.sid||','||a_s.SERIAL#||''';') as "批量杀锁表进程",
|
||||
a.sid||','||a_s.SERIAL# as sessionStr,
|
||||
a.sid||a_s.SERIAL# as sid_serial,
|
||||
a_s.SID,
|
||||
a_s.SCHEMANAME,
|
||||
a_s.MODULE,
|
||||
a_s.STATUS,
|
||||
a.type lock_type,
|
||||
a.id1,
|
||||
a.id2,
|
||||
decode(a.lmode,
|
||||
0,
|
||||
'none',
|
||||
1,
|
||||
null,
|
||||
2,
|
||||
'row-S (SS)',
|
||||
3,
|
||||
'row-X (SX)',
|
||||
4,
|
||||
'share (S)',
|
||||
5,
|
||||
'S/Row-X (SSX)',
|
||||
6,
|
||||
'exclusive (X)') lock_mode,
|
||||
'后为被阻塞信息',
|
||||
b.INST_ID blocked_inst_id,
|
||||
b_s.SID blocked_sid,
|
||||
b.TYPE blocked_lock_type,
|
||||
decode(b.request,
|
||||
0,
|
||||
'none',
|
||||
1,
|
||||
null,
|
||||
2,
|
||||
'row-S (SS)',
|
||||
3,
|
||||
'row-X (SX)',
|
||||
4,
|
||||
'share (S)',
|
||||
5,
|
||||
'S/Row-X (SSX)',
|
||||
6,
|
||||
'exclusive (X)') blocked_lock_request,
|
||||
b_s.SCHEMANAME blocked_SCHEMANAME,
|
||||
b_s.MODULE blocked_module,
|
||||
b_s.STATUS blocked_status,
|
||||
b_s.SQL_ID blocked_sql_id,
|
||||
obj.owner blocked_owner,
|
||||
obj.object_name blocked_object_name,
|
||||
obj.OBJECT_TYPE blocked_OBJECT_TYPE,
|
||||
case
|
||||
when b_s.ROW_WAIT_OBJ# <> -1 then
|
||||
dbms_rowid.rowid_create(1,
|
||||
obj.DATA_OBJECT_ID,
|
||||
b_s.ROW_WAIT_FILE#,
|
||||
b_s.ROW_WAIT_BLOCK#,
|
||||
b_s.ROW_WAIT_ROW#)
|
||||
else
|
||||
'-1'
|
||||
end blocked_rowid, --被阻塞数据的rowid
|
||||
decode(obj.object_type,
|
||||
'TABLE',
|
||||
'select * from ' || obj.owner || '.' || obj.object_name ||
|
||||
' where rowid=''' ||
|
||||
dbms_rowid.rowid_create(1,
|
||||
obj.DATA_OBJECT_ID,
|
||||
b_s.ROW_WAIT_FILE#,
|
||||
b_s.ROW_WAIT_BLOCK#,
|
||||
b_s.ROW_WAIT_ROW#) || '''',
|
||||
NULL) blocked_data_querysql
|
||||
from gv$lock a,
|
||||
gv$lock b,
|
||||
gv$session a_s,
|
||||
gv$session b_s,
|
||||
dba_objects obj
|
||||
where a.id1 = b.id1
|
||||
and a.id2 = b.id2
|
||||
and a.BLOCK > 0 --阻塞了其他人
|
||||
and b.request > 0
|
||||
and ((a.INST_ID = b.INST_ID and a.sid <> b.sid) or
|
||||
(a.INST_ID <> b.INST_ID))
|
||||
and a.sid = a_s.sid
|
||||
and a.INST_ID = a_s.INST_ID
|
||||
and b.sid = b_s.sid
|
||||
and b.INST_ID = b_s.INST_ID
|
||||
and b_s.ROW_WAIT_OBJ# = obj.object_id(+)
|
||||
order by a.inst_id, a.sid
|
||||
) t -- 包裹一层,避免杀进程语句重复
|
||||
]]>
|
||||
</select>
|
||||
|
||||
<update id="killSession" parameterType="java.lang.String">
|
||||
alter system kill session '${sessionStr}'
|
||||
</update>
|
||||
|
|
|
@ -20,5 +20,8 @@ public enum DataSourceType
|
|||
Db1,
|
||||
Db2,
|
||||
Db3,
|
||||
Db4;
|
||||
Db4,
|
||||
Db5,
|
||||
hitapp
|
||||
;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
APP_NAME=ruoyi-admin-neuhisutools.jar
|
||||
PID=$(ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}')
|
||||
JVM="-server -Xms1g -Xmx4g -Xmn1g -verbose:gc-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=5 -XX:+ExplicitGCInvokesConcurrent -XX:GCTimeRatio=19 -XX:CMSInitiatingOccupancyFraction=70 -XX:CMSFullGCsBeforeCompaction=0 -Xnoclassgc -XX:SoftRefLRUPolicyMSPerMB=0"
|
||||
|
||||
if [ "$PID" != "" ]; then
|
||||
echo '================>停止服务..........'
|
||||
kill -9 $PID
|
||||
sleep 3s
|
||||
fi
|
||||
|
||||
echo '================>nohup.out日志清空成功.........'
|
||||
echo '' > nohup.out
|
||||
echo '================>开始重启服务.........'
|
||||
|
||||
nohup java $JVM -jar $APP_NAME 2>&1 &
|
||||
tail -f nohup.out
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
echo '================>停止服务开始..........'
|
||||
APP_NAME=ruoyi-admin-neuhisutools.jar
|
||||
PID=$(ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}')
|
||||
if [ "$PID" != "" ]; then
|
||||
echo '================>停止服务结束..........'
|
||||
kill -9 ${PID}
|
||||
sleep 3s
|
||||
fi
|
||||
|
Loading…
Reference in New Issue