宇树Java面试被问:数据库死锁检测和自动回滚机制

一、死锁原理与检测机制

1. 死锁产生原理

sql

复制

下载

复制代码
-- 死锁产生的四个必要条件(Coffman条件):
-- 1. 互斥条件 (Mutual Exclusion)
-- 2. 持有并等待 (Hold and Wait) 
-- 3. 不可剥夺 (No Preemption)
-- 4. 循环等待 (Circular Wait)

-- 示例:典型的死锁场景
-- 事务T1:                  事务T2:
-- BEGIN;                   BEGIN;
-- UPDATE users SET ...    UPDATE products SET ...
-- WHERE id = 1;           WHERE id = 100;
--                         
-- UPDATE products SET ... UPDATE users SET ...
-- WHERE id = 100;         WHERE id = 1;
-- COMMIT;                 COMMIT;

2. 数据库死锁检测实现

java

复制

下载

复制代码
/**
 * 死锁检测算法实现
 */
public class DeadlockDetector {
    
    /**
     * 等待图(Wait-For Graph)算法
     * 将事务和锁等待关系建模为有向图
     */
    public static class WaitForGraph {
        
        // 节点:事务
        // 边:T1 -> T2 表示 T1 等待 T2 释放锁
        
        private final Map<String, Set<String>> graph = new ConcurrentHashMap<>();
        private final Object lock = new Object();
        
        /**
         * 添加等待关系
         * @param waiter 等待的事务
         * @param holder 持有锁的事务
         */
        public void addWaitFor(String waiter, String holder) {
            synchronized (lock) {
                graph.computeIfAbsent(waiter, k -> new HashSet<>()).add(holder);
                System.out.printf("Wait-for edge added: %s -> %s%n", waiter, holder);
                
                // 检查是否产生死锁
                if (hasCycle(waiter)) {
                    System.out.println("⚠️  Deadlock detected!");
                    resolveDeadlock(waiter);
                }
            }
        }
        
        /**
         * 移除等待关系
         */
        public void removeWaitFor(String waiter, String holder) {
            synchronized (lock) {
                Set<String> holders = graph.get(waiter);
                if (holders != null) {
                    holders.remove(holder);
                    if (holders.isEmpty()) {
                        graph.remove(waiter);
                    }
                }
            }
        }
        
        /**
         * 检测环路(深度优先搜索)
         */
        private boolean hasCycle(String startNode) {
            Set<String> visited = new HashSet<>();
            Set<String> recursionStack = new HashSet<>();
            
            return dfs(startNode, visited, recursionStack);
        }
        
        private boolean dfs(String node, Set<String> visited, Set<String> recursionStack) {
            if (recursionStack.contains(node)) {
                return true; // 发现环路
            }
            
            if (visited.contains(node)) {
                return false;
            }
            
            visited.add(node);
            recursionStack.add(node);
            
            Set<String> neighbors = graph.get(node);
            if (neighbors != null) {
                for (String neighbor : neighbors) {
                    if (dfs(neighbor, visited, recursionStack)) {
                        return true;
                    }
                }
            }
            
            recursionStack.remove(node);
            return false;
        }
        
        /**
         * 查找环路中的所有事务
         */
        private List<String> findCycle(String startNode) {
            Map<String, String> parent = new HashMap<>();
            Set<String> visited = new HashSet<>();
            
            Queue<String> queue = new LinkedList<>();
            queue.offer(startNode);
            visited.add(startNode);
            
            while (!queue.isEmpty()) {
                String current = queue.poll();
                Set<String> neighbors = graph.get(current);
                
                if (neighbors != null) {
                    for (String neighbor : neighbors) {
                        if (!visited.contains(neighbor)) {
                            visited.add(neighbor);
                            parent.put(neighbor, current);
                            queue.offer(neighbor);
                        } else if (neighbor.equals(startNode)) {
                            // 找到环路
                            return buildCyclePath(parent, current, startNode);
                        }
                    }
                }
            }
            
            return Collections.emptyList();
        }
        
        /**
         * 构建环路路径
         */
        private List<String> buildCyclePath(Map<String, String> parent, String end, String start) {
            List<String> cycle = new ArrayList<>();
            String current = end;
            
            while (current != null) {
                cycle.add(current);
                if (current.equals(start)) {
                    break;
                }
                current = parent.get(current);
            }
            
            Collections.reverse(cycle);
            cycle.add(start); // 闭合环路
            return cycle;
        }
        
        /**
         * 解决死锁
         */
        private void resolveDeadlock(String victimCandidate) {
            // 查找完整的环路
            List<String> cycle = findCycle(victimCandidate);
            
            if (cycle.isEmpty()) {
                System.out.println("No cycle found, false positive");
                return;
            }
            
            System.out.println("Deadlock cycle: " + String.join(" -> ", cycle));
            
            // 选择牺牲者(通常选择代价最小的事务)
            String victim = selectVictim(cycle);
            
            System.out.println("Selected victim: " + victim);
            
            // 回滚牺牲者事务
            rollbackTransaction(victim);
            
            // 清理等待图
            cleanupAfterRollback(victim);
        }
        
        /**
         * 选择牺牲者策略
         */
        private String selectVictim(List<String> cycle) {
            // 策略1: 选择最近开始的事务(最少工作丢失)
            // 策略2: 选择持有锁最少的事务
            // 策略3: 基于事务优先级
            // 策略4: 随机选择(简单但公平)
            
            Random random = new Random();
            return cycle.get(random.nextInt(cycle.size()));
        }
        
        private void rollbackTransaction(String transactionId) {
            System.out.println("Rolling back transaction: " + transactionId);
            // 实际实现中,这里会调用数据库的回滚机制
            // 例如:发送 ROLLBACK 命令
        }
        
        private void cleanupAfterRollback(String transactionId) {
            // 移除所有与该事务相关的边
            synchronized (lock) {
                // 移除该事务等待的边
                graph.remove(transactionId);
                
                // 移除其他事务等待该事务的边
                graph.values().forEach(holders -> holders.remove(transactionId));
                
                // 清理空的条目
                graph.entrySet().removeIf(entry -> entry.getValue().isEmpty());
            }
        }
        
        /**
         * 可视化等待图
         */
        public void visualizeGraph() {
            System.out.println("\n=== Wait-For Graph ===");
            graph.forEach((waiter, holders) -> {
                holders.forEach(holder -> {
                    System.out.printf("  %s -> %s%n", waiter, holder);
                });
            });
            System.out.println("=====================\n");
        }
    }
    
    /**
     * 超时检测算法
     */
    public static class TimeoutDetector {
        private final Map<String, Long> transactionStartTimes = new ConcurrentHashMap<>();
        private final long timeoutThreshold; // 毫秒
        
        public TimeoutDetector(long timeoutThreshold) {
            this.timeoutThreshold = timeoutThreshold;
        }
        
        public void startTransaction(String txId) {
            transactionStartTimes.put(txId, System.currentTimeMillis());
        }
        
        public void endTransaction(String txId) {
            transactionStartTimes.remove(txId);
        }
        
        public void checkTimeouts() {
            long currentTime = System.currentTimeMillis();
            
            transactionStartTimes.entrySet().removeIf(entry -> {
                long duration = currentTime - entry.getValue();
                if (duration > timeoutThreshold) {
                    System.out.printf("Transaction %s timed out after %dms%n", 
                                     entry.getKey(), duration);
                    rollbackTransaction(entry.getKey());
                    return true;
                }
                return false;
            });
        }
        
        private void rollbackTransaction(String txId) {
            System.out.println("Rolling back timed out transaction: " + txId);
        }
    }
}

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】

二、数据库自动死锁检测实现

1. MySQL 死锁检测与处理

sql

复制

下载

复制代码
-- MySQL 死锁相关配置和监控
SHOW VARIABLES LIKE '%deadlock%';
-- innodb_deadlock_detect: ON(默认开启死锁检测)
-- innodb_lock_wait_timeout: 50(默认50秒)

-- 查看死锁日志
SHOW ENGINE INNODB STATUS\G
-- 在输出中查找 "LATEST DETECTED DEADLOCK" 部分

-- 死锁信息表(MySQL 8.0+)
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

-- 死锁检测和处理的存储过程
DELIMITER $$

CREATE PROCEDURE monitor_and_handle_deadlocks()
BEGIN
    DECLARE deadlock_count INT DEFAULT 0;
    DECLARE victim_transaction VARCHAR(100);
    DECLARE done INT DEFAULT FALSE;
    
    -- 创建临时表存储死锁信息
    CREATE TEMPORARY TABLE IF NOT EXISTS temp_deadlocks (
        deadlock_id INT AUTO_INCREMENT PRIMARY KEY,
        transaction_id VARCHAR(100),
        waiting_query TEXT,
        blocking_query TEXT,
        detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
    
    -- 模拟死锁检测(实际中会解析 SHOW ENGINE INNODB STATUS)
    -- 这里简化为检查锁等待超时
    SELECT COUNT(*) INTO deadlock_count
    FROM information_schema.INNODB_TRX trx1
    JOIN information_schema.INNODB_LOCKS lock1 ON trx1.trx_id = lock1.lock_trx_id
    JOIN information_schema.INNODB_LOCKS lock2 ON lock1.lock_table = lock2.lock_table 
        AND lock1.lock_index = lock2.lock_index
        AND lock1.lock_trx_id != lock2.lock_trx_id
    WHERE TIMESTAMPDIFF(SECOND, trx1.trx_started, NOW()) > 30; -- 30秒超时
    
    IF deadlock_count > 0 THEN
        -- 记录死锁信息
        INSERT INTO temp_deadlocks (transaction_id, waiting_query, blocking_query)
        SELECT trx1.trx_id, trx1.trx_query, trx2.trx_query
        FROM information_schema.INNODB_TRX trx1
        JOIN information_schema.INNODB_LOCKS lock1 ON trx1.trx_id = lock1.lock_trx_id
        JOIN information_schema.INNODB_LOCKS lock2 ON lock1.lock_table = lock2.lock_table
        JOIN information_schema.INNODB_TRX trx2 ON lock2.lock_trx_id = trx2.trx_id
        WHERE TIMESTAMPDIFF(SECOND, trx1.trx_started, NOW()) > 30
        LIMIT 1;
        
        -- 选择牺牲者(选择开始时间最晚的)
        SELECT transaction_id INTO victim_transaction
        FROM temp_deadlocks
        ORDER BY detected_at DESC
        LIMIT 1;
        
        -- 这里实际需要调用 KILL 命令
        -- SET @kill_stmt = CONCAT('KILL ', victim_transaction);
        -- PREPARE kill_cmd FROM @kill_stmt;
        -- EXECUTE kill_cmd;
        
        -- 记录到死锁日志表
        INSERT INTO deadlock_logs (victim_transaction, deadlock_info, resolved_at)
        VALUES (victim_transaction, 
               CONCAT('Deadlock resolved automatically at ', NOW()),
               NOW());
        
        SELECT CONCAT('Deadlock resolved, victim: ', victim_transaction) AS result;
    ELSE
        SELECT 'No deadlock detected' AS result;
    END IF;
    
    DROP TEMPORARY TABLE IF EXISTS temp_deadlocks;
END$$

DELIMITER ;

-- 创建死锁日志表
CREATE TABLE IF NOT EXISTS deadlock_logs (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    victim_transaction VARCHAR(100),
    deadlock_info TEXT,
    resolved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_resolved_at (resolved_at)
);

-- 创建事件定期运行死锁检测
CREATE EVENT IF NOT EXISTS auto_deadlock_detector
ON SCHEDULE EVERY 10 SECOND
DO
    CALL monitor_and_handle_deadlocks();

-- 查看当前锁等待情况
SELECT 
    r.trx_id AS waiting_trx_id,
    r.trx_mysql_thread_id AS waiting_thread,
    r.trx_query AS waiting_query,
    b.trx_id AS blocking_trx_id,
    b.trx_mysql_thread_id AS blocking_thread,
    b.trx_query AS blocking_query,
    TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_time_seconds
FROM information_schema.INNODB_LOCK_WAITS w
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id;

2. PostgreSQL 死锁处理

sql

复制

下载

复制代码
-- PostgreSQL 死锁检测配置
SHOW deadlock_timeout; -- 默认 1s
-- PostgreSQL 每 deadlock_timeout 毫秒检查一次死锁

-- 查看当前锁信息
SELECT 
    locktype,
    database,
    relation::regclass,
    page,
    tuple,
    virtualxid,
    transactionid,
    classid,
    objid,
    objsubid,
    virtualtransaction,
    pid,
    mode,
    granted
FROM pg_locks
WHERE NOT granted;

-- 死锁检测查询
SELECT 
    w1.pid AS waiting_pid,
    w1.usename AS waiting_user,
    w1.query AS waiting_query,
    w2.pid AS blocking_pid,
    w2.usename AS blocking_user,
    w2.query AS blocking_query,
    w1.wait_event_type,
    w1.wait_event,
    age(now(), w1.query_start) AS waiting_duration
FROM pg_stat_activity w1
JOIN pg_locks l1 ON w1.pid = l1.pid AND NOT l1.granted
JOIN pg_locks l2 ON l1.relation = l2.relation AND l1.locktype = l2.locktype
JOIN pg_stat_activity w2 ON w2.pid = l2.pid AND l2.granted
WHERE w1.wait_event_type = 'Lock';

-- 自动死锁处理函数
CREATE OR REPLACE FUNCTION handle_deadlocks()
RETURNS void AS $$
DECLARE
    deadlock_record RECORD;
    victim_pid INT;
BEGIN
    -- 查找可能的死锁(长时间等待)
    FOR deadlock_record IN 
        SELECT 
            waiting.pid AS waiting_pid,
            blocking.pid AS blocking_pid,
            age(now(), waiting.query_start) AS wait_time,
            waiting.query AS waiting_query,
            blocking.query AS blocking_query
        FROM pg_stat_activity waiting
        JOIN pg_locks wl ON waiting.pid = wl.pid AND NOT wl.granted
        JOIN pg_locks bl ON wl.relation = bl.relation 
            AND wl.locktype = bl.locktype 
            AND wl.pid != bl.pid
        JOIN pg_stat_activity blocking ON blocking.pid = bl.pid AND bl.granted
        WHERE waiting.wait_event_type = 'Lock'
            AND age(now(), waiting.query_start) > INTERVAL '30 seconds'
        LIMIT 1
    LOOP
        -- 记录死锁信息
        INSERT INTO deadlock_history (
            waiting_pid, 
            blocking_pid, 
            wait_time, 
            waiting_query,
            blocking_query,
            resolved_at
        ) VALUES (
            deadlock_record.waiting_pid,
            deadlock_record.blocking_pid,
            deadlock_record.wait_time,
            deadlock_record.waiting_query,
            deadlock_record.blocking_query,
            now()
        );
        
        -- 选择牺牲者(等待时间最长的)
        victim_pid := deadlock_record.waiting_pid;
        
        -- 终止进程(实际生产环境要谨慎)
        PERFORM pg_terminate_backend(victim_pid);
        
        RAISE NOTICE 'Deadlock resolved: terminated pid %', victim_pid;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- 创建死锁历史表
CREATE TABLE IF NOT EXISTS deadlock_history (
    id SERIAL PRIMARY KEY,
    waiting_pid INT,
    blocking_pid INT,
    wait_time INTERVAL,
    waiting_query TEXT,
    blocking_query TEXT,
    resolved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建自动执行的函数
SELECT cron.schedule(
    'deadlock-detector',  -- 任务名
    '* * * * *',          -- 每分钟执行
    $$SELECT handle_deadlocks()$$
);

3. 应用层死锁检测与处理

java

复制

下载

复制代码
/**
 * 应用层死锁检测管理器
 */
public class ApplicationDeadlockManager {
    
    /**
     * 分布式死锁检测器
     */
    public static class DistributedDeadlockDetector {
        private final Map<String, TransactionLockInfo> lockTable = new ConcurrentHashMap<>();
        private final ScheduledExecutorService detectorScheduler;
        private final long checkInterval;
        
        public DistributedDeadlockDetector(long checkInterval) {
            this.checkInterval = checkInterval;
            this.detectorScheduler = Executors.newSingleThreadScheduledExecutor();
            startDetection();
        }
        
        /**
         * 事务锁信息
         */
        static class TransactionLockInfo {
            String transactionId;
            String resourceId;
            LockType lockType;
            long timestamp;
            String appNodeId;
            Set<String> waitingFor = new HashSet<>();
            
            enum LockType {
                SHARED, EXCLUSIVE
            }
        }
        
        /**
         * 注册事务获取锁
         */
        public void acquireLock(String txId, String resourceId, 
                               TransactionLockInfo.LockType lockType) {
            TransactionLockInfo lockInfo = new TransactionLockInfo();
            lockInfo.transactionId = txId;
            lockInfo.resourceId = resourceId;
            lockInfo.lockType = lockType;
            lockInfo.timestamp = System.currentTimeMillis();
            lockInfo.appNodeId = getNodeId();
            
            lockTable.put(txId + ":" + resourceId, lockInfo);
            
            // 检查锁冲突
            checkLockConflict(txId, resourceId, lockType);
        }
        
        /**
         * 注册事务等待锁
         */
        public void waitForLock(String waiterTxId, String resourceId, 
                               String holderTxId) {
            String key = waiterTxId + ":" + resourceId;
            TransactionLockInfo info = lockTable.get(key);
            
            if (info != null) {
                info.waitingFor.add(holderTxId);
                
                // 构建全局等待图
                buildGlobalWaitForGraph();
            }
        }
        
        /**
         * 构建全局等待图(跨节点)
         */
        private void buildGlobalWaitForGraph() {
            // 收集所有节点的锁信息
            Map<String, Set<String>> globalGraph = new HashMap<>();
            
            // 本地锁信息
            lockTable.forEach((key, info) -> {
                if (!info.waitingFor.isEmpty()) {
                    globalGraph.put(info.transactionId, new HashSet<>(info.waitingFor));
                }
            });
            
            // TODO: 从其他节点获取锁信息
            // 这里简化实现,实际需要跨节点通信
            
            // 检测死锁
            detectDeadlockFromGraph(globalGraph);
        }
        
        /**
         * 从图中检测死锁
         */
        private void detectDeadlockFromGraph(Map<String, Set<String>> graph) {
            Set<String> visited = new HashSet<>();
            
            for (String node : graph.keySet()) {
                if (!visited.contains(node)) {
                    Set<String> path = new HashSet<>();
                    if (hasCycleDFS(node, graph, visited, path)) {
                        // 发现死锁
                        resolveDistributedDeadlock(path);
                        return;
                    }
                }
            }
        }
        
        private boolean hasCycleDFS(String node, Map<String, Set<String>> graph,
                                   Set<String> visited, Set<String> path) {
            if (path.contains(node)) {
                return true;
            }
            
            if (visited.contains(node)) {
                return false;
            }
            
            visited.add(node);
            path.add(node);
            
            Set<String> neighbors = graph.get(node);
            if (neighbors != null) {
                for (String neighbor : neighbors) {
                    if (hasCycleDFS(neighbor, graph, visited, path)) {
                        return true;
                    }
                }
            }
            
            path.remove(node);
            return false;
        }
        
        /**
         * 解决分布式死锁
         */
        private void resolveDistributedDeadlock(Set<String> cycleTransactions) {
            System.out.println("Distributed deadlock detected in cycle: " + cycleTransactions);
            
            // 选择牺牲者策略
            String victim = selectVictim(cycleTransactions);
            
            // 通知相关节点回滚事务
            rollbackTransaction(victim);
            
            // 清理锁表
            cleanupAfterRollback(victim);
        }
        
        private String selectVictim(Set<String> candidates) {
            // 策略:选择最年轻的事务
            long youngestTime = Long.MAX_VALUE;
            String youngestTx = null;
            
            for (String txId : candidates) {
                // 简化实现,实际需要获取事务开始时间
                if (txId.hashCode() < youngestTime) {
                    youngestTime = txId.hashCode();
                    youngestTx = txId;
                }
            }
            
            return youngestTx;
        }
        
        private void rollbackTransaction(String txId) {
            System.out.println("Rolling back distributed transaction: " + txId);
            // 实际实现中需要通知所有参与节点
        }
        
        private void startDetection() {
            detectorScheduler.scheduleAtFixedRate(() -> {
                try {
                    checkForTimeouts();
                    checkForDeadlocks();
                } catch (Exception e) {
                    System.err.println("Deadlock detection error: " + e.getMessage());
                }
            }, checkInterval, checkInterval, TimeUnit.MILLISECONDS);
        }
        
        private void checkForTimeouts() {
            long currentTime = System.currentTimeMillis();
            long timeoutThreshold = 30000; // 30秒
            
            lockTable.entrySet().removeIf(entry -> {
                TransactionLockInfo info = entry.getValue();
                long age = currentTime - info.timestamp;
                
                if (age > timeoutThreshold) {
                    System.out.println("Transaction timeout: " + info.transactionId);
                    rollbackTransaction(info.transactionId);
                    return true;
                }
                
                return false;
            });
        }
        
        private void checkForDeadlocks() {
            buildGlobalWaitForGraph();
        }
        
        private String getNodeId() {
            try {
                return InetAddress.getLocalHost().getHostName();
            } catch (Exception e) {
                return "unknown";
            }
        }
        
        private void checkLockConflict(String txId, String resourceId, 
                                      TransactionLockInfo.LockType lockType) {
            // 检查是否有其他事务持有冲突的锁
            for (TransactionLockInfo existing : lockTable.values()) {
                if (existing.resourceId.equals(resourceId) && 
                    !existing.transactionId.equals(txId)) {
                    
                    boolean conflict = false;
                    
                    if (lockType == TransactionLockInfo.LockType.EXCLUSIVE) {
                        // 排他锁与任何锁都冲突
                        conflict = true;
                    } else if (lockType == TransactionLockInfo.LockType.SHARED && 
                               existing.lockType == TransactionLockInfo.LockType.EXCLUSIVE) {
                        // 共享锁与排他锁冲突
                        conflict = true;
                    }
                    
                    if (conflict) {
                        // 注册等待关系
                        waitForLock(txId, resourceId, existing.transactionId);
                        break;
                    }
                }
            }
        }
        
        private void cleanupAfterRollback(String txId) {
            // 移除该事务的所有锁
            lockTable.entrySet().removeIf(entry -> 
                entry.getValue().transactionId.equals(txId)
            );
            
            // 移除其他事务对该事务的等待
            lockTable.values().forEach(info -> 
                info.waitingFor.remove(txId)
            );
        }
        
        public void shutdown() {
            detectorScheduler.shutdown();
            try {
                if (!detectorScheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                    detectorScheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                detectorScheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /**
     * 基于数据库的死锁监控器
     */
    public static class DatabaseDeadlockMonitor {
        private final DataSource dataSource;
        private final ScheduledExecutorService monitorScheduler;
        private final DeadlockHandler deadlockHandler;
        
        public DatabaseDeadlockMonitor(DataSource dataSource, DeadlockHandler handler) {
            this.dataSource = dataSource;
            this.deadlockHandler = handler;
            this.monitorScheduler = Executors.newSingleThreadScheduledExecutor();
        }
        
        public interface DeadlockHandler {
            void onDeadlockDetected(String victimTransaction, String deadlockInfo);
        }
        
        /**
         * 开始监控
         */
        public void startMonitoring(long interval, TimeUnit unit) {
            monitorScheduler.scheduleAtFixedRate(() -> {
                try {
                    checkForDeadlocks();
                } catch (Exception e) {
                    System.err.println("Deadlock monitoring error: " + e.getMessage());
                }
            }, 0, interval, unit);
        }
        
        /**
         * 检查死锁
         */
        private void checkForDeadlocks() throws SQLException {
            String databaseType = getDatabaseType();
            
            switch (databaseType.toLowerCase()) {
                case "mysql":
                    checkMySQLDeadlocks();
                    break;
                case "postgresql":
                    checkPostgreSQLDeadlocks();
                    break;
                case "oracle":
                    checkOracleDeadlocks();
                    break;
                default:
                    checkGenericDeadlocks();
            }
        }
        
        /**
         * MySQL 死锁检查
         */
        private void checkMySQLDeadlocks() throws SQLException {
            // 检查锁等待超时
            String sql = """
                SELECT 
                    r.trx_id AS waiting_trx_id,
                    r.trx_mysql_thread_id AS waiting_thread,
                    r.trx_query AS waiting_query,
                    b.trx_id AS blocking_trx_id,
                    b.trx_mysql_thread_id AS blocking_thread,
                    b.trx_query AS blocking_query,
                    TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_seconds
                FROM information_schema.INNODB_LOCK_WAITS w
                JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id
                JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id
                WHERE TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) > 30
                """;
            
            try (Connection conn = dataSource.getConnection();
                 Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery(sql)) {
                
                while (rs.next()) {
                    String waitingTx = rs.getString("waiting_trx_id");
                    String blockingTx = rs.getString("blocking_trx_id");
                    int waitSeconds = rs.getInt("wait_seconds");
                    
                    if (waitSeconds > 60) { // 超过60秒,认为是死锁
                        String deadlockInfo = String.format(
                            "Long lock wait detected: %s waiting for %s for %d seconds",
                            waitingTx, blockingTx, waitSeconds
                        );
                        
                        deadlockHandler.onDeadlockDetected(waitingTx, deadlockInfo);
                    }
                }
            }
        }
        
        /**
         * 获取数据库类型
         */
        private String getDatabaseType() throws SQLException {
            try (Connection conn = dataSource.getConnection()) {
                return conn.getMetaData().getDatabaseProductName();
            }
        }
        
        /**
         * 通用的死锁检查
         */
        private void checkGenericDeadlocks() throws SQLException {
            // 通过查询长时间运行的事务来检测可能的死锁
            String sql = """
                SELECT 
                    tx_id,
                    start_time,
                    current_timestamp - start_time AS duration,
                    query_text
                FROM sys.transactions
                WHERE state = 'ACTIVE'
                AND current_timestamp - start_time > INTERVAL '30 seconds'
                ORDER BY duration DESC
                """;
            
            // 注意:这是一个通用模板,实际SQL需要根据具体数据库调整
            System.out.println("Generic deadlock check would run here");
        }
        
        /**
         * 杀死死锁事务
         */
        public void killDeadlockedTransaction(String transactionId) throws SQLException {
            String dbType = getDatabaseType();
            String killSql;
            
            switch (dbType.toLowerCase()) {
                case "mysql":
                    killSql = "KILL " + transactionId;
                    break;
                case "postgresql":
                    killSql = "SELECT pg_terminate_backend(" + transactionId + ")";
                    break;
                default:
                    throw new UnsupportedOperationException(
                        "Kill operation not supported for " + dbType
                    );
            }
            
            try (Connection conn = dataSource.getConnection();
                 Statement stmt = conn.createStatement()) {
                stmt.execute(killSql);
                System.out.println("Killed transaction: " + transactionId);
            }
        }
        
        public void shutdown() {
            monitorScheduler.shutdown();
        }
    }
}

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】

三、自动回滚机制实现

1. 智能回滚策略

java

复制

下载

复制代码
/**
 * 智能回滚管理器
 */
public class SmartRollbackManager {
    
    /**
     * 回滚策略枚举
     */
    public enum RollbackStrategy {
        ROLLBACK_FULL,          // 完全回滚
        ROLLBACK_PARTIAL,       // 部分回滚到保存点
        ROLLBACK_AND_RETRY,     // 回滚后重试
        COMPENSATING_ACTION,    // 补偿操作
        DELAYED_ROLLBACK        // 延迟回滚(等待依赖事务)
    }
    
    /**
     * 回滚决策器
     */
    public static class RollbackDecisionEngine {
        
        /**
         * 决定最佳回滚策略
         */
        public RollbackDecision decideRollbackStrategy(
                TransactionContext context, 
                DeadlockInfo deadlockInfo) {
            
            RollbackDecision decision = new RollbackDecision();
            
            // 因素1: 事务执行时间
            long executionTime = System.currentTimeMillis() - context.getStartTime();
            if (executionTime < 1000) {
                // 短事务,完全回滚代价小
                decision.strategy = RollbackStrategy.ROLLBACK_FULL;
                decision.priority = RollbackPriority.HIGH;
            } else if (executionTime < 5000) {
                // 中等事务,检查是否有保存点
                if (context.hasSavepoint()) {
                    decision.strategy = RollbackStrategy.ROLLBACK_PARTIAL;
                    decision.savepointName = context.getLastSavepoint();
                } else {
                    decision.strategy = RollbackStrategy.ROLLBACK_FULL;
                }
                decision.priority = RollbackPriority.MEDIUM;
            } else {
                // 长事务,尝试补偿操作
                decision.strategy = RollbackStrategy.COMPENSATING_ACTION;
                decision.priority = RollbackPriority.LOW;
            }
            
            // 因素2: 事务类型
            if (context.getTransactionType() == TransactionType.READ_ONLY) {
                decision.strategy = RollbackStrategy.ROLLBACK_FULL;
                decision.priority = RollbackPriority.HIGH;
            } else if (context.getTransactionType() == TransactionType.CRITICAL) {
                // 关键事务,尝试重试
                decision.strategy = RollbackStrategy.ROLLBACK_AND_RETRY;
                decision.retryCount = 3;
                decision.retryDelay = 100;
                decision.priority = RollbackPriority.CRITICAL;
            }
            
            // 因素3: 死锁中的角色
            if (deadlockInfo.isCyclic()) {
                // 在循环死锁中,选择代价最小的事务
                if (calculateTransactionCost(context) < 
                    calculateAverageCost(deadlockInfo)) {
                    decision.strategy = RollbackStrategy.ROLLBACK_FULL;
                    decision.priority = RollbackPriority.HIGH;
                }
            }
            
            return decision;
        }
        
        private long calculateTransactionCost(TransactionContext context) {
            // 计算事务回滚代价
            long cost = 0;
            
            // 已修改的行数
            cost += context.getModifiedRows() * 10;
            
            // 执行时间
            cost += (System.currentTimeMillis() - context.getStartTime()) / 100;
            
            // 事务重要性权重
            cost *= context.getPriority().getWeight();
            
            return cost;
        }
        
        private long calculateAverageCost(DeadlockInfo deadlockInfo) {
            // 计算平均代价
            return deadlockInfo.getInvolvedTransactions().stream()
                .mapToLong(this::calculateTransactionCost)
                .average()
                .orElse(0);
        }
    }
    
    /**
     * 回滚执行器
     */
    public static class RollbackExecutor {
        private final DataSource dataSource;
        private final Map<String, CompensatingAction> compensatingActions;
        
        public RollbackExecutor(DataSource dataSource) {
            this.dataSource = dataSource;
            this.compensatingActions = new HashMap<>();
            registerDefaultActions();
        }
        
        /**
         * 执行回滚
         */
        public boolean executeRollback(String transactionId, 
                                      RollbackDecision decision) throws SQLException {
            
            System.out.printf("Executing rollback for %s with strategy: %s%n", 
                             transactionId, decision.strategy);
            
            switch (decision.strategy) {
                case ROLLBACK_FULL:
                    return executeFullRollback(transactionId);
                    
                case ROLLBACK_PARTIAL:
                    return executePartialRollback(transactionId, decision.savepointName);
                    
                case ROLLBACK_AND_RETRY:
                    return executeRollbackAndRetry(transactionId, decision);
                    
                case COMPENSATING_ACTION:
                    return executeCompensatingAction(transactionId, decision);
                    
                case DELAYED_ROLLBACK:
                    return executeDelayedRollback(transactionId, decision);
                    
                default:
                    return executeFullRollback(transactionId);
            }
        }
        
        /**
         * 完全回滚
         */
        private boolean executeFullRollback(String transactionId) throws SQLException {
            // 对于MySQL,需要获取连接并执行ROLLBACK
            // 这里简化实现
            try (Connection conn = dataSource.getConnection()) {
                // 如果知道具体的连接,可以针对该连接执行ROLLBACK
                // 否则需要其他机制
                return true;
            }
        }
        
        /**
         * 部分回滚到保存点
         */
        private boolean executePartialRollback(String transactionId, String savepoint) 
                throws SQLException {
            
            String sql = "ROLLBACK TO SAVEPOINT " + savepoint;
            
            try (Connection conn = dataSource.getConnection();
                 Statement stmt = conn.createStatement()) {
                return stmt.execute(sql);
            }
        }
        
        /**
         * 回滚并重试
         */
        private boolean executeRollbackAndRetry(String transactionId, 
                                               RollbackDecision decision) {
            
            int retryCount = 0;
            boolean success = false;
            
            while (retryCount < decision.retryCount && !success) {
                try {
                    // 回滚
                    executeFullRollback(transactionId);
                    
                    // 等待重试延迟
                    if (decision.retryDelay > 0) {
                        Thread.sleep(decision.retryDelay);
                    }
                    
                    // 重新执行事务逻辑
                    success = retryTransaction(transactionId);
                    
                } catch (Exception e) {
                    System.err.println("Retry failed: " + e.getMessage());
                    retryCount++;
                    
                    // 指数退避
                    decision.retryDelay *= 2;
                }
            }
            
            return success;
        }
        
        /**
         * 补偿操作
         */
        private boolean executeCompensatingAction(String transactionId,
                                                 RollbackDecision decision) {
            
            // 查找注册的补偿操作
            CompensatingAction action = compensatingActions.get(transactionId);
            
            if (action != null) {
                try {
                    return action.compensate();
                } catch (Exception e) {
                    System.err.println("Compensating action failed: " + e.getMessage());
                    // 回退到完全回滚
                    try {
                        return executeFullRollback(transactionId);
                    } catch (SQLException ex) {
                        return false;
                    }
                }
            }
            
            return false;
        }
        
        /**
         * 延迟回滚
         */
        private boolean executeDelayedRollback(String transactionId,
                                              RollbackDecision decision) {
            
            // 创建延迟任务
            ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
            
            scheduler.schedule(() -> {
                try {
                    executeFullRollback(transactionId);
                } catch (SQLException e) {
                    System.err.println("Delayed rollback failed: " + e.getMessage());
                }
            }, decision.delaySeconds, TimeUnit.SECONDS);
            
            return true;
        }
        
        /**
         * 重试事务
         */
        private boolean retryTransaction(String transactionId) {
            // 这里应该调用原始的业务逻辑
            System.out.println("Retrying transaction: " + transactionId);
            return true;
        }
        
        /**
         * 注册补偿操作
         */
        public void registerCompensatingAction(String transactionType, 
                                              CompensatingAction action) {
            compensatingActions.put(transactionType, action);
        }
        
        private void registerDefaultActions() {
            // 注册默认的补偿操作
            compensatingActions.put("ORDER_CREATE", new OrderCreateCompensator());
            compensatingActions.put("PAYMENT_PROCESS", new PaymentProcessCompensator());
        }
        
        /**
         * 补偿操作接口
         */
        public interface CompensatingAction {
            boolean compensate() throws Exception;
        }
        
        /**
         * 订单创建补偿器
         */
        static class OrderCreateCompensator implements CompensatingAction {
            @Override
            public boolean compensate() throws Exception {
                // 如果订单创建失败,可能需要:
                // 1. 释放库存预留
                // 2. 退款(如果已支付)
                // 3. 发送通知
                System.out.println("Executing order creation compensation");
                return true;
            }
        }
        
        /**
         * 支付处理补偿器
         */
        static class PaymentProcessCompensator implements CompensatingAction {
            @Override
            public boolean compensate() throws Exception {
                // 如果支付处理失败,可能需要:
                // 1. 撤销支付请求
                // 2. 更新订单状态
                // 3. 记录审计日志
                System.out.println("Executing payment process compensation");
                return true;
            }
        }
    }
    
    /**
     * 回滚决策
     */
    static class RollbackDecision {
        RollbackStrategy strategy;
        RollbackPriority priority;
        String savepointName;
        int retryCount;
        long retryDelay;
        int delaySeconds;
    }
    
    enum RollbackPriority {
        LOW(1), MEDIUM(3), HIGH(5), CRITICAL(10);
        
        private final int weight;
        
        RollbackPriority(int weight) {
            this.weight = weight;
        }
        
        public int getWeight() {
            return weight;
        }
    }
    
    /**
     * 事务上下文
     */
    static class TransactionContext {
        private String transactionId;
        private long startTime;
        private TransactionType transactionType;
        private int modifiedRows;
        private RollbackPriority priority;
        private List<String> savepoints = new ArrayList<>();
        
        // getters and setters
        
        public boolean hasSavepoint() {
            return !savepoints.isEmpty();
        }
        
        public String getLastSavepoint() {
            return savepoints.isEmpty() ? null : savepoints.get(savepoints.size() - 1);
        }
    }
    
    enum TransactionType {
        READ_ONLY, READ_WRITE, CRITICAL, BATCH
    }
    
    /**
     * 死锁信息
     */
    static class DeadlockInfo {
        private boolean cyclic;
        private List<TransactionContext> involvedTransactions = new ArrayList<>();
        
        // getters and setters
    }
}

2. 基于保存点的细粒度回滚

java

复制

下载

复制代码
/**
 * 保存点管理器
 */
public class SavepointManager {
    
    private final Map<String, List<Savepoint>> transactionSavepoints = new ConcurrentHashMap<>();
    private final DataSource dataSource;
    
    public SavepointManager(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    /**
     * 创建保存点
     */
    public String createSavepoint(String transactionId, String name) throws SQLException {
        Savepoint savepoint = new Savepoint();
        savepoint.name = name;
        savepoint.createdAt = System.currentTimeMillis();
        savepoint.sqlState = captureSqlState(transactionId);
        
        transactionSavepoints
            .computeIfAbsent(transactionId, k -> new ArrayList<>())
            .add(savepoint);
        
        // 在数据库中创建保存点
        try (Connection conn = dataSource.getConnection();
             Statement stmt = conn.createStatement()) {
            stmt.execute("SAVEPOINT " + name);
        }
        
        return name;
    }
    
    /**
     * 回滚到指定保存点
     */
    public boolean rollbackToSavepoint(String transactionId, String savepointName) 
            throws SQLException {
        
        List<Savepoint> savepoints = transactionSavepoints.get(transactionId);
        if (savepoints == null) {
            return false;
        }
        
        // 找到保存点
        Savepoint target = null;
        for (Savepoint sp : savepoints) {
            if (sp.name.equals(savepointName)) {
                target = sp;
                break;
            }
        }
        
        if (target == null) {
            return false;
        }
        
        // 执行数据库回滚
        try (Connection conn = dataSource.getConnection();
             Statement stmt = conn.createStatement()) {
            stmt.execute("ROLLBACK TO SAVEPOINT " + savepointName);
        }
        
        // 清理后续的保存点
        int index = savepoints.indexOf(target);
        if (index >= 0) {
            savepoints.subList(index + 1, savepoints.size()).clear();
        }
        
        return true;
    }
    
    /**
     * 捕获SQL状态
     */
    private String captureSqlState(String transactionId) {
        // 捕获当前事务的SQL执行状态
        // 可以包括:已执行的SQL语句、修改的行、锁状态等
        return "SQL_STATE_" + transactionId + "_" + System.currentTimeMillis();
    }
    
    /**
     * 保存点信息
     */
    static class Savepoint {
        String name;
        long createdAt;
        String sqlState;
        Map<String, Object> metadata = new HashMap<>();
    }
    
    /**
     * 自动保存点策略
     */
    public static class AutoSavepointStrategy {
        private final SavepointManager savepointManager;
        private final int operationsBetweenSavepoints;
        private final long timeBetweenSavepoints; // 毫秒
        
        public AutoSavepointStrategy(SavepointManager manager, 
                                    int opsBetween, long timeBetween) {
            this.savepointManager = manager;
            this.operationsBetweenSavepoints = opsBetween;
            this.timeBetweenSavepoints = timeBetween;
        }
        
        /**
         * 监控事务并自动创建保存点
         */
        public void monitorTransaction(String transactionId) {
            Thread monitorThread = new Thread(() -> {
                int operationCount = 0;
                long lastSavepointTime = System.currentTimeMillis();
                
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        // 检查操作计数
                        if (operationCount >= operationsBetweenSavepoints) {
                            createAutoSavepoint(transactionId, "auto_ops_" + operationCount);
                            operationCount = 0;
                        }
                        
                        // 检查时间间隔
                        long currentTime = System.currentTimeMillis();
                        if (currentTime - lastSavepointTime >= timeBetweenSavepoints) {
                            createAutoSavepoint(transactionId, "auto_time_" + currentTime);
                            lastSavepointTime = currentTime;
                        }
                        
                        // 监控事务状态
                        if (!isTransactionActive(transactionId)) {
                            break;
                        }
                        
                        Thread.sleep(1000); // 每秒检查一次
                    }
                } catch (Exception e) {
                    System.err.println("Auto-savepoint monitoring error: " + e.getMessage());
                }
            });
            
            monitorThread.setDaemon(true);
            monitorThread.start();
        }
        
        private void createAutoSavepoint(String transactionId, String name) {
            try {
                savepointManager.createSavepoint(transactionId, name);
                System.out.println("Auto-created savepoint: " + name + " for " + transactionId);
            } catch (SQLException e) {
                System.err.println("Failed to create auto-savepoint: " + e.getMessage());
            }
        }
        
        private boolean isTransactionActive(String transactionId) {
            // 检查事务是否仍然活跃
            // 简化实现
            return true;
        }
    }
}

四、死锁预防与优化策略

1. 应用层死锁预防

java

复制

下载

复制代码
/**
 * 死锁预防策略
 */
public class DeadlockPreventionStrategies {
    
    /**
     * 锁顺序管理器(预防循环等待)
     */
    public static class LockOrderManager {
        private static final ThreadLocal<Set<String>> acquiredLocks = 
            ThreadLocal.withInitial(HashSet::new);
        
        private static final Object globalLock = new Object();
        private static final Map<String, Integer> resourceOrder = new ConcurrentHashMap<>();
        private static int nextOrder = 0;
        
        /**
         * 按固定顺序获取锁
         */
        public static void acquireInOrder(String... resourceIds) {
            // 按资源ID排序(确保全局一致)
            List<String> sortedResources = Arrays.stream(resourceIds)
                .sorted(Comparator.comparing(LockOrderManager::getResourceOrder))
                .collect(Collectors.toList());
            
            // 按顺序获取锁
            for (String resource : sortedResources) {
                acquireLock(resource);
            }
        }
        
        private static int getResourceOrder(String resourceId) {
            synchronized (globalLock) {
                return resourceOrder.computeIfAbsent(resourceId, k -> nextOrder++);
            }
        }
        
        private static void acquireLock(String resourceId) {
            // 模拟获取锁
            Set<String> locks = acquiredLocks.get();
            
            if (locks.contains(resourceId)) {
                throw new IllegalStateException("Lock already acquired: " + resourceId);
            }
            
            // 检查是否违反顺序
            int currentOrder = getResourceOrder(resourceId);
            for (String lock : locks) {
                int lockOrder = getResourceOrder(lock);
                if (currentOrder < lockOrder) {
                    throw new IllegalStateException(
                        String.format("Lock order violation: %s(%d) before %s(%d)", 
                                     resourceId, currentOrder, lock, lockOrder)
                    );
                }
            }
            
            locks.add(resourceId);
            System.out.println("Acquired lock: " + resourceId);
        }
        
        /**
         * 释放所有锁
         */
        public static void releaseAll() {
            acquiredLocks.get().clear();
            acquiredLocks.remove();
        }
    }
    
    /**
     * 锁超时机制
     */
    public static class LockWithTimeout {
        private final Map<String, LockInfo> lockTable = new ConcurrentHashMap<>();
        private final ScheduledExecutorService timeoutScheduler;
        
        public LockWithTimeout() {
            this.timeoutScheduler = Executors.newSingleThreadScheduledExecutor();
            startTimeoutChecker();
        }
        
        /**
         * 尝试获取锁(带超时)
         */
        public boolean tryAcquire(String lockKey, long timeout, TimeUnit unit) 
                throws InterruptedException {
            
            long deadline = System.currentTimeMillis() + unit.toMillis(timeout);
            
            while (System.currentTimeMillis() < deadline) {
                synchronized (lockTable) {
                    if (!lockTable.containsKey(lockKey)) {
                        // 获取锁
                        LockInfo info = new LockInfo();
                        info.owner = Thread.currentThread().getName();
                        info.acquiredAt = System.currentTimeMillis();
                        info.timeout = unit.toMillis(timeout);
                        
                        lockTable.put(lockKey, info);
                        System.out.println("Lock acquired: " + lockKey + " by " + info.owner);
                        return true;
                    }
                    
                    // 检查锁是否超时
                    LockInfo existing = lockTable.get(lockKey);
                    if (System.currentTimeMillis() - existing.acquiredAt > existing.timeout) {
                        // 锁超时,强制释放
                        System.out.println("Lock timeout: " + lockKey + ", force releasing");
                        lockTable.remove(lockKey);
                        continue;
                    }
                }
                
                // 等待一段时间后重试
                Thread.sleep(100);
            }
            
            return false;
        }
        
        /**
         * 释放锁
         */
        public void release(String lockKey) {
            synchronized (lockTable) {
                LockInfo info = lockTable.get(lockKey);
                if (info != null && info.owner.equals(Thread.currentThread().getName())) {
                    lockTable.remove(lockKey);
                    System.out.println("Lock released: " + lockKey);
                }
            }
        }
        
        private void startTimeoutChecker() {
            timeoutScheduler.scheduleAtFixedRate(() -> {
                long currentTime = System.currentTimeMillis();
                
                synchronized (lockTable) {
                    lockTable.entrySet().removeIf(entry -> {
                        LockInfo info = entry.getValue();
                        boolean expired = currentTime - info.acquiredAt > info.timeout;
                        if (expired) {
                            System.out.println("Timeout checker removed lock: " + entry.getKey());
                        }
                        return expired;
                    });
                }
            }, 1, 1, TimeUnit.SECONDS);
        }
        
        static class LockInfo {
            String owner;
            long acquiredAt;
            long timeout;
        }
        
        public void shutdown() {
            timeoutScheduler.shutdown();
        }
    }
    
    /**
     * 事务重试机制
     */
    public static class TransactionRetryManager {
        
        /**
         * 带退避的重试执行
         */
        public static <T> T executeWithRetry(Callable<T> task, 
                                            int maxRetries,
                                            RetryStrategy strategy) throws Exception {
            
            int attempt = 0;
            Exception lastException = null;
            
            while (attempt <= maxRetries) {
                try {
                    return task.call();
                    
                } catch (SQLException e) {
                    lastException = e;
                    
                    // 检查是否死锁相关错误
                    if (isDeadlockError(e)) {
                        System.out.println("Deadlock detected, retrying...");
                        
                        // 计算退避时间
                        long backoff = strategy.calculateBackoff(attempt);
                        
                        if (backoff > 0) {
                            Thread.sleep(backoff);
                        }
                        
                        attempt++;
                        continue;
                    }
                    
                    // 非死锁错误,直接抛出
                    throw e;
                }
            }
            
            throw new Exception("Max retries exceeded", lastException);
        }
        
        private static boolean isDeadlockError(SQLException e) {
            String sqlState = e.getSQLState();
            int errorCode = e.getErrorCode();
            
            // MySQL死锁错误代码
            if (errorCode == 1213 || "40001".equals(sqlState)) {
                return true;
            }
            
            // PostgreSQL死锁错误
            if ("40P01".equals(sqlState)) {
                return true;
            }
            
            // 其他数据库...
            return false;
        }
        
        /**
         * 重试策略
         */
        public interface RetryStrategy {
            long calculateBackoff(int attempt);
        }
        
        /**
         * 指数退避策略
         */
        public static class ExponentialBackoffStrategy implements RetryStrategy {
            private final long initialDelay;
            private final long maxDelay;
            private final double multiplier;
            
            public ExponentialBackoffStrategy(long initialDelay, long maxDelay, double multiplier) {
                this.initialDelay = initialDelay;
                this.maxDelay = maxDelay;
                this.multiplier = multiplier;
            }
            
            @Override
            public long calculateBackoff(int attempt) {
                long delay = (long) (initialDelay * Math.pow(multiplier, attempt));
                return Math.min(delay, maxDelay);
            }
        }
        
        /**
         * 固定延迟策略
         */
        public static class FixedDelayStrategy implements RetryStrategy {
            private final long delay;
            
            public FixedDelayStrategy(long delay) {
                this.delay = delay;
            }
            
            @Override
            public long calculateBackoff(int attempt) {
                return delay;
            }
        }
    }
}

2. 数据库优化配置

sql

复制

下载

复制代码
-- MySQL 死锁优化配置
SET GLOBAL innodb_lock_wait_timeout = 30;  -- 减少锁等待超时
SET GLOBAL innodb_deadlock_detect = ON;    -- 确保死锁检测开启
SET GLOBAL innodb_print_all_deadlocks = ON; -- 记录所有死锁到错误日志

-- 优化事务隔离级别(根据业务需求选择)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 减少事务持有时间
SET SESSION autocommit = 1;  -- 自动提交小事务

-- 索引优化(减少锁冲突)
-- 确保查询使用索引,避免全表扫描
CREATE INDEX idx_user_id ON orders(user_id);
CREATE INDEX idx_product_id ON order_items(product_id);

-- PostgreSQL 优化配置
SET deadlock_timeout = '1s';  -- 设置合适的死锁检测间隔
SET lock_timeout = '30s';     -- 设置锁等待超时

-- 监控和调优配置
-- 开启详细日志记录
ALTER SYSTEM SET log_lock_waits = ON;
ALTER SYSTEM SET log_min_duration_statement = '1s';

-- 查询优化:使用 FOR UPDATE SKIP LOCKED 避免锁等待
SELECT * FROM orders 
WHERE status = 'PENDING' 
FOR UPDATE SKIP LOCKED 
LIMIT 10;

-- 使用更细粒度的锁
BEGIN;
SELECT * FROM users WHERE id = 1 FOR UPDATE;  -- 行级锁,不是表锁
-- 处理业务逻辑
COMMIT;

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】

五、监控与告警系统

1. 死锁监控平台

java

复制

下载

复制代码
/**
 * 死锁监控平台
 */
public class DeadlockMonitoringPlatform {
    
    /**
     * 监控指标收集器
     */
    public static class MetricsCollector {
        private final MeterRegistry meterRegistry;
        private final Map<String, Counter> deadlockCounters = new ConcurrentHashMap<>();
        private final Map<String, Timer> transactionTimers = new ConcurrentHashMap<>();
        
        public MetricsCollector() {
            this.meterRegistry = new SimpleMeterRegistry();
            
            // 注册关键指标
            Metrics.globalRegistry.add(meterRegistry);
        }
        
        /**
         * 记录死锁事件
         */
        public void recordDeadlock(String database, String transactionType) {
            Counter counter = deadlockCounters.computeIfAbsent(
                database + "." + transactionType,
                key -> Counter.builder("database.deadlocks")
                    .tag("database", database)
                    .tag("type", transactionType)
                    .register(meterRegistry)
            );
            
            counter.increment();
            
            // 触发告警
            if (counter.count() > 10) { // 阈值
                sendAlert("High deadlock rate detected for " + transactionType + 
                         " in " + database);
            }
        }
        
        /**
         * 记录事务执行时间
         */
        public Timer.Sample startTransactionTimer() {
            return Timer.start(meterRegistry);
        }
        
        public void stopTransactionTimer(Timer.Sample sample, String transactionName) {
            Timer timer = transactionTimers.computeIfAbsent(
                transactionName,
                key -> Timer.builder("database.transaction.duration")
                    .tag("name", transactionName)
                    .publishPercentiles(0.5, 0.95, 0.99)
                    .register(meterRegistry)
            );
            
            sample.stop(timer);
        }
        
        /**
         * 获取监控报告
         */
        public MonitoringReport generateReport() {
            MonitoringReport report = new MonitoringReport();
            
            // 收集死锁统计
            deadlockCounters.forEach((key, counter) -> {
                report.addDeadlockStat(key, counter.count());
            });
            
            // 收集事务性能统计
            transactionTimers.forEach((name, timer) -> {
                timer.takeSnapshot().percentileValues().forEach(value -> {
                    report.addTransactionPercentile(name, value.percentile(), value.value());
                });
            });
            
            return report;
        }
        
        private void sendAlert(String message) {
            System.out.println("ALERT: " + message);
            // 实际实现:发送到监控系统(如Prometheus Alertmanager)
        }
    }
    
    /**
     * 实时监控仪表板
     */
    public static class RealTimeDashboard {
        private final WebSocketHandler webSocketHandler;
        private final MetricsCollector metricsCollector;
        private final ScheduledExecutorService updateScheduler;
        
        public RealTimeDashboard(MetricsCollector collector) {
            this.metricsCollector = collector;
            this.webSocketHandler = new WebSocketHandler();
            this.updateScheduler = Executors.newSingleThreadScheduledExecutor();
            
            startDashboardUpdates();
        }
        
        /**
         * 启动仪表板更新
         */
        private void startDashboardUpdates() {
            updateScheduler.scheduleAtFixedRate(() -> {
                try {
                    MonitoringReport report = metricsCollector.generateReport();
                    webSocketHandler.broadcastUpdate(report);
                } catch (Exception e) {
                    System.err.println("Dashboard update error: " + e.getMessage());
                }
            }, 0, 5, TimeUnit.SECONDS); // 每5秒更新一次
        }
        
        /**
         * 生成HTML仪表板
         */
        public String generateDashboardHTML() {
            return """
                <!DOCTYPE html>
                <html>
                <head>
                    <title>Database Deadlock Monitor</title>
                    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
                    <style>
                        .dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
                        .chart-container { background: white; padding: 20px; border-radius: 8px; }
                        .alert-panel { grid-column: 1 / -1; }
                    </style>
                </head>
                <body>
                    <div class="dashboard">
                        <div class="chart-container">
                            <h3>Deadlock Statistics</h3>
                            <canvas id="deadlockChart"></canvas>
                        </div>
                        <div class="chart-container">
                            <h3>Transaction Performance</h3>
                            <canvas id="transactionChart"></canvas>
                        </div>
                        <div class="alert-panel">
                            <h3>Recent Alerts</h3>
                            <div id="alertList"></div>
                        </div>
                    </div>
                    
                    <script>
                        const ws = new WebSocket('ws://localhost:8080/deadlock-monitor');
                        ws.onmessage = (event) => {
                            const data = JSON.parse(event.data);
                            updateCharts(data);
                        };
                        
                        function updateCharts(report) {
                            // 更新图表逻辑
                        }
                    </script>
                </body>
                </html>
                """;
        }
        
        static class WebSocketHandler {
            public void broadcastUpdate(MonitoringReport report) {
                // 广播更新到所有连接的客户端
            }
        }
    }
    
    /**
     * 监控报告
     */
    static class MonitoringReport {
        private Map<String, Double> deadlockStats = new HashMap<>();
        private Map<String, Map<Double, Double>> transactionPercentiles = new HashMap<>();
        
        public void addDeadlockStat(String key, double count) {
            deadlockStats.put(key, count);
        }
        
        public void addTransactionPercentile(String name, double percentile, double value) {
            transactionPercentiles
                .computeIfAbsent(name, k -> new HashMap<>())
                .put(percentile, value);
        }
    }
}

六、总结与最佳实践

关键原则:

  1. 预防优于检测:通过良好的设计避免死锁

  2. 快速失败:设置合理的超时时间

  3. 优雅降级:死锁发生时采取合适的恢复策略

  4. 持续监控:实时监控死锁情况并告警

最佳实践检查表:

设计阶段

  • 统一锁获取顺序

  • 减少事务持有时间

  • 合理设置事务隔离级别

  • 使用索引优化查询

开发阶段

  • 实现重试机制(带退避)

  • 使用保存点进行细粒度回滚

  • 实现补偿事务机制

  • 添加完善的日志记录

配置阶段

  • 设置合适的锁等待超时

  • 开启死锁检测和日志

  • 配置监控和告警

  • 定期优化数据库统计信息

运维阶段

  • 监控死锁频率和模式

  • 定期分析死锁日志

  • 根据监控数据优化配置

  • 建立应急预案

各数据库建议:

MySQL:

  • 开启 innodb_deadlock_detect

  • 设置 innodb_lock_wait_timeout = 30

  • 监控 SHOW ENGINE INNODB STATUS

  • 使用行级锁而非表级锁

PostgreSQL:

  • 设置 deadlock_timeout = 1s

  • 使用 FOR UPDATE SKIP LOCKED

  • 监控 pg_lockspg_stat_activity

  • 合理使用保存点

Oracle:

  • 使用 DBMS_LOCK 管理应用层锁

  • 监控 V$LOCKV$SESSION

  • 设置合适的 UNDO_RETENTION

通过综合运用检测、预防、恢复和监控策略,可以显著降低死锁对系统的影响,提高数据库的稳定性和可用性。

相关推荐
输出输入2 小时前
JAVA能进行鸿蒙系统应用的开发吗
java
数据知道2 小时前
PostgreSQL实战:详解权限设置与管理全流程
数据库·postgresql
PwnGuo2 小时前
Android逆向:在 Unidbg 中解决 native 函数内调用 Java 方法的报错
android·java·python
输出输入2 小时前
IJ IDEA 目录结构
java
-大头.2 小时前
GIT教程系列(共3篇)---------第一篇:Git入门与核心概念完全指南
大数据·git·elasticsearch
Kratzdisteln2 小时前
【1902】预先生成完整的树状PPT结构
java·前端·powerpoint
Dontla2 小时前
Database Schema Introduction (structure of data, NoSQL schema)
数据库·nosql
2401_832298102 小时前
存算分离2.0,阿里云EMR Serverless破解数据处理瓶颈
数据库
Sylvia-girl2 小时前
Lambda表达式
java·开发语言