Nodejs mysql2+express+yaml

现在把需要把mysqlexpress,nodejs连接起来。

安装依赖

复制代码
npm install mysql2 express js-yaml
  1. mysql2 用来连接mysql和编写sql语句
  2. express 用来提供接口 增删改差
  3. js-yaml 用来编写配置文件

编写代码

  • db.config.yaml
yaml 复制代码
db:
   host: localhost #主机
   port: 3306 #端口
   user: root #账号
   password: '123456' #密码 一定要字符串
   database: xiaoman # 库
  • index.js
js 复制代码
import mysql2 from "mysql2/promise";
import * as jsyaml from "js-yaml";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import express from "express";

// ESM 获取当前文件所在目录路径
const __filename = fileURLToPath(import.meta.url); //C:\CN\全栈AI\node\nodecode\mysql-express-yaml\index.js
const __dirname = path.dirname(__filename); //C:\CN\全栈AI\node\nodecode\mysql-express-yaml
console.log(__filename, __dirname);
// 读取 db.config.yaml 文件
const yamlText = fs.readFileSync(
  path.join(__dirname, "./db.config.yaml"),
  "utf8"
);
const config = jsyaml.load(yamlText);

// 创建数据库连接------是异步的,所以下面都要用async await
const sql = await mysql2.createConnection({
  ...config.db,
});
// console.log('sql', sql)

const app = express();
app.use(express.json());

//查询接口 全部
app.get("/", async (req, res) => {
  const [data] = await sql.query("select * from user");
  res.send(data);
});
//单个查询 params
app.get("/user/:id", async (req, res) => {
  const [row] = await sql.query(
    `select * from user where id = ${req.params.id}`
  );
  // const [row] = await sql.query(`select * from user where id = ?`, [
  //   req.params.id,
  // ]);
  res.send(row);
});

//新增接口
app.post("/create", async (req, res) => {
  const { name, age, address } = req.body;
  await sql.query(`insert into user(name,age,address) values(?,?,?)`, [
    name,
    age,
    address,
  ]);
  res.send({ ok: 1 });
});

//编辑
app.post("/update", async (req, res) => {
  const { name, age, address, id } = req.body;
  await sql.query(`update user set name = ?,age = ?,address = ? where id = ?`, [
    name,
    age,
    address,
    id,
  ]);
  res.send({ ok: 1 });
});
//删除
app.post("/delete", async (req, res) => {
  await sql.query(`delete from user where id = ?`, [req.body.id]);
  res.send({ ok: 1 });
});
const port = 3000;

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
  • index.http

方便测试接口

http 复制代码
# 查询全部
 GET http://localhost:3000/ HTTP/1.1

# 单个查询
GET http://localhost:3000/user/2 HTTP/1.1

# 添加数据
POST http://localhost:3000/create HTTP/1.1
Content-Type: application/json

{
    "name":"张三",
    "age":18
}

# 更新数据
POST http://localhost:3000/update HTTP/1.1
Content-Type: application/json

{
    "name":"法外狂徒",
    "age":20,
    "id":23
}


#删除
# POST http://localhost:3000/delete HTTP/1.1
# Content-Type: application/json

# {
#     "id":24
# }

db.config.yaml

db.config.yaml数据库配置文件 ,后缀 .yaml / .yml。 作用:把数据库连接信息抽离到配置文件,不写死在代码里

host、端口、账号、密码、库名,全部写在 yaml,代码读取这个文件获取参数,再去连接 mysql2。

好处:

  1. 代码和配置分离;改数据库信息不用修改 js 代码
  2. 开发环境、测试、生产环境可以放不同配置
  3. yaml 格式简洁,比 json 少写引号逗号

⚠️ 重要:yaml 严禁 tab 缩进,只能用空格,一般 2 空格缩进。

典型完整格式 db.config.yaml

yaml 复制代码
# db.config.yaml
# mysql数据库配置
mysql:
  host: 127.0.0.1
  port: 3306
  user: root
  password: "123456"
  database: test_db
  charset: utf8mb4
  # 连接池配置 mysql2 pool
  connectionLimit: 10
  waitForConnections: true
  queueLimit: 0

# 也可以区分环境
dev:
  mysql:
    host: 127.0.0.1
    port: 3306
    user: root
    password: "dev123"
    database: dev_database

prod:
  mysql:
    host: 192.168.1.100
    port: 3306
    user: prod_user
    password: "@Prod#2026"
    database: prod_db

createPool vs createConnection 核心区别

php 复制代码
// ① 创建连接池
const pool = mysql2.createPool({ 
  host: dbConf.host, 
  port: dbConf.port, 
  user: dbConf.user, 
  password: dbConf.password, 
  database: dbConf.database, 
  connectionLimit: dbConf.connectionLimit, 
  waitForConnections: dbConf.waitForConnections 
});

// ② 创建单次连接
const sql = await mysql2.createConnection({ ...config.db })

1. createConnection 单次连接

创建一条独立数据库连接,用完需要手动关闭

csharp 复制代码
const conn = await mysql2.createConnection({...config.db})

// 查询
const [rows] = await conn.query('select * from user')

// ⚠️ 用完必须手动关闭
await conn.end()

特点

  1. 每次调用 createConnection新建一条物理 TCP 连接和 MySQL 握手认证。
  2. 请求量大的时候,频繁创建销毁连接,性能差。
  3. 如果忘记 conn.end(),连接会一直挂在 MySQL,占用连接数,会造成连接泄漏
  4. 适合:脚本、一次性小程序,只执行少量 SQL 就退出
  5. 不适合 Web 服务接口(Express/Koa) 。每来一个 http 请求新建连接会把 MySQL 连接打满。

如果你写接口,每访问一次接口执行一次createConnection,会疯狂新建连接。

2. createPool 连接池(Web 项目生产环境推荐

连接池:提前创建好一批数据库连接,放在池子里面,复用连接

arduino 复制代码
const pool = mysql2.createPool({
  ...config.db,
  connectionLimit: 10, //池子最多保存10条连接
  waitForConnections: true
})

// 直接使用pool,不需要手动获取/释放连接!
const [rows] = await pool.query('SELECT * FROM user')

工作原理

  1. 初始化时,维护最多 connectionLimit 条连接。
  2. 执行 pool.query():自动从池子里拿空闲连接,执行 SQL,执行完自动归还连接回池子 ,不需要手动.end()
  3. 并发请求过来,复用已有连接,不需要反复和 MySQL 握手认证,性能高
  4. waitForConnections:true:池子满了,新请求排队等待空闲连接,而不是直接报错。

特点

  • ✅ 连接复用,性能高,避免反复创建销毁 TCP
  • ✅ 自动管理连接,不会连接泄漏
  • ✅ 适合 web 服务、接口服务(Express/Koa 后端必用)
  • ✅ 可以直接 pool.query(),不用手动拿连接
  • 如果你需要事务,可以手动取出连接:const conn = await pool.getConnection(),用完 conn.release() 归还池子。

关键对比表

表格

项目 createConnection createPool(连接池)
连接行为 每次新建物理连接 复用池子里已有连接
关闭 必须手动await conn.end() 自动归还,不用手动关闭
适用场景 一次性脚本、简单 demo Web 接口、后端服务(生产首选)
并发性能 差,频繁创建销毁 好,连接复用
泄漏风险 容易忘记 end,发生泄漏 几乎不会泄漏
事务 直接 conn.beginTransaction () 需要pool.getConnection()拿到连接再事务

两个写法简单示例

createConnection(脚本示例)

javascript 复制代码
// 适合一次性脚本执行完就退出
const conn = await mysql2.createConnection({...config.db})
const [rows] = await conn.query('select 1')
console.log(rows)
await conn.end() // 必须关闭!

createPool(web 后端,项目标准写法)

javascript 复制代码
// db.js 全局只初始化一次pool,整个项目复用这一个pool
const pool = mysql2.createPool({
  ...config.db,
  connectionLimit: 10,
  waitForConnections: true
})

export default pool

// 在业务接口直接导入pool使用
import pool from './db.js'
const [rows] = await pool.query('select * from user')

事务场景区别

  1. createConnection
vbnet 复制代码
const conn = await mysql2.createConnection({...config.db})
await conn.beginTransaction()
await conn.query(sql1)
await conn.query(sql2)
await conn.commit()
await conn.end()
  1. createPool 事务(必须手动取出连接)
csharp 复制代码
const conn = await pool.getConnection() // 从池子拿一条连接
try{
  await conn.beginTransaction()
  await conn.query(sql1)
  await conn.query(sql2)
  await conn.commit()
}catch(e){
  await conn.rollback()
}finally{
  conn.release() // 归还到池子!!不是end()
}

pool 拿到的连接用 .release() 归还池子,不能用 .end(),end 会直接销毁连接

开发建议

  1. 写后端接口(express):一定用 createPool,全局只 new 一次 pool,不要每次接口都创建连接。
  2. 本地跑一次性脚本:可以简单用 createConnection。
  3. 不要把 pool 到处重复创建,整个应用只初始化一个 pool 实例

很多新手踩坑:在路由函数内部写 const pool = mysql2.createPool({...}),每次访问接口新建一个池子,这是错误。pool 只需要在项目启动初始化一次。

结合你的 yaml 配置修改你的 db.config.yaml

yaml 复制代码
db:
  host: localhost
  port: 3306
  user: root
  password: '123456'
  database: xiaoman
  connectionLimit: 10
  waitForConnections: true

读取后直接:

arduino 复制代码
const pool = mysql2.createPool({ ...config.db })
相关推荐
风尘小子3 小时前
node.js系列:process配置
前端·node.js
怕浪猫3 小时前
ZCode 开源了来看看这是个什么东西
node.js·github·代码规范
flash俊杰1 天前
Electron 打包后窗口 30 秒不出现:一个 ABI 不匹配的血案
electron·node.js
@tangguo1231 天前
npm 和 yarn 配置说明
前端·javascript·npm·node.js·yarn
flash俊杰1 天前
一套代码接入所有大模型:OpenAI 兼容适配器设计
node.js·openai
右耳朵猫AI1 天前
Node.js周刊2026W38 | 进程中断缺陷修复、Copilot 迁至 Rust、Node 新增 VFS
javascript·后端·node.js
光影少年2 天前
Express 中间件原理
后端·node.js·express
时速GEO系统2 天前
初元 AI V1.1 版本升级,首个正式版发布一周・实现生成、部署、上线、优化全流程自动化闭环
人工智能·数据挖掘·node.js
console.log('npc')2 天前
06 — Model 层:数据模型与操作
前端·后端·node.js·express