[alibaba/druid]发生致命错误时创建连接可能重复触发

2025-11-10 34 views
6

错误代码如下

 protected final void handleFatalError(DruidPooledConnection conn,
                                          SQLException error,
                                          String sql) throws SQLException {
        final DruidConnectionHolder holder = conn.holder;

        if (conn.isTraceEnable()) {
            activeConnectionLock.lock();
            try {
                if (conn.isTraceEnable()) {
                    activeConnections.remove(conn);
                    conn.setTraceEnable(false);
                }
            } finally {
                activeConnectionLock.unlock();
            }
        }

        long lastErrorTimeMillis = this.lastErrorTimeMillis;
        if (lastErrorTimeMillis == 0) {
            lastErrorTimeMillis = System.currentTimeMillis();
        }

        if (sql != null && sql.length() > 1024) {
            sql = sql.substring(0, 1024);
        }

        boolean requireDiscard = false;
        final ReentrantLock lock = conn.lock;
        lock.lock();
        try {
            if ((!conn.isClosed()) && !conn.isDisable()) {
                conn.disable(error);
                requireDiscard = true;
            }

            lastFatalErrorTimeMillis = lastErrorTimeMillis;
            fatalErrorCount++;
            if (fatalErrorCount - fatalErrorCountLastShrink > onFatalErrorMaxActive) {
                onFatalError = true;
            }
            lastFatalError = error;
            lastFatalErrorSql = sql;
        } finally {
            lock.unlock();
        }

        if (onFatalError && holder != null && holder.getDataSource() != null) {
            ReentrantLock dataSourceLock = holder.getDataSource().lock;
            dataSourceLock.lock();
            try {
                emptySignal();
            } finally {
                dataSourceLock.unlock();
            }
        }

        if (requireDiscard) {
            if (holder.statementTrace != null) {
                holder.lock.lock();
                try {
                    for (Statement stmt : holder.statementTrace) {
                        JdbcUtils.close(stmt);
                    }
                } finally {
                    holder.lock.unlock();
                }
            }

            this.discardConnection(holder);
        }

        // holder.
        LOG.error("{conn-" + holder.getConnectionId() + "} discard", error);
    }

回答

6

另外 所有做这种连接判断的地方 由于都是异步创建的 我理解断言都是全凭运气的?

7

在 https://github.com/alibaba/druid/pull/5015 中修复。关于这种异步的断言 温少打算如何处理

2

哥,你这个有重现的代码吗?谢谢

4

哥,你这个有重现的代码吗?谢谢

OracleExceptionSorterTest_closeConn_1.test_connect:71 expected:<1> but was:<2> https://pipelines.actions.githubusercontent.com/serviceHosts/4864c16f-3afc-4fd3-9c2e-97e873615ab5/_apis/pipelines/1/runs/176/signedlogcontent/2?urlExpires=2023-02-05T11%3A20%3A09.1033342Z&urlSigningMethod=HMACV1&urlSignature=izNuR4KKCfclNd3Vkpps%2F0lAHr4%2Bb1%2Bdh9YRhMLYbAk%3D

直接跑单元测试就会发现问题 @Eatin