前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# mysql模块

30 秒速记

  • mysql 包是 Node 连 MySQL 的驱动,回调风格;新项目一般直接用 mysql2,自带 Promise API
  • MySQL 8 默认认证插件是 caching_sha2_password,老 mysql 包连不上,报 ER_NOT_SUPPORTED_AUTH_MODE
  • 线上用连接池 createPool,控制 connectionLimit,用完一定 release
  • 值一律用 ? 占位符传参,别拼字符串;表名、排序字段用白名单
  • 进程退出前 pool.end(),不然连接挂着,脚本不退出

mysql 模块就是 Node 和 MySQL 之间的翻译官,帮你建连接、发 SQL、把结果变成 JS 对象。 它是纯 JS 写的、回调风格,教程里很常见,但现在新项目我一般选 mysql2:API 基本兼容,多了 mysql2/promise 可以直接 await,还支持 MySQL 8 默认的 caching_sha2_password 认证。不管用哪个,三件事是固定的:用连接池、用占位符防注入、用完把连接还回去。

理解「mysql模块」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 database 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

Node 里操作 MySQL,本质就是三步:拿到一个连接,发一条 SQL,拿结果。下面用 mysql2/promise 写一个最小可运行的例子,概念和 mysql 包是一样的,只是不用写回调。

// npm i mysql2
const mysql = require('mysql2/promise')

const pool = mysql.createPool({
  host: '127.0.0.1',
  user: 'root',
  password: process.env.DB_PASSWORD, // 密码别写死在代码里
  database: 'koa_demo',
  connectionLimit: 10,
})

async function main() {
  // pool.query 会自动 getConnection + release
  const [rows] = await pool.query('SELECT id, email FROM user WHERE id = ?', [1])
  console.log(rows) // [ { id: 1, email: '1@example.com' } ]
  await pool.end() // 关掉连接池,进程才会退出
}

main().catch(err => {
  console.error(err.code, err.message) // 比如 ER_ACCESS_DENIED_ERROR
  process.exit(1)
})
@前端进阶之旅: 代码已经复制到剪贴板

几个容易踩的点:

  • pool.query 是 getConnection + query + release 的简写,绝大多数查询用它就够了。只有事务这种「多条语句必须在同一个连接上执行」的场景,才需要手动 getConnection,并在 finally 里 release。
  • 错误要按 err.code 区分:ECONNREFUSED 是库没起来,ER_ACCESS_DENIED_ERROR 是账号密码错,ER_DUP_ENTRY 是唯一键冲突。只有连接类错误值得重试,唯一键冲突重试多少次都一样。
  • 时间字段建议用 DATETIME 或 TIMESTAMP,字符集用 utf8mb4,否则存 emoji 会报错。

面试官追问

追问 1本地装的 MySQL 8,用 mysql 包一连就报 ER_NOT_SUPPORTED_AUTH_MODE,怎么办?
参考回答

老 mysql 包不支持 MySQL 8 默认的 caching_sha2_password。最干净的办法是换 mysql2;实在不能换,就把账号改成 mysql_native_password,但这是在降安全性,只适合本地。

追问 2'SELECT * FROM user WHERE id = ' + id 这么写有什么问题?
参考回答

id 传个 1 OR 1=1 就把整张表查出来了,这是 SQL 注入。改成 query('SELECT * FROM user WHERE id = ?', [id]),驱动会负责转义。

追问 3排序字段是前端传的 orderBy,能放进 ? 占位符吗?
参考回答

不行,? 会把它当字符串值转义成 'name',排序就失效了。标识符要走白名单:const col = ['name', 'created_at'].includes(orderBy) ? orderBy : 'id',或者用 ?? 占位符做标识符转义。

追问 4脚本查完数据打印了结果,但进程就是不退出,为什么?
参考回答

连接池或连接还开着,事件循环里还有活跃的 socket。脚本最后调一次 pool.end() 或 connection.end(),进程就会自然退出。

追问 5mysql 和 mysql2 怎么选?
参考回答

新项目选 mysql2:维护活跃、有 Promise API、支持预处理语句 execute、性能也更好。老项目已经稳定跑着 mysql,没有遇到认证或性能问题,不必为了换而换。

# mysql模块

# 快速开始

30 秒速记

  • 三步走:装 MySQL 服务 → npm i mysql(或 mysql2)→ createConnection / createPool 发 SQL
  • 先在命令行用 mysql -u root -p 确认库能连上,再写 Node 代码,排错能少一半
  • 连接配置至少要有 host、user、password、database
  • 密码放环境变量,别写死在代码里提交上去

快速开始就是把「数据库能连上、Node 能发 SQL、能拿到结果」这条链路跑通。 我一般先不碰代码,用 mysql -u root -p 登进去,CREATE DATABASE 建好库,确认账号密码没问题;然后再装驱动写最小的 SELECT 1。这样一旦报错,就能分清是数据库本身的问题还是 Node 代码的问题。跑通后第一件事就是把密码挪到 .env 里。

理解「快速开始」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1Node 报 ECONNREFUSED 127.0.0.1:3306,第一步查什么?
参考回答

先确认 MySQL 服务有没有起来、端口是不是 3306,命令行 mysql -h 127.0.0.1 -u root -p 能不能连上。命令行都连不上,就不用去看 Node 代码了。

追问 2命令行能连上,Node 报 ER_ACCESS_DENIED_ERROR,为什么?
参考回答

账号密码或者授权的 host 不对。比如账号只授权了 'root'@'localhost',而 Node 用 127.0.0.1 走 TCP 连,MySQL 会把它当成不同的来源。

追问 3最小的连通性测试你会写什么?
参考回答

await pool.query('SELECT 1'),能返回就说明网络、账号、库都通了。服务启动时跑一次这个,失败直接退出,比等到第一个用户请求才报错强。

追问 4用 Docker 起 MySQL,Node 也在容器里,host 填 127.0.0.1 连不上?
参考回答

容器里的 127.0.0.1 是它自己。同一个 docker compose 网络里,host 要填服务名,比如 db。

# 安装MySQL数据库

30 秒速记

  • 本地开发三种装法:官网安装包 / brew install mysql / docker run mysql:8,我更推荐 Docker,删了不留垃圾
  • 装完先改 root 密码,再建一个业务专用账号,别让应用直接用 root
  • MySQL 8 默认认证 caching_sha2_password,老驱动会连不上
  • 字符集设成 utf8mb4,utf8 在 MySQL 里只有 3 字节,存不了 emoji

本地装 MySQL 只是为了有个能连的库,怎么省事怎么来,我一般直接用 Docker。 一条 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8 就起来了,不想要了删容器就行。装完要注意两件事:一是 MySQL 8 默认的认证方式,老的 mysql 包不支持,要么换 mysql2,要么给账号改认证插件;二是建库时指定 utf8mb4,不然用户昵称里带个 emoji 就插入失败。

https://www.mysql.com/downloads/

理解「安装MySQL数据库」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

mysql模块|Nodejs专题系列

# mysql模块

30 秒速记

  • mysql 包是 Node 连 MySQL 的驱动,回调风格;新项目一般直接用 mysql2,自带 Promise API
  • MySQL 8 默认认证插件是 caching_sha2_password,老 mysql 包连不上,报 ER_NOT_SUPPORTED_AUTH_MODE
  • 线上用连接池 createPool,控制 connectionLimit,用完一定 release
  • 值一律用 ? 占位符传参,别拼字符串;表名、排序字段用白名单
  • 进程退出前 pool.end(),不然连接挂着,脚本不退出

mysql 模块就是 Node 和 MySQL 之间的翻译官,帮你建连接、发 SQL、把结果变成 JS 对象。 它是纯 JS 写的、回调风格,教程里很常见,但现在新项目我一般选 mysql2:API 基本兼容,多了 mysql2/promise 可以直接 await,还支持 MySQL 8 默认的 caching_sha2_password 认证。不管用哪个,三件事是固定的:用连接池、用占位符防注入、用完把连接还回去。

理解「mysql模块」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 database 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

Node 里操作 MySQL,本质就是三步:拿到一个连接,发一条 SQL,拿结果。下面用 mysql2/promise 写一个最小可运行的例子,概念和 mysql 包是一样的,只是不用写回调。

// npm i mysql2
const mysql = require('mysql2/promise')

const pool = mysql.createPool({
  host: '127.0.0.1',
  user: 'root',
  password: process.env.DB_PASSWORD, // 密码别写死在代码里
  database: 'koa_demo',
  connectionLimit: 10,
})

async function main() {
  // pool.query 会自动 getConnection + release
  const [rows] = await pool.query('SELECT id, email FROM user WHERE id = ?', [1])
  console.log(rows) // [ { id: 1, email: '1@example.com' } ]
  await pool.end() // 关掉连接池,进程才会退出
}

main().catch(err => {
  console.error(err.code, err.message) // 比如 ER_ACCESS_DENIED_ERROR
  process.exit(1)
})
@前端进阶之旅: 代码已经复制到剪贴板

几个容易踩的点:

  • pool.query 是 getConnection + query + release 的简写,绝大多数查询用它就够了。只有事务这种「多条语句必须在同一个连接上执行」的场景,才需要手动 getConnection,并在 finally 里 release。
  • 错误要按 err.code 区分:ECONNREFUSED 是库没起来,ER_ACCESS_DENIED_ERROR 是账号密码错,ER_DUP_ENTRY 是唯一键冲突。只有连接类错误值得重试,唯一键冲突重试多少次都一样。
  • 时间字段建议用 DATETIME 或 TIMESTAMP,字符集用 utf8mb4,否则存 emoji 会报错。

面试官追问

追问 1本地装的 MySQL 8,用 mysql 包一连就报 ER_NOT_SUPPORTED_AUTH_MODE,怎么办?
参考回答

老 mysql 包不支持 MySQL 8 默认的 caching_sha2_password。最干净的办法是换 mysql2;实在不能换,就把账号改成 mysql_native_password,但这是在降安全性,只适合本地。

追问 2'SELECT * FROM user WHERE id = ' + id 这么写有什么问题?
参考回答

id 传个 1 OR 1=1 就把整张表查出来了,这是 SQL 注入。改成 query('SELECT * FROM user WHERE id = ?', [id]),驱动会负责转义。

追问 3排序字段是前端传的 orderBy,能放进 ? 占位符吗?
参考回答

不行,? 会把它当字符串值转义成 'name',排序就失效了。标识符要走白名单:const col = ['name', 'created_at'].includes(orderBy) ? orderBy : 'id',或者用 ?? 占位符做标识符转义。

追问 4脚本查完数据打印了结果,但进程就是不退出,为什么?
参考回答

连接池或连接还开着,事件循环里还有活跃的 socket。脚本最后调一次 pool.end() 或 connection.end(),进程就会自然退出。

追问 5mysql 和 mysql2 怎么选?
参考回答

新项目选 mysql2:维护活跃、有 Promise API、支持预处理语句 execute、性能也更好。老项目已经稳定跑着 mysql,没有遇到认证或性能问题,不必为了换而换。

# mysql模块

# 快速开始

30 秒速记

  • 三步走:装 MySQL 服务 → npm i mysql(或 mysql2)→ createConnection / createPool 发 SQL
  • 先在命令行用 mysql -u root -p 确认库能连上,再写 Node 代码,排错能少一半
  • 连接配置至少要有 host、user、password、database
  • 密码放环境变量,别写死在代码里提交上去

快速开始就是把「数据库能连上、Node 能发 SQL、能拿到结果」这条链路跑通。 我一般先不碰代码,用 mysql -u root -p 登进去,CREATE DATABASE 建好库,确认账号密码没问题;然后再装驱动写最小的 SELECT 1。这样一旦报错,就能分清是数据库本身的问题还是 Node 代码的问题。跑通后第一件事就是把密码挪到 .env 里。

理解「快速开始」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1Node 报 ECONNREFUSED 127.0.0.1:3306,第一步查什么?
参考回答

先确认 MySQL 服务有没有起来、端口是不是 3306,命令行 mysql -h 127.0.0.1 -u root -p 能不能连上。命令行都连不上,就不用去看 Node 代码了。

追问 2命令行能连上,Node 报 ER_ACCESS_DENIED_ERROR,为什么?
参考回答

账号密码或者授权的 host 不对。比如账号只授权了 'root'@'localhost',而 Node 用 127.0.0.1 走 TCP 连,MySQL 会把它当成不同的来源。

追问 3最小的连通性测试你会写什么?
参考回答

await pool.query('SELECT 1'),能返回就说明网络、账号、库都通了。服务启动时跑一次这个,失败直接退出,比等到第一个用户请求才报错强。

追问 4用 Docker 起 MySQL,Node 也在容器里,host 填 127.0.0.1 连不上?
参考回答

容器里的 127.0.0.1 是它自己。同一个 docker compose 网络里,host 要填服务名,比如 db。

# 安装MySQL数据库

30 秒速记

  • 本地开发三种装法:官网安装包 / brew install mysql / docker run mysql:8,我更推荐 Docker,删了不留垃圾
  • 装完先改 root 密码,再建一个业务专用账号,别让应用直接用 root
  • MySQL 8 默认认证 caching_sha2_password,老驱动会连不上
  • 字符集设成 utf8mb4,utf8 在 MySQL 里只有 3 字节,存不了 emoji

本地装 MySQL 只是为了有个能连的库,怎么省事怎么来,我一般直接用 Docker。 一条 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8 就起来了,不想要了删容器就行。装完要注意两件事:一是 MySQL 8 默认的认证方式,老的 mysql 包不支持,要么换 mysql2,要么给账号改认证插件;二是建库时指定 utf8mb4,不然用户昵称里带个 emoji 就插入失败。

https://www.mysql.com/downloads/

理解「安装MySQL数据库」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 database 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1用户昵称存了个 emoji,插入时报 Incorrect string value,为什么?
参考回答

表或列的字符集是 utf8,MySQL 的 utf8 最多 3 字节,emoji 要 4 字节。建表用 CHARSET=utf8mb4,连接配置里也写 charset: 'utf8mb4'。

追问 2应用连库为什么不建议用 root?
参考回答

root 能删库、能改权限,一旦有注入漏洞就是全库沦陷。给应用建个账号,只授予业务库的增删改查权限。

追问 3团队里每个人本地 MySQL 版本不一样,导致行为不一致,怎么统一?
参考回答

在仓库里放一个 docker-compose.yml,把镜像版本写死成 mysql:8.0,大家都 docker compose up。版本一致了,很多「我这里没问题」就消失了。

追问 4容器删掉重建,数据全没了,怎么办?
参考回答

数据目录要挂卷,比如 -v mysql-data:/var/lib/mysql。不挂卷的话数据只在容器的可写层里,删容器就跟着没了。

# 安装 node.js的mysql模块

30 秒速记

  • npm install mysql,现在 npm 5+ 默认就会写进 dependencies,--save 可以省掉
  • 新项目更推荐 npm install mysql2,API 兼容,多了 Promise 和 MySQL 8 认证支持
  • 驱动是纯 JS 实现,不需要编译原生模块,Windows 上装也不会卡在 node-gyp
  • 提交 package-lock.json 或 yarn.lock,保证线上装到的版本和本地一致

装驱动就一条命令,真正要想清楚的是选 mysql 还是 mysql2。 mysql 是老牌的纯 JS 驱动,回调风格,对 MySQL 8 默认认证支持不好;mysql2 基本兼容它的 API,还提供 mysql2/promise,配合 async/await 写起来干净很多。我新项目都直接装 mysql2。另外 npm 5 之后 install 默认就会写进 dependencies,老教程里的 --save 不写也一样。

← 7.3 异步上传图片实现8.2 async await封装使用mysql →

fe