最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實現(xiàn)對數(shù)據(jù)庫慢查詢監(jiān)控的方案小結(jié)

 更新時間:2025年06月03日 08:32:10   作者:風象南  
在企業(yè)級應(yīng)用開發(fā)中,數(shù)據(jù)庫性能往往是系統(tǒng)整體性能的關(guān)鍵瓶頸,因此,對數(shù)據(jù)庫慢查詢進行有效監(jiān)控和及時優(yōu)化,是保障系統(tǒng)穩(wěn)定運行的重要環(huán)節(jié),下面我們來看看SpringBoot實現(xiàn)慢查詢的6種監(jiān)控方案吧

在企業(yè)級應(yīng)用開發(fā)中,數(shù)據(jù)庫性能往往是系統(tǒng)整體性能的關(guān)鍵瓶頸。慢查詢不僅會影響用戶體驗,還可能導致連接池耗盡,進而引發(fā)系統(tǒng)雪崩。

因此,對數(shù)據(jù)庫慢查詢進行有效監(jiān)控和及時優(yōu)化,是保障系統(tǒng)穩(wěn)定運行的重要環(huán)節(jié)。

本文將介紹6種在SpringBoot應(yīng)用中實現(xiàn)慢查詢監(jiān)控的方案。

一、數(shù)據(jù)庫原生慢查詢?nèi)罩?/h2>

原理概述

幾乎所有主流關(guān)系型數(shù)據(jù)庫都提供了內(nèi)置的慢查詢?nèi)罩竟δ?,通過設(shè)置閾值,將執(zhí)行時間超過閾值的SQL記錄到專門的日志文件中。

實現(xiàn)方式

以MySQL為例:

1. 配置慢查詢?nèi)罩?/strong>

修改MySQL配置文件(my.cnf):

# 開啟慢查詢?nèi)罩?
slow_query_log = 1
# 慢查詢?nèi)罩疚募恢?
slow_query_log_file = /var/log/mysql/mysql-slow.log
# 設(shè)置慢查詢閾值(秒)
long_query_time = 1
# 記錄沒有使用索引的查詢
log_queries_not_using_indexes = 1

2. 在SpringBoot中查看慢查詢?nèi)罩?/strong>

@Repository
public class SlowQueryAnalyzer {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public List<Map<String, Object>> getSlowQueries() {
        String sql = "SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 100";
        return jdbcTemplate.queryForList(sql);
    }
    
    public void analyzeSlowQueries() {
        String sql = "SELECT COUNT(*) as count, db, sql_text, AVG(query_time) as avg_time " +
                     "FROM mysql.slow_log " +
                     "GROUP BY db, sql_text " +
                     "ORDER BY avg_time DESC " +
                     "LIMIT 10";
        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
        
        // 處理結(jié)果...
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 零代碼侵入,無需修改應(yīng)用代碼
  • 數(shù)據(jù)庫原生支持,準確性高
  • 可捕獲所有慢查詢,包括非應(yīng)用發(fā)起的查詢

缺點:

  • 需要數(shù)據(jù)庫管理員權(quán)限配置
  • 增加數(shù)據(jù)庫I/O負擔,生產(chǎn)環(huán)境需謹慎使用
  • 日志分析需要額外工具支持
  • 無法與應(yīng)用上下文關(guān)聯(lián)(如調(diào)用方法、請求URL等)

適用場景

• 開發(fā)和測試環(huán)境的問題排查

• 對數(shù)據(jù)庫有完全控制權(quán)的場景

• 需要捕獲所有數(shù)據(jù)庫操作的場景

• 基礎(chǔ)設(shè)施層面的監(jiān)控需求

二、基于AOP的慢查詢監(jiān)控

原理概述

利用Spring AOP機制,在Repository方法執(zhí)行前后添加切面,計算執(zhí)行時間并記錄超過閾值的方法調(diào)用。

實現(xiàn)方式

1. 添加AOP依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 創(chuàng)建慢查詢監(jiān)控切面

@Aspect
@Component
@Slf4j
public class SlowQueryAspect {
    
    @Value("${slow.query.threshold:500}")
    private long slowQueryThreshold; // 默認閾值500毫秒
    
    @Around("execution(* com.example.repository.*.*(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        long startTime = System.currentTimeMillis();
        
        Object result = joinPoint.proceed();
        
        long executionTime = System.currentTimeMillis() - startTime;
        
        if (executionTime > slowQueryThreshold) {
            String args = Arrays.toString(joinPoint.getArgs());
            log.warn("Slow Query detected: {} with args {}, execution time: {} ms", 
                    methodName, args, executionTime);
            
            // 可以將慢查詢信息保存到數(shù)據(jù)庫或發(fā)送告警
            saveSlowQueryInfo(methodName, args, executionTime);
        }
        
        return result;
    }
    
    private void saveSlowQueryInfo(String methodName, String args, long executionTime) {
        // 保存慢查詢信息到數(shù)據(jù)庫或發(fā)送到監(jiān)控系統(tǒng)
    }
}

3. 創(chuàng)建慢查詢事件監(jiān)聽器(可選)

@Component
@Slf4j
public class SlowQueryEventListener {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void onSlowQuery(String methodName, String args, long executionTime) {
        SlowQueryEvent event = new SlowQueryEvent(this, methodName, args, executionTime);
        eventPublisher.publishEvent(event);
    }
    
    @EventListener
    public void handleSlowQueryEvent(SlowQueryEvent event) {
        // 處理慢查詢事件,如發(fā)送告警郵件、存儲到時序數(shù)據(jù)庫等
        log.warn("Handling slow query event: {}", event);
    }
}

@Getter
public class SlowQueryEvent extends ApplicationEvent {
    private final String methodName;
    private final String args;
    private final long executionTime;
    
    public SlowQueryEvent(Object source, String methodName, String args, long executionTime) {
        super(source);
        this.methodName = methodName;
        this.args = args;
        this.executionTime = executionTime;
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 實現(xiàn)簡單,代碼侵入性低
  • 可以捕獲完整的方法調(diào)用上下文
  • 靈活可定制,可以根據(jù)需求調(diào)整監(jiān)控策略
  • 可以與應(yīng)用現(xiàn)有的監(jiān)控系統(tǒng)集成

缺點:

  • 只能監(jiān)控應(yīng)用代碼中的查詢,無法監(jiān)控原生SQL
  • 性能開銷較大,特別是在高并發(fā)場景
  • 可能出現(xiàn)AOP失效的場景(如內(nèi)部方法調(diào)用)
  • 無法獲取到實際執(zhí)行的SQL語句

適用場景

• 小型應(yīng)用或并發(fā)量不大的系統(tǒng)

• 需要監(jiān)控特定Repository方法性能的場景

• 開發(fā)或測試環(huán)境的性能調(diào)優(yōu)

• 已經(jīng)廣泛使用Spring AOP的項目

三、Spring Boot Actuator + Micrometer

原理概述

利用Spring Boot Actuator和Micrometer提供的指標收集功能,監(jiān)控數(shù)據(jù)庫操作性能,并將數(shù)據(jù)導出到監(jiān)控系統(tǒng)。

實現(xiàn)方式

1. 添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

2. 配置Actuator和數(shù)據(jù)源監(jiān)控

application.properties中添加:

# 開啟所有Actuator端點
management.endpoints.web.exposure.include=*
# 啟用數(shù)據(jù)庫指標收集
management.metrics.enable.jdbc=true
# 配置Prometheus端點
management.metrics.export.prometheus.enabled=true

3. 自定義數(shù)據(jù)源代理,添加指標收集

@Configuration
public class DataSourceProxyConfig {
    
    @Bean
    @Primary
    public DataSource dataSource(DataSource originalDataSource, MeterRegistry meterRegistry) {
        return ProxyDataSourceBuilder
                .create(originalDataSource)
                .name("metrics-ds")
                .listener(new QueryExecutionListener() {
                    @Override
                    public void beforeQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
                        // 查詢執(zhí)行前的操作
                    }
                    
                    @Override
                    public void afterQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
                        long elapsedTime = execInfo.getElapsedTime();
                        
                        // 記錄查詢時間指標
                        Timer.builder("datasource.query.time")
                                .tag("success", String.valueOf(execInfo.isSuccess()))
                                .tag("query", getSafeQueryName(queryInfoList))
                                .register(meterRegistry)
                                .record(elapsedTime, TimeUnit.MILLISECONDS);
                        
                        // 檢測慢查詢并記錄
                        if (elapsedTime > 500) { // 500ms閾值
                            Counter.builder("datasource.slow.queries")
                                    .tag("query", getSafeQueryName(queryInfoList))
                                    .register(meterRegistry)
                                    .increment();
                            
                            // 可以記錄慢查詢?nèi)罩?
                            logSlowQuery(execInfo, queryInfoList);
                        }
                    }
                    
                    private String getSafeQueryName(List<QueryInfo> queryInfoList) {
                        if (queryInfoList.isEmpty()) {
                            return "unknown";
                        }
                        
                        String sql = queryInfoList.get(0).getQuery();
                        // 簡化SQL以避免過多的唯一標簽
                        return DigestUtils.md5DigestAsHex(sql.getBytes()).substring(0, 8);
                    }
                    
                    private void logSlowQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
                        // 記錄慢查詢詳情
                    }
                })
                .build();
    }
}

ProxyDataSourceBuilder 來自開源庫datasource-proxy,datasource-proxy可以用于 JDBC 數(shù)據(jù)源的代理,可以用來攔截和監(jiān)控 SQL 查詢執(zhí)行,實現(xiàn) SQL 日志記錄、性能監(jiān)控、查詢統(tǒng)計等功能。

<dependency>
    <groupId>net.ttddyy</groupId>
    <artifactId>datasource-proxy</artifactId>
    <version>1.9</version>
</dependency>

4. 創(chuàng)建自定義端點查看慢查詢

@Component
@Endpoint(id = "slowqueries")
public class SlowQueryEndpoint {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @ReadOperation
    public Map<String, Object> slowQueries() {
        Map<String, Object> result = new HashMap<>();
        
        // 獲取慢查詢計數(shù)器
        List<Meter> meters = meterRegistry.getMeters().stream()
                .filter(m -> m.getId().getName().equals("datasource.slow.queries"))
                .collect(Collectors.toList());
        
        Map<String, Double> queryCounts = new HashMap<>();
        
        for (Meter meter : meters) {
            String query = meter.getId().getTag("query");
            double count = ((Counter) meter).count();
            queryCounts.put(query, count);
        }
        
        result.put("counts", queryCounts);
        
        // 獲取慢查詢時間分布
        List<Meter> timers = meterRegistry.getMeters().stream()
                .filter(m -> m.getId().getName().equals("datasource.query.time"))
                .collect(Collectors.toList());
        
        Map<String, Map<String, Object>> queryTimes = new HashMap<>();
        
        for (Meter meter : timers) {
            String query = meter.getId().getTag("query");
            Timer timer = (Timer) meter;
            
            Map<String, Object> stats = new HashMap<>();
            stats.put("count", timer.count());
            stats.put("max", timer.max(TimeUnit.MILLISECONDS));
            stats.put("mean", timer.mean(TimeUnit.MILLISECONDS));
            stats.put("percentile95", timer.takeSnapshot().percentileValues()[0].value(TimeUnit.MILLISECONDS));
            
            queryTimes.put(query, stats);
        }
        
        result.put("times", queryTimes);
        
        return result;
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 與Spring Boot生態(tài)緊密集成
  • 支持多種監(jiān)控系統(tǒng),如Prometheus、Grafana等
  • 提供豐富的指標和可視化能力
  • 運行時監(jiān)控,影響生產(chǎn)代碼較小

缺點:

  • 配置相對復雜
  • 資源消耗較大,特別是在大量指標收集的情況下
  • 需要額外的監(jiān)控系統(tǒng)支持
  • 學習成本較高

適用場景

• 中大型微服務(wù)架構(gòu)

• 已經(jīng)使用Prometheus + Grafana等監(jiān)控系統(tǒng)的團隊

• 需要全面監(jiān)控系統(tǒng)性能的場景

• 對指標和可視化有較高要求的項目

四、使用P6Spy進行SQL性能監(jiān)控

原理概述

P6Spy是一個開源的JDBC代理框架,能夠攔截JDBC操作并記錄SQL語句的執(zhí)行情況,包括執(zhí)行時間、參數(shù)等信息。

實現(xiàn)方式

1. 添加依賴

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

2. 配置數(shù)據(jù)源

修改數(shù)據(jù)源配置,將驅(qū)動類替換為P6Spy的代理驅(qū)動:

# 原始配置
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/test

# P6Spy配置
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/test

3. 創(chuàng)建P6Spy配置文件

resources目錄下創(chuàng)建spy.properties文件:

# 指定日志輸出模塊
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 日志格式
logMessageFormat=com.example.config.CustomP6SpyLogFormat
# 是否開啟慢SQL記錄
outagedetection=true
# 慢SQL閾值(毫秒)
outagedetectioninterval=2000
# 設(shè)置 p6spy driver 代理
deregisterdrivers=true
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 實際驅(qū)動
driverlist=com.mysql.cj.jdbc.Driver

4. 自定義日志格式化器

package com.example.config;

import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class CustomP6SpyLogFormat implements MessageFormattingStrategy {
    
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    @Override
    public String formatMessage(int connectionId, String now, long elapsed, String category,
                               String prepared, String sql, String url) {
        return StringUtils.hasText(sql) ? 
                LocalDateTime.now().format(formatter) + 
                " | " + elapsed + "ms | " + category + 
                " | connection " + connectionId + 
                " | " + sql : "";
    }
}

5. 創(chuàng)建P6Spy慢查詢監(jiān)聽器

package com.example.config;

import com.p6spy.engine.common.ConnectionInformation;
import com.p6spy.engine.event.JdbcEventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class SlowQueryListener extends JdbcEventListener {
    
    @Value("${sql.slow.threshold:500}")
    private long slowThreshold; // 默認500毫秒
    
    @Override
    public void onAfterAnyExecute(ConnectionInformation connectionInformation, long timeElapsedNanos, SQLException e) {
        long timeElapsedMillis = TimeUnit.NANOSECONDS.toMillis(timeElapsedNanos);
        
        if (timeElapsedMillis > slowThreshold) {
            String query = connectionInformation.getSqlWithValues();
            log.warn("Slow SQL detected: {} ms, SQL: {}", timeElapsedMillis, query);
            
            // 可以記錄到數(shù)據(jù)庫或發(fā)送告警
            saveSlowQuery(query, timeElapsedMillis);
        }
    }
    
    private void saveSlowQuery(String query, long timeElapsed) {
        // 保存慢查詢記錄到數(shù)據(jù)庫或告警系統(tǒng)
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 能夠獲取完整的SQL語句和參數(shù)值
  • 配置簡單,幾乎零代碼侵入
  • 可以監(jiān)控所有JDBC操作,包括非ORM框架的查詢
  • 提供豐富的自定義選項

缺點:

  • 對性能有一定影響,不建議在高負載生產(chǎn)環(huán)境長期開啟
  • 日志量較大,需要合理配置
  • 可能與某些特定數(shù)據(jù)庫驅(qū)動不兼容
  • 不提供內(nèi)置的圖形化監(jiān)控界面

適用場景

• 開發(fā)和測試環(huán)境的SQL調(diào)優(yōu)

• 需要詳細了解SQL執(zhí)行情況的場景

• 排查特定SQL問題的臨時監(jiān)控

• 對SQL執(zhí)行參數(shù)有監(jiān)控需求的場景

五、基于APM工具的慢查詢監(jiān)控

原理概述

應(yīng)用性能監(jiān)控(APM)工具如SkyWalking、Pinpoint、Elastic APM等通過Java Agent技術(shù)在字節(jié)碼級別插樁,實現(xiàn)對數(shù)據(jù)庫操作的全方位監(jiān)控。

實現(xiàn)方式

以SkyWalking為例:

1. 下載SkyWalking Agent

從SkyWalking官網(wǎng)下載Agent包。

2. 配置Java Agent

在啟動命令中添加:

java -javaagent:/path/to/skywalking-agent.jar -Dskywalking.agent.service_name=your-service-name -jar your-application.jar

或在Spring Boot應(yīng)用中通過環(huán)境變量配置:

# application.yml
spring:
  application:
    name: your-service-name

3. 配置SkyWalking Agent

修改agent.config文件:

# 設(shè)置后端服務(wù)地址
collector.backend_service=localhost:11800
# 啟用SQL跟蹤
plugin.jdbc.trace_sql=true
# 設(shè)置慢SQL閾值
plugin.jdbc.slow_sql_threshold=1000

4. 集成SkyWalking API(可選)

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>8.7.0</version>
</dependency>
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public User findUserById(Long id) {
        // 添加自定義Tag
        ActiveSpan.tag("userId", id.toString());
        
        // 獲取traceId,可用于日志關(guān)聯(lián)
        String traceId = TraceContext.traceId();
        log.info("Processing user query with traceId: {}", traceId);
        
        return userRepository.findById(id).orElse(null);
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 全方位監(jiān)控,包括HTTP請求、數(shù)據(jù)庫操作、遠程調(diào)用等
  • 分布式追蹤能力,可以跟蹤完整調(diào)用鏈
  • 零代碼侵入(基礎(chǔ)功能)
  • 提供豐富的可視化界面和告警功能
  • 支持多種存儲后端(ElasticSearch、MySQL等)

缺點:

  • 部署復雜,需要額外維護監(jiān)控服務(wù)器
  • 資源消耗較大,增加應(yīng)用內(nèi)存占用
  • 學習成本較高
  • 可能與某些安全策略沖突(如禁止Java Agent)

適用場景

• 中大型分布式系統(tǒng)

• 微服務(wù)架構(gòu)應(yīng)用

• 需要完整分布式追蹤的場景

• 生產(chǎn)環(huán)境監(jiān)控

• 需要同時監(jiān)控多種性能指標的場景

六、基于Druid連接池的慢查詢監(jiān)控

原理概述

阿里巴巴開源的Druid連接池內(nèi)置了強大的監(jiān)控功能,包括慢查詢統(tǒng)計、SQL防火墻等。

實現(xiàn)方式

1. 添加依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>

2. 配置Druid

application.properties中添加:

# 數(shù)據(jù)源類型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/test
spring.datasource.druid.username=root
spring.datasource.druid.password=password

# 連接池配置
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000

# 慢SQL監(jiān)控配置
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=1000
spring.datasource.druid.filter.stat.merge-sql=true

# 開啟監(jiān)控頁面
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1
spring.datasource.druid.stat-view-servlet.deny=

# 開啟Web應(yīng)用監(jiān)控
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*

# 開啟Spring監(jiān)控
spring.datasource.druid.aop-patterns=com.example.service.*,com.example.repository.*

3. 配置Druid監(jiān)控(Java Config方式)

@Configuration
public class DruidConfig {
    
    @Bean
    public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() {
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        
        Map<String, String> initParams = new HashMap<>();
        initParams.put("loginUsername", "admin");
        initParams.put("loginPassword", "admin");
        initParams.put("allow", "127.0.0.1");
        
        bean.setInitParameters(initParams);
        return bean;
    }
    
    @Bean
    public FilterRegistrationBean<WebStatFilter> druidWebStatFilter() {
        FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>(new WebStatFilter());
        
        Map<String, String> initParams = new HashMap<>();
        initParams.put("exclusions", "*.js,*.css,/druid/*");
        
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Collections.singletonList("/*"));
        
        return bean;
    }
    
    @Bean
    @ConfigurationProperties("spring.datasource.druid.filter.stat")
    public StatFilter statFilter() {
        StatFilter filter = new StatFilter();
        filter.setSlowSqlMillis(1000);
        filter.setLogSlowSql(true);
        filter.setMergeSql(true);
        return filter;
    }
    
    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        return new DruidStatInterceptor();
    }
    
    @Bean
    public BeanNameAutoProxyCreator druidStatProxyCreator() {
        BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
        creator.setProxyTargetClass(true);
        creator.setBeanNames("*Service", "*ServiceImpl", "*Repository");
        creator.setInterceptorNames("druidStatInterceptor");
        return creator;
    }
}

4. 自定義慢查詢監(jiān)聽器(可選)

@Component
public class DruidSlowSqlListener implements ApplicationListener<ContextRefreshedEvent> {
    
    @Autowired
    private DruidDataSource dataSource;
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        dataSource.setConnectionProperties("druid.stat.slowSqlMillis=1000");
        
        StatFilter statFilter = new StatFilter();
        statFilter.setLogSlowSql(true);
        statFilter.setSlowSqlMillis(1000);
        statFilter.setMergeSql(true);
        
        statFilter.setSlowSqlLoggerName("SLOW_SQL_LOGGER");
        
        dataSource.getProxyFilters().add(statFilter);
    }
}

5. 自定義慢查詢Controller(可選)

@RestController
@RequestMapping("/api/monitor")
public class DruidMonitorController {
    
    @Autowired
    private DruidDataSource dataSource;
    
    @GetMapping("/slow-sql")
    public List<Map<String, Object>> getSlowSql() {
        List<Map<String, Object>> result = new ArrayList<>();
        
        try {
            JdbcStatManager statManager = JdbcStatManager.getInstance();
            for (Object item : statManager.getDataSourceList().values()) {
                JdbcDataSourceStat dataSourceStat = (JdbcDataSourceStat) item;
                Map<String, JdbcSqlStat> sqlStatMap = dataSourceStat.getSqlStatMap();
                
                for (Map.Entry<String, JdbcSqlStat> entry : sqlStatMap.entrySet()) {
                    JdbcSqlStat sqlStat = entry.getValue();
                    
                    if (sqlStat.getExecuteMillisMax() > 1000) {
                        Map<String, Object> slowSql = new HashMap<>();
                        slowSql.put("sql", sqlStat.getSql());
                        slowSql.put("executionCount", sqlStat.getExecuteCount());
                        slowSql.put("maxTime", sqlStat.getExecuteMillisMax());
                        slowSql.put("avgTime", sqlStat.getExecuteMillisTotal() / sqlStat.getExecuteCount());
                        
                        result.add(slowSql);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return result;
    }
}

優(yōu)缺點分析

優(yōu)點:

  • 集成度高,開箱即用
  • 自帶可視化監(jiān)控界面
  • 功能全面,除慢查詢外還有連接池監(jiān)控、SQL防火墻等

缺點:

  • 僅適用于使用Druid連接池的場景
  • 與其他監(jiān)控系統(tǒng)集成需要額外開發(fā)
  • 默認監(jiān)控頁面功能固定,不易擴展
  • 安全配置較為重要,否則可能泄露敏感信息

適用場景

• 對數(shù)據(jù)庫性能有全面監(jiān)控需求的場景

• 需要開箱即用監(jiān)控功能的項目

• 小型到中型規(guī)模的應(yīng)用

• 對監(jiān)控數(shù)據(jù)安全性有要求的場景

七、方案對比

方案實現(xiàn)復雜度代碼侵入性性能影響監(jiān)控全面性可視化能力
數(shù)據(jù)庫原生慢查詢?nèi)罩?/td>
基于AOP的監(jiān)控
Spring Boot Actuator + Micrometer高(需外部系統(tǒng))
P6Spy中高
APM工具(SkyWalking等)中高極高
Druid連接池

總結(jié)

慢查詢監(jiān)控是數(shù)據(jù)庫性能優(yōu)化的重要環(huán)節(jié),選擇合適的監(jiān)控方案對于提升應(yīng)用性能至關(guān)重要。

在實際應(yīng)用中,可以根據(jù)項目規(guī)模、技術(shù)棧和團隊能力選擇合適的方案,也可以組合使用多種方案,實現(xiàn)更全面的監(jiān)控覆蓋。隨著應(yīng)用的發(fā)展,監(jiān)控策略也應(yīng)該不斷演進和優(yōu)化,以適應(yīng)不斷變化的性能需求。

到此這篇關(guān)于SpringBoot實現(xiàn)對數(shù)據(jù)庫慢查詢監(jiān)控的方案小結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)庫慢查詢監(jiān)控內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JPA中@ElementCollection使用示例詳解

    JPA中@ElementCollection使用示例詳解

    在JPA中,@ElementCollection注解主要用于映射集合屬性,例如List、Set或數(shù)組等集合屬性,以及Map結(jié)構(gòu)的集合屬性,每個屬性值都有對應(yīng)的key映射,這篇文章主要介紹了JPA中@ElementCollection使用,需要的朋友可以參考下
    2023-11-11
  • SpringBoot時間格式化的方法小結(jié)

    SpringBoot時間格式化的方法小結(jié)

    SpringBoot中的時間格式化通常指的是將Java中的日期時間類型轉(zhuǎn)換為指定格式的字符串,或者將字符串類型的時間解析為Java中的日期時間類型,本文小編將給大家詳細總結(jié)了SpringBoot時間格式化的方法,剛興趣的小伙伴跟著小編一起來看看吧
    2023-10-10
  • Java中char[] 和 String 類型占用字節(jié)大小問題

    Java中char[] 和 String 類型占用字節(jié)大小問題

    這篇文章主要介紹了Java中char[] 和 String 類型占用字節(jié)大小問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • SpringBoot實現(xiàn)多端口監(jiān)聽的代碼示例

    SpringBoot實現(xiàn)多端口監(jiān)聽的代碼示例

    當你需要在同一個Spring Boot應(yīng)用中,通過不同的端口來提供不同的服務(wù)或功能時,就需要實現(xiàn)多端口監(jiān)聽,所以本文給大家介紹了SpringBoot實現(xiàn)多端口監(jiān)聽的方法示例,并有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-09-09
  • 詳解springBoot啟動時找不到或無法加載主類解決辦法

    詳解springBoot啟動時找不到或無法加載主類解決辦法

    這篇文章主要介紹了詳解springBoot啟動時找不到或無法加載主類解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • springboot實現(xiàn)單、多文件上傳過程(前后端都有)

    springboot實現(xiàn)單、多文件上傳過程(前后端都有)

    Spring Boot中實現(xiàn)文件上傳,前端使用`file`類型的`input`表單,后端通過`MultipartFile`類接收文件,上傳接口接收`MultipartFile`參數(shù),調(diào)用其方法處理文件,單文件上傳直接處理,多文件上傳需遍歷`MultipartFile`數(shù)組
    2025-12-12
  • Netty?拆包沾包問題解決方案詳解

    Netty?拆包沾包問題解決方案詳解

    這篇文章主要為大家介紹了Netty?拆包沾包問題解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • JAVA實現(xiàn)的簡單萬年歷代碼

    JAVA實現(xiàn)的簡單萬年歷代碼

    這篇文章主要介紹了JAVA實現(xiàn)的簡單萬年歷代碼,涉及Java日期操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • springboot?通過博途獲取plc點位的數(shù)據(jù)代碼實現(xiàn)

    springboot?通過博途獲取plc點位的數(shù)據(jù)代碼實現(xiàn)

    這篇文章主要介紹了springboot?通過博途獲取plc點位的數(shù)據(jù)的代碼實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • spring boot教程之全局處理異常封裝

    spring boot教程之全局處理異常封裝

    這篇文章主要給大家介紹了關(guān)于spring boot教程之全局處理異常封裝的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用spring boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09

最新評論

夹江县| 双江| 乌鲁木齐县| 共和县| 琼结县| 基隆市| 敦化市| 丘北县| 汉源县| 驻马店市| 徐水县| 翼城县| 北京市| 元朗区| 江孜县| 高要市| 平安县| 资兴市| 鹤岗市| 济源市| 塔城市| 枣阳市| 都兰县| 胶南市| 鄢陵县| 凤庆县| 河东区| 宁乡县| 顺义区| 霍山县| 陆丰市| 乃东县| 临潭县| 营山县| 大渡口区| 南涧| 铁岭市| 辽宁省| 金坛市| 舒兰市| 青海省|