
1. 为什么我决定把MySQL基础从头过一遍第一天的安排长这样先交代一下背景。我之前用SQL基本属于“能跑就行”的状态会写select、会join、会插数据但真要说到索引原理、事务隔离级别、连接池参数怎么调脑子里是糊的。项目一忙就是复制粘贴改改表名出问题就靠重启大法。最近手里接了个新项目数据库部分要从建库开始自己设计我才发现自己对MySQL的理解其实只停留在表面。所以就有了这份“MySQL学习笔记”系列。DAY01这一篇我给自己定的目标很简单——不贪多把“环境、建库、建表、增查”这四件事彻底搞明白每一步都自己敲一遍把坑记下来。我建议刚接触MySQL的朋友也别一上来就啃《高性能MySQL》或者看一堆面试题第一天先把地基打牢安装好一个能用的MySQL亲手建立一个数据库和一张表插入几条数据再用查询把它读出来。这四步走通了后面学索引、学事务、学调优才有实操基础。说句实话很多人第一天就挂在安装和连接上。我在网上随手一搜光是“mysql安装”“mysql无法连接”“mysql 2002错误”这类问题就占了大半。所以这篇DAY01不会讲太深的理论重点是把环境准备和基础操作讲透每一步都给出可复现的命令和参数让零基础的人照着敲也能跑通。2. 环境准备下载MySQL 8.0时我踩过的几个细节先说明一下我用的是Windows 11 MySQL 8.0.36连接工具用的MySQL自带的命令行没有额外装Navicat之类的图形工具。这么选择是有意的命令行能强迫你把每条SQL的真实语法记清楚而且后面写脚本、排查问题时命令行操作远比点鼠标可靠。2.1 下载版本怎么选zip包和安装包的区别去官网下载时会看到两个主流选项一个是MySQL Installer安装向导版一个是ZIP Archive免安装版。我第一次学的时候无脑选了安装向导版一路Next确实省事但有一个问题——它会在系统里注册一大堆服务项卸载的时候特别容易留垃圾。而且你很难看出MySQL到底装了哪些组件。我更推荐用ZIP Archive。做法很简单下载解压后手动配置my.ini再执行初始化命令。整个过程每一步都在自己掌控中出问题也容易定位。如果你不确定选哪个直接下载mysql-8.0.36-winx64.zip这个包大小在200MB左右里面已经包含了服务端和客户端。2.2 配置文件my.ini的必备参数解压完不要急着启动先新建一个my.ini放在MySQL根目录下。网上有很多模板但第一天我建议只用最简配置其余参数等学到相关章节再加否则你都不知道自己配了些什么[mysqld] # 设置端口 port3306 # 指定MySQL安装目录 basedirD:/mysql-8.0.36-winx64 # 指定数据文件目录 datadirD:/mysql-8.0.36-winx64/data # 字符集 character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci # 默认存储引擎 default-storage-engineINNODB [client] port3306 default-character-setutf8mb4注意basedir和datadir一定要用正斜杠/不要用反斜杠\。我第一次写成了D:\mysql-8.0.36-winx64结果初始化时直接报错找不到路径。这是个特别蠢但特别常见的坑。2.3 初始化与启动服务的完整命令序列配置完my.ini打开管理员权限的CMD进入MySQL的bin目录按顺序执行# 1. 初始化数据目录生成data文件夹和root账号 mysqld --initialize-insecure # 2. 注册Windows服务 mysqld --install mysql # 3. 启动服务 net start mysql # 4. 连接数据库因为initialize-insecureroot无密码 mysql -u root -p这里有个关键选择--initialize-insecure表示root账号初始密码为空--initialize则会生成一个随机密码并写入日志文件。我第一次用了--initialize结果登录时死活找不到那个临时密码后来才知道密码在data目录下的*.err文件里。对新手来说我推荐先用--initialize-insecure登录进去之后立刻用ALTER USER设置密码省去到处找密码的麻烦。连接成功后你会看到mysql提示符输入以下命令修改root密码并退出重登ALTER USER rootlocalhost IDENTIFIED BY YourStrongPssw0rd; FLUSH PRIVILEGES; EXIT;重登之后逐个跑一下下面几条命令确认环境彻底OKSELECT VERSION(); SELECT CURRENT_DATE(); SHOW DATABASES;如果三个结果都正常说明你的MySQL环境已经可以用了。这一步比你想的重要得多——我见过太多人装了MySQL却连不上最后排查半天发现是服务压根没启动。3. 建库建表别急着写代码先把数据模型想清楚环境就绪之后就是DAY01最核心的部分了。我先强调一个观念建库建表不是随便敲几条CREATE语句而是你在定义数据在这个系统里的“形状”。表结构设计得烂后面写查询、写索引、做报表都会痛苦。第一天不必追求设计多复杂的业务表但规范的习惯要从第一张表就养成。3.1 创建数据库时我为什么坚持用utf8mb4大多数教程会让你直接执行CREATE DATABASE test;。但我建议从第一天开始就写明字符集CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;为什么非要用utf8mb4而不是utf8因为MySQL里的utf8实际上最多只支持3字节编码像Emoji表情、生僻字都存不进去。以前我给表设置utf8结果业务里有用户昵称带了个emoji插入时直接报“Incorrect string value”错误。当时还没意识到是字符集的问题排查了很久。utf8mb4才是真正完整的UTF-8实现连emoji都能存。后面的COLLATE utf8mb4_unicode_ci是指排序规则ci是case insensitive也就是排序和比较时不区分大小写。这个细节等学到排序和索引时会体现区别第一天先按这个标准设上。查看数据库是否创建成功SHOW DATABASES;USE student_db;切换到你的库然后继续。3.2 第一张学生信息表的字段设计思路为了练手我建了一张学生信息表。这张表的结构我非常想让你仔细看因为它涵盖了MySQL最常用的几种数据类型而且每一条字段都能解释出设计理由CREATE TABLE student ( id INT NOT NULL AUTO_INCREMENT COMMENT 主键ID, student_no VARCHAR(20) NOT NULL COMMENT 学号, name VARCHAR(50) NOT NULL COMMENT 姓名, gender TINYINT NOT NULL DEFAULT 0 COMMENT 性别 0-未知 1-男 2-女, age TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 年龄, email VARCHAR(100) DEFAULT NULL COMMENT 邮箱, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, enrollment_date DATE NOT NULL COMMENT 入学日期, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_student_no (student_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生信息表;我逐条讲一下设计意图id INT NOT NULL AUTO_INCREMENT代理主键自增长。这里有个常见争议是否直接用student_no当主键我建议业务字段不要当主键因为学号虽然当前唯一但未来若涉及转校生、数据迁移业务主键很容易出问题。自增id是纯技术字段绝对稳定。gender TINYINT用数字表示性别而不是字符串是为了节省空间。TINYINT只占1字节而CHAR(2)至少占2字节更重要的是数字枚举在代码层好映射。加COMMENT注释是给团队看的这是职业习惯。age TINYINT UNSIGNED年龄不会为负加上UNSIGNED把取值范围从-128~127变成0~255。enrollment_date DATE日期类型只存年月日如果是需要时分秒的字段应该用DATETIME。create_time和update_time这两个字段是必加的几乎每张业务表都要有。DEFAULT CURRENT_TIMESTAMP表示插入时自动写入当前时间ON UPDATE CURRENT_TIMESTAMP表示更新记录时自动刷新时间省了大量应用层代码。MySQL 8.0的默认存储引擎是InnoDB我建表时还是习惯显式写ENGINEInnoDB。原因是InnoDB支持事务、支持行级锁即便当前业务用不上未来数据量上来后它也是更稳妥的选择。老项目里常见的MyISAM引擎虽然查询快但不支持事务崩溃恢复也弱新项目尽量不用。表创建后用下面命令确认一下结构是否和预期一致DESC student; SHOW CREATE TABLE student;DESC看到的是简化表格SHOW CREATE TABLE则能看到完整的建表语句注意对比一下系统是不是把utf8mb4_unicode_ci和InnoDB都正确应用了。4. 插入与查询第一天先跑通最常用的增查动作建表只是开始真正让表“活”起来的是数据操作。第一天我没有急着讲修改和删除因为增和查才是用得最频繁的操作也是后续一切操作的基础。先把这两个动作做到条件反射级别。4.1 插入数据的三种写法我推荐灵活混合使用插入语句最标准的写法INSERT INTO student (student_no, name, gender, age, email, enrollment_date) VALUES (202501001, 张三, 1, 18, zhangsanexample.com, 2025-09-01);注意我没有插入id、create_time、update_time这三个字段因为它们在建表时有默认逻辑数据库会自动处理。你只需要给业务字段赋值就行。另一种是批量插入一次塞多条INSERT INTO student (student_no, name, gender, age, email, enrollment_date) VALUES (202501002, 李四, 2, 19, lisiexample.com, 2025-09-01), (202501003, 王五, 1, 20, NULL, 2025-09-02), (202501004, 赵六, 0, 18, zhaoliuexample.com, 2025-09-03);批量插入的效率比一条一条插高得多。原因在于每一条INSERT语句都要经历一次完整的SQL解析、事务提交和日志写入而批量语句只进一次。以后在项目里导入初始数据、处理临时数据时这条技巧能省不少时间。如果你想在数据量很小的情况下看一眼全表可以直接SELECT * FROM student;不过我要提醒你SELECT *在开发环境练手没问题到了生产环境或者数据量大之后是个坏习惯。因为*会返回所有列浪费网络传输带宽而且当表结构新增字段时结果集会莫名其妙多出你不需要的数据。团队代码规范里通常明令禁止SELECT *。第一天可以这么看但心里要有这根弦。4.2 筛选与排序WHERE和ORDER BY是你每天都要用的先来一个最简单的筛选查“性别为男”的学生SELECT id, student_no, name, gender, age FROM student WHERE gender 1;再试试按年龄从大到小排序SELECT id, student_no, name, age FROM student ORDER BY age DESC;DESC是降序ASC是升序默认就是升序。关键词“mysql排序”“mysql设置默认值为0”其实都和这个有关。排序放在WHERE之后如果一个条件筛选一个排序这是最基本的查询骨架。综合一下找“2025年之后入学、年龄大于等于18岁的女生按年龄降序”SELECT name, age, enrollment_date FROM student WHERE gender 2 AND age 18 AND enrollment_date 2025-01-01 ORDER BY age DESC;再补充两个常用操作去重和模糊查询。SELECT DISTINCT gender FROM student; SELECT name, email FROM student WHERE email LIKE %example.com;DISTINCT会去掉重复值LIKE配合%做模糊匹配。这里有个性能提醒LIKE %xxx这样以%开头的写法会让索引失效全表扫描。第一天你数据量小感觉不出来等表里有几十万条记录时会发现查询慢得离谱。后续学到索引时我会专门讲这个问题今天先在脑门上贴个便条。你有没有注意到上面我每次查询都会明确写字段名这个习惯从第一天开始养后面写复杂SQL的时候收益极大——你能直观看出每条查询到底取了哪些数据排查问题快很多。5. 第一天必然遇到的坑错误2002、服务启动失败与字符集乱码标题里我放了“mysql学习笔记”但真正想让你记住的是那些不亲自滚一遍根本不知道的坑。第一天我把自己遇到的三个问题原原本本记录下来每个都给到排查链路和解决办法建议你也收藏起来。5.1 ERROR 2002Cant connect to local MySQL server through socket /tmp/mysql.sock这几乎是Linux和macOS上最常见的问题。报错长这样ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock (2)我第一次遇到时一脸懵还以为是socket文件丢了。后来排查链路走了一遍发现绝大多数情况根本不是socket文件坏了而是MySQL服务压根没启动。用命令行验证# 查看MySQL服务状态 systemctl status mysqld # 如果没启动启动它 systemctl start mysqld # 设置开机自启 systemctl enable mysqld然后把socket文件路径单独拎出来看一下mysql -h 127.0.0.1 -P 3306 -u root -p注意我用的是TCP/IP方式连接。如果这样能连上说明问题确实在socket文件路径上。去看一下MySQL配置文件里的socket参数默认写在/tmp/mysql.sock而你的客户端可能在找/var/run/mysqld/mysqld.sock两者不一致就会报2002。解决办法是在/etc/my.cnf里统一socket路径[mysqld] socket/var/run/mysqld/mysqld.sock [client] socket/var/run/mysqld/mysqld.sock改完重启服务。这个问题的根因就是“服务没起”或“客户端和服务端socket路径不一致”没有第三种常见可能。5.2 Windows下服务启动失败提示发生系统错误服务名无效用net start mysql时如果报“服务名无效”十有八九是服务注册名字里带版本号。我做安装向导版时注册的服务名是MySQL80不是mysql。所以建议你记住这套组合拳# 查看当前已注册的MySQL服务 sc query mysql # 如果服务名不对先移除旧的再重新注册 mysqld --remove mysqld --install mysql net start mysql5.3 插入中文后乱码三个层面都要统一乱码问题在旧版本里非常常见8.0版本已经优化很多但如果你还是看到了???这样的数据排查顺序要按三步走客户端字符集、连接字符集、表字符集。第一步先看当前会话的字符集SHOW VARIABLES LIKE character_set%;第二步确保命令行窗口和MySQL之间的字符集一致。Windows的CMD窗口我用过chcp 65001切到UTF-8但有时候会和MySQL客户端冲突一个更稳的方式是连接时显式指定mysql -u root -p --default-character-setutf8mb4第三步确认表本身的字符集SHOW TABLE STATUS LIKE student;如果这三层都统一成了utf8mb4中文基本不会乱码。我前几年处理过一个项目数据从Excel导入后大量乱码排查到最后就是Excel导出文件是GBK编码而MySQL表是utf8mb4。你只要有“数据从源头到存储编码要一路统一”这个意识就能省掉很多排查时间。6. 第一天的收尾动作备份、服务管理和下一步规划最后这一部分是我给自己留的每日固定动作。学习数据库不能只敲代码每天结束时要有“复盘 存档”的环节。哪怕你只学了几个小时也值得花十到十五分钟整理当天的笔记、检查环境状态。6.1 备份第一个库学会mysqldump的基本用法第一天建的表虽然数据量小但养成备份习惯非常关键。MySQL自带的mysqldump命令是备份的标配# 在CMD中执行不在mysql交互环境里 mysqldump -u root -p student_db D:/backup/student_db_20250101.sql这条命令会把student_db库的所有表结构和数据导成一个SQL文件。恢复的时候用mysql -u root -p student_db D:/backup/student_db_20250101.sql备份文件里是标准的SQL语句你打开看一眼就知道MySQL在底层是怎么创建表、怎么插入数据的。这比纯粹背命令有帮助得多。同时检查一下服务状态net start | findstr mysql这个结果能让你看到MySQL服务是否在运行。以后每次开机第一件事就是确认服务是否启动很多连接报错都源于此。6.2 我给DAY01划出的“必须掌握清单”学习最怕“感觉都会了一写就卡壳”。第一天结束前我建议你对着清单自测一遍能不看笔记写出来的才是真学会能不能用一句话说清楚数据库、表、字段、记录这几个概念的区别能不能独立写出一条CREATE TABLE语句并且说出每个字段类型为什么这么选能不能独立完成插入、查询、排序、筛选一组操作遇到ERROR 2002能不能自己定位是服务没起还是socket路径问题这四个问题如果都能答得上来DAY01就算真正过关了。答不上来也不要紧第二天回头再练一遍就好数据库学习本身就是反复循环。我在第一天最后还做了一件事把MySQL官方文档里关于CREATE TABLE的语法页保存到了书签。说实话网上的教程五花八门深浅不一但官方文档永远是最权威的。建议你也养成“遇到语法问题先查官方文档”的习惯而不是直接复制搜索结果里的语句。看得多了你会对那些不规范的写法越来越敏感。6.3 关于连接池、索引和后续学习的一点提前说明标题里我放了“mysql的数据库连接池”“mysql锁原理及面试题”这几个词但DAY01我坚决不讲太多。因为这些内容对这个阶段来说还太早——连接池涉及应用层和数据库之间的资源管理锁原理需要先理解事务是什么面试题更是建立在大量实操经验上的总结。就好比你还没学会走路先去看马拉松比赛的战术分析吸收不了。我给自己定的路线是DAY01环境与基础DAY02数据库设计规范与常用数据类型进阶DAY03查询进阶与常用函数DAY04索引原理与执行计划DAY05事务与锁DAY06连接池与性能调优入门。你如果也在学我建议你也把这个顺序参考起来每天只攻一个主题比囫囵吞枣强得多。最后分享一个小技巧我在命令行终端里用TEE记录了当天执行过的所有SQLTEE D:/mysql_learning_day01.log;这样当天敲过的每一条命令都会自动保存到日志文件里方便第二天复盘。很多老手不知道自己当天执行过什么全靠脑子和历史记录吃了不少亏。你从第一天就开始留这份痕迹一个月下来回头看会非常直观看到自己的进步轨迹。