diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index cfd6010a5..29d594b95 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -9,7 +9,7 @@
4.0.0
jar
- ruoyi-admin
+ ruoyi-admin-neuhisutools
web服务入口
diff --git a/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLock.java b/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLock.java
index 6c9d9c0da..eb4ec2141 100644
--- a/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLock.java
+++ b/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLock.java
@@ -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;
- }
}
diff --git a/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLockRac.java b/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLockRac.java
new file mode 100644
index 000000000..1010745d9
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/neuhis/his/domain/dto/DeadLockRac.java
@@ -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;
+ }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/neuhis/his/mapper/OracleSysMapper.java b/ruoyi-admin/src/main/java/com/neuhis/his/mapper/OracleSysMapper.java
index 7e1b9fac7..4048a62be 100644
--- a/ruoyi-admin/src/main/java/com/neuhis/his/mapper/OracleSysMapper.java
+++ b/ruoyi-admin/src/main/java/com/neuhis/his/mapper/OracleSysMapper.java
@@ -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 getDeadLockSession();
+ /**
+ * 简版: 获取死锁进程
+ * 主要用途是识别出那些已经处于等待锁状态超过5分钟并且当前是活跃的数据库会话,
+ * 这对于诊断和解决数据库死锁或长时间运行的事务问题非常有用
+ */
+ List getDeadLockSessionV1();
+ /**
+ * RAC方式,获取死锁对象
+ * --查询跟踪卡顿的阻塞锁会话进程SQL(集群RAC),速度很快
+ * --解释:从 RAC(Real Application Clusters)环境中获取当前存在锁争用(blocking locks)的会话信息。查询结果提供了关于阻塞会话的各种细节,包括锁定的对象、会话状态、等待时间和可能的解锁命令等
+ * --查杀步骤:查看【等待时间】最长,【RAC_KILL】 != 的进行 杀进程
+ * --查询跟踪卡顿的阻塞锁会话进程SQL
+ */
+ List getDeadLockSessionV2Rac();
+ /**
+ * Slow版本
+ */
+ List getDeadLockSessionV3Slow();
+
+ /**
+ * 形如:ALTER SYSTEM KILL SESSION '4150,14295,@1' immediate ;
+ * @param sessionStr '4150,14295,@1'
+ */
void killSession(String sessionStr);
}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/neuhis/his/service/IOracleSysService.java b/ruoyi-admin/src/main/java/com/neuhis/his/service/IOracleSysService.java
index 9b8b08f0b..63b5e4c9b 100644
--- a/ruoyi-admin/src/main/java/com/neuhis/his/service/IOracleSysService.java
+++ b/ruoyi-admin/src/main/java/com/neuhis/his/service/IOracleSysService.java
@@ -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 getDeadLockSession();
+ /**
+ * 简易版查询,速度很快
+ */
+ List getDeadLockSessionV1();
+ /**
+ * RAC版本,速度很快
+ */
+ List getDeadLockSessionV2Rac();
+ /**
+ * slow版本
+ */
+ List getDeadLockSessionV3Slow();
void killSession(String sessionStr);
}
diff --git a/ruoyi-admin/src/main/java/com/neuhis/his/service/impl/OracleSysServiceImpl.java b/ruoyi-admin/src/main/java/com/neuhis/his/service/impl/OracleSysServiceImpl.java
index c7416525d..58ca2a12e 100644
--- a/ruoyi-admin/src/main/java/com/neuhis/his/service/impl/OracleSysServiceImpl.java
+++ b/ruoyi-admin/src/main/java/com/neuhis/his/service/impl/OracleSysServiceImpl.java
@@ -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 getDeadLockSession() {
- return oracleSysMapper.getDeadLockSession();
+ public List getDeadLockSessionV1() {
+ return oracleSysMapper.getDeadLockSessionV1();
+ }
+
+ @Override
+ public List getDeadLockSessionV2Rac() {
+ List deadLockRacs = oracleSysMapper.getDeadLockSessionV2Rac();
+ return this.findV2DeadLockRacSessionId(deadLockRacs);
+ }
+
+ @Override
+ public List 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 findV2DeadLockRacSessionId(List 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 deadlockList) {
+ Map 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());
+ }
+ }
}
diff --git a/ruoyi-admin/src/main/java/com/neuhis/quartz/task/HisTask.java b/ruoyi-admin/src/main/java/com/neuhis/quartz/task/HisTask.java
index ac9be09c7..4ec79991b 100644
--- a/ruoyi-admin/src/main/java/com/neuhis/quartz/task/HisTask.java
+++ b/ruoyi-admin/src/main/java/com/neuhis/quartz/task/HisTask.java
@@ -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 deadLocks = oracleSysService.getDeadLockSessionV1();
+ ///deadLocks.forEach(deadLock -> HisTask.this.oracleSysService.killSession(deadLock.getSessionStr()));
+
+ List 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"));
+ }
+ }
+
/*
* 定时删除日志表数据
* */
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
deleted file mode 100644
index a69d8feb2..000000000
--- a/ruoyi-admin/src/main/resources/application-druid.yml
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-xyzxhis.yml b/ruoyi-admin/src/main/resources/application-xyzxhis.yml
index dff909c16..705a03930 100644
--- a/ruoyi-admin/src/main/resources/application-xyzxhis.yml
+++ b/ruoyi-admin/src/main/resources/application-xyzxhis.yml
@@ -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
# 最小连接池数量
diff --git a/ruoyi-admin/src/main/resources/mapper/his/OracleSysMapper.xml b/ruoyi-admin/src/main/resources/mapper/his/OracleSysMapper.xml
index 8a695aa65..bece6f8d5 100644
--- a/ruoyi-admin/src/main/resources/mapper/his/OracleSysMapper.xml
+++ b/ruoyi-admin/src/main/resources/mapper/his/OracleSysMapper.xml
@@ -3,7 +3,7 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-