You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js连接MariaDB超时且被拒,求排查与解决方案

问题描述

我无法运行MariaDB官方文档中的示例程序,以下是基于文档示例修改后的代码:

const mariadb = require('mariadb');

const pool = mariadb.createPool({
    host: 'localhost',
    user: 'admin',
    password: 'adminpassword',
    database: 'userdb',
    port: 3306,
    connectionLimit: 5
});

async function f() {

    console.log(pool);

    let connection;
    
    try {
        console.log('Connection start');

        connection = await pool.getConnection();
        console.log('Connected');

        const rows = await connection.query('select * from users');
        console.log(rows);

        const res = await connection.query('insert into users value (?, ?)', [1, 'testuser']);
        console.log(res);

        await connection.release();
    }
    catch(exception) {
        console.log(exception);
    }

    if(connection) {
        return connection.end();
    }
}

f();

运行代码后得到如下输出:

node index.js 
PoolPromise {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  [Symbol(kCapture)]: false
}
Connection start
SqlError: (conn=-1, no: 45028, SQLState: HY000) retrieve connection from pool timeout after 10001ms
    (pool connections: active=0 idle=0 limit=5)
    at module.exports.createError (.../node_modules/mariadb/lib/misc/errors.js:57:10)
    at Pool._requestTimeoutHandler (.../node_modules/mariadb/lib/pool.js:345:26)
    at listOnTimeout (node:internal/timers:564:17)
    at process.processTimers (node:internal/timers:507:7) {
  text: 'retrieve connection from pool timeout after 10001ms\n' +
    '    (pool connections: active=0 idle=0 limit=5)',
  sql: null,
  fatal: false,
  errno: 45028,
  sqlState: 'HY000',
  code: 'ER_GET_CONNECTION_TIMEOUT'
}
node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

Error: connect ECONNREFUSED ::1:3306
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1471:16)
 From event:
    at .../node_modules/mariadb/lib/connection.js:115:13
    at new Promise (<anonymous>)
    at Connection.connect (.../node_modules/mariadb/lib/connection.js:103:12)
    at Pool._createConnection (.../node_modules/mariadb/lib/pool.js:402:16)
    at Pool._doCreateConnection (.../node_modules/mariadb/lib/pool.js:40:10)
    at listOnTimeout (node:internal/timers:564:17)
    at process.processTimers (node:internal/timers:507:7)
Emitted 'error' event on PoolPromise instance at:
    at Pool.emit (node:events:513:28)
    at .../node_modules/mariadb/lib/pool.js:258:22
    at process.processTicksAndRejections (node:internal/task_queues:95:5) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '::1',
  port: 3306,
  fatal: true,
  sqlState: 'HY000'
}

Node.js v19.3.0

我可以通过CLI和Beekeeper Studio正常连接数据库,现咨询:

  1. 问题原因
  2. 日志位置及开启方法
  3. 调试方案

解决方案

1. 问题原因

核心问题是Node.js程序尝试通过IPv6地址::1连接MariaDB,但你的MariaDB服务仅监听了IPv4的127.0.0.1,未开启IPv6支持。而CLI和Beekeeper Studio默认使用IPv4连接127.0.0.1,因此可以正常访问。连接池超时只是表象,本质是底层连接被拒绝导致无法创建有效连接。

2. 日志位置及开启方法

默认日志位置

  • Linux:/var/log/mariadb/mariadb.log 或 /var/log/mysql/mysql.log
  • Windows:MariaDB安装目录下的data文件夹,文件名为[主机名].err
  • macOS(brew安装):/usr/local/var/log/mariadb/mariadb.log

开启详细日志

  1. 编辑MariaDB配置文件:
    • Linux:/etc/my.cnf 或 /etc/mysql/my.cnf
    • Windows:安装目录下的my.ini
    • macOS(brew):/usr/local/etc/my.cnf
  2. 在[mysqld]段添加以下配置(替换路径为实际可写入的目录):
    general_log = 1
    general_log_file = /var/log/mariadb/general.log
    slow_query_log = 1
    slow_query_log_file = /var/log/mariadb/slow.log
    log_error = /var/log/mariadb/error.log
    
  3. 保存配置后重启MariaDB服务。

3. 调试方案

  • 强制使用IPv4连接:将代码中的host: 'localhost'改为host: '127.0.0.1',直接指定IPv4地址,验证是否解决问题。
  • 检查MariaDB监听地址:
    • Linux/macOS:执行netstat -tulpn | grep 3306,查看输出是否包含:::3306(IPv6监听)或0.0.0.0:3306(全地址监听),如果只有127.0.0.1:3306,则确认是IPv6未开启的问题。
    • Windows:执行netstat -ano | findstr :3306,查看监听地址类型。
  • 开启MariaDB IPv6支持:如果需要保留localhost配置,可在MariaDB配置文件的[mysqld]段添加bind-address = ::,重启服务后会同时监听IPv4和IPv6地址。
  • 捕获池错误事件:在代码中添加池错误监听,避免未捕获异常导致程序崩溃:
    pool.on('error', (err) => {
      console.error('连接池错误:', err);
    });
    
  • 测试基础连接:跳过连接池,直接创建单个连接测试,缩小问题范围:
    async function testDirectConn() {
      try {
        const conn = await mariadb.createConnection({
          host: '127.0.0.1',
          user: 'admin',
          password: 'adminpassword',
          database: 'userdb',
          port: 3306
        });
        console.log('直接连接成功');
        await conn.end();
      } catch (err) {
        console.error('直接连接失败:', err);
      }
    }
    testDirectConn();
    

内容的提问来源于stack exchange,提问作者user2138149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:06:49