ElIauk

MySQL 安装与库表设计基础

三种安装方式 学 MySQL 不必纠结装在哪,先把三种常见方式分清楚: Windows:官网下 MSI 安装包,一路下一步,记得勾选“Add to PATH”,最后设置 root 密码; Linux:用 yum 或 apt 装发行版仓库里的版本,或者下载 tar 包手动初始化; Docker:本地开

评论
MySQL 安装与库表设计基础

三种安装方式

学 MySQL 不必纠结装在哪,先把三种常见方式分清楚:

  • Windows:官网下 MSI 安装包,一路下一步,记得勾选“Add to PATH”,最后设置 root 密码;
  • Linux:用 yum 或 apt 装发行版仓库里的版本,或者下载 tar 包手动初始化;
  • Docker:本地开发最省事,一条命令起一个实例,删了不心疼。
docker run -d --name mysql8 \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e TZ=Asia/Shanghai \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

-v 把数据目录挂到命名卷上,容器删了数据还在。学习环境用 root 账号没问题,但别把这种命令原样搬到服务器上,生产环境要单独建业务账号。

初始化配置

MySQL 8.0 默认字符集已经是 utf8mb4,但显式写进配置文件更稳妥。Linux 下通常是 /etc/my.cnf:

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci
default-time-zone='+08:00'

改完重启服务,用 SQL 确认:

show variables like 'character_set_%';
select @@time_zone, now();

JDBC 连接串里也要带时区,否则可能差 8 小时:

jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

MySQL 8 默认的 caching_sha2_password 认证方式,老版本驱动可能连接失败,需要升级驱动,或者在连接串加 allowPublicKeyRetrieval=true。

数据类型与建表

先记住几条选择原则:

类型 场景 注意
bigint unsigned 主键 比 int 更抗增长,配合自增
decimal(12,2) 金额 不要用 float/double
datetime 业务时间 存“墙上时间”,不随时区转换
timestamp 自动更新时间 受时区影响,2038 年上限
varchar(n) 变长字符串 长度按实际需求给,别一律 255
tinyint 状态、逻辑删除 用 0/1 表示,字段名用 deleted
create table t_user (
    id bigint unsigned not null auto_increment comment '主键',
    username varchar(32) not null comment '用户名',
    mobile varchar(20) not null default '' comment '手机号',
    balance decimal(12,2) not null default 0.00 comment '余额',
    status tinyint not null default 0 comment '状态:0 正常,1 禁用',
    deleted tinyint not null default 0 comment '是否删除:0 否,1 是',
    created_at datetime not null default current_timestamp comment '创建时间',
    updated_at datetime not null default current_timestamp
        on update current_timestamp comment '更新时间',
    primary key (id),
    unique key uk_username (username),
    key idx_mobile (mobile)
) engine=InnoDB default charset=utf8mb4 comment='用户表';

表名加 t_ 前缀、字段名全小写下划线,是很多团队的约定,主要为了避开保留字、也和 Java 实体的驼峰命名形成清晰对应。

索引与约束基础

建表时顺手把索引想清楚,比上线后再加索引省事得多。先分清几种约束:

  • 主键:唯一且非空,InnoDB 里就是聚簇索引,一张表只能有一个;
  • 唯一索引:保证列值不重复,允许 null(多个 null 不算重复);
  • 普通索引:只为加速查询,不约束数据;
  • 外键:保证引用完整性,但高并发写入时容易成为瓶颈,互联网项目通常不建物理外键,改由业务保证。

联合索引要记住最左前缀:(a, b, c) 能支持 a、a,b、a,b,c 的查询,但单独查 b 或 c 用不上。所以把区分度高、查询频率高的列放左边。

索引不是越多越好。每个索引都占磁盘、拖慢写入,还会增加优化器选错索引的概率。只为真正出现在 where、order by、join 条件里的列建索引,写完用 explain 看一眼有没有走索引。

字符串字段建索引要控制长度。varchar(255) 整列建索引占空间很大,可以只索引前 20 个字符(key idx_name (name(20))),但前缀索引不支持覆盖索引,要权衡。

常见坑

1. 以为 utf8 就是完整的 UTF-8

MySQL 里的 utf8 最多存 3 个字节,emoji 和一些生僻字存不进去,插入时会报 Incorrect string value。真正完整的是 utf8mb4,建库建表、连接串、客户端三处都要对上。

2. 时区差 8 小时

数据库里存的时间和页面显示的差 8 小时,通常是连接串没写 serverTimezone,或者服务器时区是 UTC。先执行 select now() 看数据库当前时间,再查 JDBC 连接参数,两头对齐。

3. 用 root 远程连接

为了图省事把 root 的 host 改成 %,等于把整台库暴露出去。正确做法是建业务账号,只授予必要的库权限:

create user 'app'@'%' identified by '请替换成强密码';
grant select, insert, update, delete on demo.* to 'app'@'%';

grant all 和 *.* 留给 DBA,业务账号用不到。

4. 表名大小写不一致

Windows 和 macOS 上 MySQL 默认不区分表名大小写,Linux 默认区分。本地 select * from t_User 能跑,部署到 Linux 就报表不存在。统一用小写表名,从根源上避免。

5. 用浮点数存金额

double 存 0.1 再加 0.2,结果可能是 0.30000000000000004。金额字段一律用 decimal,Java 里对应 BigDecimal。

排查步骤

  1. 连不上:先用 mysql -h 主机 -P 3306 -u 用户 -p 在服务器本机试,排除网络和防火墙;
  2. 字符集问题:show variables like 'character_set_%',重点看 character_set_server 和 character_set_client;
  3. 时区问题:select @@global.time_zone, @@session.time_zone, now();
  4. 表不存在:确认库名、表名大小写、当前连接的 database;
  5. 启动失败:看 error.log,常见原因是端口被占、数据目录权限不对、配置文件语法错误。

参考

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者