第 1 章 · 关系型数据库概论与 MySQL 8 环境搭建
本章目标:理解关系型数据库(RDBMS)核心概念(表、行、列、主键、外键);在 Windows / macOS 上用 Docker Compose 启动 MySQL 8;掌握 mysql 客户端连接与基本操作;配置 utf8mb4 字符集与排序规则;能对比 SQL vs NoSQL 选型;在虚构项目 ~/go-learn/shop-db 中完成 shop_db 库初始化,为 ch02~ch06 纯 SQL 练习打基础。
学时建议:3~4 小时(含 Docker 安装 1 小时 + 跟练 2 小时)
前置:完成 go-dev ch01~ch03(Go 基础与 go mod);了解 HTTP 与 JSON 即可。本章只教纯 SQL 与数据库设计,ORM 应用见 gin-web GORM;database/sql 系统讲解见 go-database ch08+;标准库 net/http 见 go-dev ch12;数据库入门见 go-database ch08。
1.1 场景说明:shop-db 为何需要 MySQL
贤紫优选 虚构商城的后端 API 部署在 https://api.example.com(教学引用,勿连真实生产)。商品、用户、订单等持久化数据存放在 MySQL 8 库 shop_db 中。你在本地目录 ~/go-learn/shop-db 搭建与线上一致的 Docker Compose 环境,用 mysql 客户端 或 Go database/sql 选修片段 验证连接。
┌─────────────────────────────────────────────────────────┐
│ C 端 / 运营后台(gin-web 后续章节) │
└───────────────────────────┬─────────────────────────────┘
│ HTTP /api/v1/products/:slug
▼
┌─────────────────────────────────────────────────────────┐
│ 应用层(本章不涉及 ORM,ch02 起直接写 SQL) │
└───────────────────────────┬─────────────────────────────┘
│ TCP 3306
▼
┌─────────────────────────────────────────────────────────┐
│ MySQL 8 · shop_db · utf8mb4 · InnoDB │
│ users · products · orders · order_lines │
└─────────────────────────────────────────────────────────┘
| 全站字段约定(与 django-web / gin-web 对齐) | 说明 |
|---|---|
products.slug | URL 友好标识,UNIQUE |
products.is_published | 是否上架,布尔 |
products.price | 整数分(2999 = ¥29.99) |
users.email | 登录账号,UNIQUE |
users.password_hash | 密码哈希,禁止存明文 |
orders / order_lines | 标准电商订单头 + 明细 |
分工说明:go-database 教「怎么设计表、怎么写 SQL」;gin-web 教「GORM 如何映射这些表」。不要在本章写 gorm.Model,ch05/ch06 设计完表结构后再对照框架文档。go-dev ch11 仅预览 MySQL 连接;系统 database/sql · GORM 见 go-database ch08+。
1.2 关系型数据库核心概念
关系型数据库以二维表(relation)组织数据,表之间通过外键建立逻辑关联,由 SQL 声明式查询与变更。
| 术语 | 英文 | 示例(shop_db) |
|---|---|---|
| 数据库 | Database | shop_db |
| 表 | Table | products、users |
| 行 / 记录 | Row / Record | 一条商品「Go 语言手册」 |
| 列 / 字段 | Column / Field | slug、price |
| 主键 | Primary Key | id(自增 BIGINT) |
| 外键 | Foreign Key | order_lines.product_id → products.id |
| 索引 | Index | products(slug) UNIQUE |
| 事务 | Transaction | 下单扣库存 + 写订单,要么全成功要么全回滚 |
ACID(Atomicity 原子性、Consistency 一致性、Isolation 隔离性、Durability 持久性)是关系库事务的四大特性,ch04 会深入实践。
与文件 / Excel 对比:
| 维度 | CSV / JSON 文件 | MySQL |
|---|---|---|
| 并发写入 | 易冲突、难锁 | InnoDB 行锁 + MVCC |
| 关联查询 | 应用层 JOIN | SQL JOIN 一次完成 |
| 约束 | 无 | PRIMARY KEY、UNIQUE、CHECK |
| 备份恢复 | 手工拷贝 | mysqldump、binlog、复制 |
1.3 MySQL 8 新特性(教学关注)
| 特性 | 说明 |
|---|---|
| 默认字符集 utf8mb4 | 完整 Unicode,含 emoji |
| InnoDB 默认引擎 | 支持事务、外键、行锁 |
| 窗口函数 | ROW_NUMBER()、RANK()(ch02 选修) |
| JSON 列类型 | 灵活属性;电商核心仍用规范列 |
| 角色(Role) | 权限管理;本地 dev 用 root 即可 |
| 性能 | 索引优化、直方图;ch05 讲 B+Tree |
MySQL 8 与 MariaDB 10.x 语法大体兼容,本课以 MySQL 8.0 为准。
1.4 Docker Compose 启动 MySQL 8
在 ~/go-learn/shop-db 创建编排文件(Windows 路径 %USERPROFILE%\go-learn\shop-db)。
docker-compose.yml:
services:
mysql:
image: mysql:8.0
container_name: shop-db-mysql
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: dev_root_pass_change_me
MYSQL_DATABASE: shop_db
MYSQL_USER: shop_user
MYSQL_PASSWORD: dev_shop_pass_change_me
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-authentication-plugin=mysql_native_password
volumes:
- mysql_data:/var/lib/mysql
- ./init:/docker-entrypoint-initdb.d:ro
volumes:
mysql_data:
init/01-charset.sql(首次启动自动执行):
-- shop-db 初始化:字符集与库(虚构教学环境)
CREATE DATABASE IF NOT EXISTS shop_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE shop_db;
-- 后续 ch05 会正式建表;此处仅验证连接
SELECT 'shop_db ready' AS status, @@character_set_database AS charset;
Windows(PowerShell):
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\go-learn\shop-db\init"
cd $env:USERPROFILE\go-learn\shop-db
docker compose up -d
docker compose ps
docker compose logs mysql --tail 20
macOS(Terminal):
mkdir -p ~/go-learn/shop-db/init
cd ~/go-learn/shop-db
docker compose up -d
docker compose ps
| 检查项 | 期望结果 |
|---|---|
docker compose ps | shop-db-mysql Up,端口 0.0.0.0:3306->3306 |
| 首次启动 | init/01-charset.sql 自动执行 |
| 数据持久化 | 命名卷 mysql_data,down 不丢数据 |
安全提示:密码仅供本地 Docker;禁止提交真实生产密钥到 Git。.env 可替代硬编码(选修)。
1.5 mysql 客户端:连接与元命令
方式 A · 容器内 mysql(无需本机安装客户端):
docker exec -it shop-db-mysql mysql -ushop_user -pdev_shop_pass_change_me shop_db
方式 B · 本机 mysql 客户端:
mysql -h 127.0.0.1 -P 3306 -ushop_user -pdev_shop_pass_change_me shop_db
Windows:可安装 MySQL Shell 或使用 Docker 方式 A。
常用元命令与 SQL:
-- 查看当前库与字符集
SELECT DATABASE(), @@character_set_database, @@collation_database;
-- 查看版本
SELECT VERSION();
-- 查看表(ch05 建表后才有)
SHOW TABLES;
-- 退出
EXIT;
| 元命令 | 作用 |
|---|---|
\c | 清除当前未完成的 SQL |
SOURCE file.sql | 执行脚本文件 |
SHOW CREATE TABLE products\G | 查看建表语句(ch05) |
DESCRIBE users | 查看列定义 |
GUI 选修:MySQL Workbench、DBeaver、DataGrip——连接参数与 CLI 相同(Host 127.0.0.1,Port 3306)。
1.6 字符集 utf8mb4 与排序规则
为何不用 utf8? MySQL 早期 utf8 实为 utf8mb3(最多 3 字节),无法存储 emoji 等 4 字节字符。商城商品名、用户昵称可能含 emoji,必须 utf8mb4。
| 级别 | 设置方式 | 推荐值 |
|---|---|---|
| 服务器 | my.cnf / docker command | utf8mb4 |
| 数据库 | CREATE DATABASE ... CHARACTER SET | utf8mb4_unicode_ci |
| 表 | CREATE TABLE ... DEFAULT CHARSET=utf8mb4 | 同上 |
| 列 | VARCHAR(255) CHARACTER SET utf8mb4 | 显式或继承表 |
验证 emoji 存储:
CREATE TABLE IF NOT EXISTS _charset_test (
id INT PRIMARY KEY AUTO_INCREMENT,
note VARCHAR(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO _charset_test (note) VALUES ('贤紫优选 📦 测试');
SELECT note, CHAR_LENGTH(note) AS char_len, LENGTH(note) AS byte_len
FROM _charset_test;
DROP TABLE _charset_test;
排序规则对比:
| Collation | 特点 |
|---|---|
utf8mb4_unicode_ci | 通用、多语言,推荐默认 |
utf8mb4_0900_ai_ci | MySQL 8 默认,性能更好 |
utf8mb4_bin | 二进制比较,区分大小写 |
与 gin-web 中 DB_DSN 环境变量=...characterEncoding=utf8&useUnicode=true 及 django-web ch04 charset=utf8mb4 保持一致。