带过不少新人,发现一个很有意思的现象:很多人简历上写着“熟悉 MySQL”,可真让他建一张表、写一条稍微复杂一点的查询,往往就开始卡壳。这不能全怪谁,MySQL 基础这门课,看着简单,实际新手期踩的坑一点也不少。作为目前应用最广泛的开源关系型数据库,MySQL 不管是做 Web 应用、移动端后端,还是数据仓库的中间层,几乎处处都能看到它的影子。这篇文章不打算堆砌高深理论,而是按一条完整的实操主线,带你把 MySQL 数据库基础扎扎实实走一遍:从环境搭建开始,到建库建表、增删改查、索引优化,再到日常工作里最高频的故障排查。适合刚入行想系统补数据库能力的开发者,也适合工作中要写 SQL 但总碰壁的数据分析师,准备面试想巩固基础的同学同样可以照着过一遍。
1. 内容整体设计与思路拆解
1.1 MySQL 在技术栈中的位置与价值
先说说为什么值得花时间学 MySQL。很多刚接触编程的朋友会有个误区,觉得现在 NoSQL 挺火,好像什么场景都能用 MongoDB、Redis 顶上。但实际在业务系统里,关系型数据库依然是绝对主力。MySQL 的优势很明确:免费开源、跨平台、稳定可靠、生态极其成熟。无论是个人独立开发的博客系统,还是企业级的订单、用户、权限模块,MySQL 都是数据库选型清单上的第一梯队。
从技术栈的角度看,MySQL 属于存储层,承担着“持久化”这个核心职责。程序可以重启,缓存可以失效,但用户数据必须躺在数据库里,不能丢。这就决定了我们不仅要会写 SQL,还得理解数据是怎么组织的、查询是怎么跑的,否则哪天线上出个慢查询,或者数据莫名其妙的丢了,你连排查方向都没有。
我之前带过一个新人,功能开发没问题,一到数据相关的活就发怵。后来我发现他不是笨,而是缺一套系统的基础框架。MySQL 的基础知识点其实是成体系的,东学一点西学一点,永远都是散的。只要把“实例 → 库 → 表 → 数据 → 索引 → 事务”这条链路理清楚,后面再接触任何关系型数据库都会很顺畅。
1.2 基础学习路径的设计逻辑
MySQL 基础的学习,我比较推荐一条主线:先搞懂 MySQL 是怎么跑起来的,再学库和表的创建,然后是 DML 语句(增删改查),再往后是索引和事务。为什么是这条线?因为它是按照数据在系统中的流转顺序来设计的。
举个例子,你写一个用户注册功能。用户点提交按钮,后端收到请求,首先要连接上 MySQL 实例,然后往库里某张表插入一条记录。如果表结构设计得不对,或者索引没建好,后续查询就会越用越慢。这个链条非常直观:实例是地基,库和表是房间,数据是房间里摆的东西,索引相当于给每件东西编了个检索目录,事务则是确保你同时搬多件东西时不至于磕碰损坏。
很多自学者容易犯的毛病是:上来就啃 B+ 树原理、隔离级别这些偏理论的东西,结果连一张表都建不利索。说实话,基础阶段你要掌握的 SQL 不超过二十种,核心就四类:增、删、改、查。把这些写熟练,理解 WHERE 的执行逻辑,再搞清楚 JOIN 是怎么把多张表关联起来的,日常开发里九成以上和数据库相关的活你都能应付。剩下的问题,基本都是用多了之后自然遇到的。这篇文章就按这个思路展开,保证你照着做完,能实打实上手。
2. 环境搭建与准备
2.1 安装方式选择与避坑
要学 MySQL,第一步当然是装环境。很多人在这一步就被劝退了,其实大可不必。目前主流版本是 MySQL 8.0 和 5.7,如果是从零开始学,直接选 8.0 就好,一方面它性能更好,另一方面 8.0 的默认字符集是 utf8mb4,对中文和各种生僻字的支持比 5.7 省心很多。
具体安装方式分两类。在 Windows 上,建议直接去官网下载 MySQL Installer,它会帮你把服务端、命令行客户端、Workbench 图形工具一起装好,选默认配置即可。在 Linux 服务器上,我一般用系统自带的包管理工具。比如在 Ubuntu 上,执行sudo apt install mysql-server就能搞定。CentOS 上则是sudo yum install mysql-server。装完后先别急着用,有几件事必须确认。
第一件是服务是否开机自启。可以用sudo systemctl enable mysql设置开机自启,再通过sudo systemctl status mysql或者 Windows 下的services.msc去检查服务运行状态。第二件是初始密码。MySQL 8.0 在 Linux 上安装后,root 用户默认用 auth_socket 插件认证,意思是你只能用系统 root 身份登录,这一步很迷惑,很多新手会卡在密码不对。解决办法很简单,登录后改一下认证方式就行。第三件是测试连接,命令行敲mysql -u root -p,能进到mysql>提示符就说明成功。
这里要重点提醒一句:生产环境永远不要用 root 直接操作业务库。正确做法是创建一个业务专用账号,只授予它操作特定库的权限。在练习阶段,为了方便可以用 root,但心里要绷着这根弦。
2.2 配置文件里的关键参数
MySQL 装好后,主要的配置文件在 Linux 下是/etc/mysql/my.cnf(部分发行版是/etc/my.cnf),Windows 下是安装目录里的my.ini。新手刚开始不用动太多配置,但有几个参数值得了解,因为你早晚会碰上。
第一个是port,默认是 3306。如果和本地其他服务端口冲突,你就需要改端口,同时记得同步改防火墙规则。第二个是character-set-server,建议设置成utf8mb4。我之前接过一个老项目,数据库默认字符集是 latin1,结果存中文进去直接变成乱码,折腾了一下午。教训就是字符集一开始就要设置对,别等写入数据了再改。第三个是max_connections,控制最大连接数,默认是 151,如果你的应用并发高,这个值可能要调大。但要注意,连不上数据库不一定就是连接数不够,后面我会细说。
还有一个容易被忽略的是sql_mode。MySQL 8.0 默认的 sql_mode 包含ONLY_FULL_GROUP_BY,这意味着你写 GROUP BY 查询时,SELECT 的字段必须在 GROUP BY 里出现过,否则直接报错。很多从 5.7 时代过来的人会被这个坑到。如果你不想改全局配置,可以在本次会话里执行SET SESSION sql_mode = 'ALLOW_INVALID_DATES';临时调整,但这只是应急,彻底解决方案还是把 SQL 写规范。
2.3 可视化工具还是命令行?
很多人会问我推荐用哪种方式操作 MySQL。我的看法是:命令行客户端必须得会,因为线上排查问题的时候,可能只有命令行可用;但日常开发中,用可视化工具效率更高。如果你用的是 Windows,推荐装 MySQL Workbench,虽然有点重,但功能全,支持 ER 图、查询分析、数据导入导出。我自己日常用得比较多的是一款名为 DBeaver 的开源工具,跨平台、免费、支持各种数据库,界面也比较友好。
不过有一点得说清楚:可视化工具再方便,也替代不了你对 SQL 本身的理解。你迟早会需要手动写复杂的 JOIN、子查询或者存储过程,这些在图形界面里点点点是点不出来的。所以以下所有实操,我都默认你打开命令行或者任意一个工具的 SQL 编辑器窗口,跟着敲命令,这样才能形成肌肉记忆。
3. 建库建表:基础中的基础
3.1 数据库的创建、修改与删除
登录 MySQL 之后,第一个操作就是看有多少库,命令是SHOW DATABASES;。默认会有information_schema、mysql、performance_schema、sys这几个系统库,千万别去动它们。自己建库的命令很简单:
CREATE DATABASE IF NOT EXISTS shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这里我建议你把IF NOT EXISTS养成习惯,以后跑脚本不会因为重复执行而报错。DEFAULT CHARACTER SET直接指定utf8mb4,COLLATE选择utf8mb4_unicode_ci,意思是字符串排序和比较的规则用 Unicode 通用规则。字符集和排序规则决定了很多细节,比如查询时是否区分大小写、中文排序是否按拼音,新手阶段直接按我给的这套配置来,稳妥。
建好之后,用USE shop;切换到这个库。想确认当前在哪个库,用SELECT DATABASE();,这个命令在排查问题时会很实用。删除数据库是DROP DATABASE shop;,操作前务必确认你删的是哪个库。我在实际工作中看到过有人一条DROP下去,整个业务库没了,当时入职不到一个月的实习生,那个场面至今难忘。所以建议你:删库之前,先查询一下库里的表数量,做好备份,再执行删除。
3.2 表的字段设计:类型和约束怎么选
建表是整个 MySQL 基础里最见功底的部分。表字段设计得好不好,直接影响后续的查询性能和数据完整性。先看一个例子:
CREATE TABLE users ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', username VARCHAR(50) NOT NULL COMMENT '用户名', email VARCHAR(100) DEFAULT NULL COMMENT '邮箱', age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄', 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) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';这条建表语句包含了几个核心知识点。主键我用的BIGINT UNSIGNED AUTO_INCREMENT,这是最常见的自增主键方案。有人喜欢用 UUID 做主键,但在 InnoDB 引擎里,主键是聚簇索引,UUID 是随机字符串,会导致页分裂和碎片增多,查询效率不如自增整数。所以没有特殊理由,业务表首选自增主键。
username字段加了NOT NULL和唯一索引,这是因为用户名必须有且唯一。age用TINYINT UNSIGNED,因为人的年龄绝不会是负数,用无符号小整数就够存了。这里想说明一个选择字段类型的核心原则:在满足需求的前提下,用最小的存储类型。你不需要算到每一比特,但要心里有数。DATETIME存日期时间,8 字节;TIMESTAMP也是 8 字节(5.7 之后),但有 2038 年问题。业务系统里我一般用DATETIME。created_at和updated_at的默认值设置,能让插入和更新时自动维护时间,省去不少代码。
还有一个非常容易踩的坑是TEXT/BLOB字段。这类大字段不能有默认值,而且查询时会占用更多 IO。如果一张表有好几个TEXT字段,很容易造成表体积巨大,影响全表扫描性能。能用VARCHAR就不用TEXT,这个习惯越早养成越好。
3.3 表结构的修改与删除
表建好之后不是一成不变的。业务迭代中经常要加字段,命令是:
ALTER TABLE users ADD COLUMN phone VARCHAR(20) DEFAULT NULL COMMENT '手机号' AFTER email;AFTER email的意思是放在 email 字段后面,这纯粹是为了看着舒服,不影响功能。修改字段类型或属性:
ALTER TABLE users MODIFY COLUMN phone VARCHAR(30) NOT NULL COMMENT '手机号';RENAME 改名:
ALTER TABLE users RENAME COLUMN phone TO mobile;删除字段:
ALTER TABLE users DROP COLUMN mobile;DROP TABLE users;是删表,TRUNCATE TABLE users;是清空表但保留表结构。这两个命令从“能不能找回”这个角度看,几乎是不可逆操作。我的实操习惯是:在测试库随便玩,但在生产环境执行任何ALTER、DROP、TRUNCATE之前,先把库表结构和数据导出一份备份。走一遍备份,几分钟的事,但能救命的次数绝对超乎你想象。
4. 增删改查:从会用 SQL 到写出像样的 SQL
4.1 INSERT:插入数据的花式操作
增删改查(CRUD)是数据库最核心的操作,其中 INSERT 是打底基本功。最简单的单条插入:
INSERT INTO users (username, email, age) VALUES ('zhangsan', 'zs@example.com', 25);注意,主键 id 你没有写,它会自动递增。第二条语句之前,我需要强调一个细节:INSERT时最好把字段名显式列出来,而不是直接写INSERT INTO users VALUES (...)。一旦表结构发生了变化,后面的字段对不上就全乱套了。显式列字段名,代码的可读性和健壮性都会好很多。
批量插入是提高效率的关键。比如你要一次性造 100 条测试数据,一条一条插会很慢:
INSERT INTO users (username, email, age) VALUES ('zhangsan', 'zs@example.com', 25), ('lisi', 'ls@example.com', 30), ('wangwu', 'ww@example.com', 22);批量插入的执行速度比单条逐次插入快得多,因为它只解析一次 SQL。但这个 INSERT 的长度也不是越大越好,我一般在单条语句里控制在一千行以内,否则可能超过 MySQL 的 max_allowed_packet 限制,报错或者超时。
还有一个高级技巧叫INSERT ... ON DUPLICATE KEY UPDATE,可以在插入时遇到唯一键冲突就自动执行更新:
INSERT INTO users (username, email, age) VALUES ('zhangsan', 'zs_new@example.com', 26) ON DUPLICATE KEY UPDATE email = VALUES(email), age = VALUES(age);这个命令在做数据同步、去重更新时很有用,比先查再插快得多。但我建议新手不要一上来就写这种复杂语句,先把基础 INSERT 写明白,再逐步进阶。
4.2 SELECT:不仅仅是“读出来”
SELECT 是 SQL 里出现频率最高、也最考验功底的语句。很多人停留在SELECT * FROM users;这种级别,这不太够。查询优化从字段选择就开始了。
第一条原则:尽量别用SELECT *。原因有两个,一是如果表字段很多,查出来的数据量会很大,白白占用网络和内存;二是当你用代码的 ORM 映射数据时,多余字段会影响序列化和传输性能。业务代码里,只取你真正需要的字段。比如:
SELECT username, age FROM users WHERE age > 20 ORDER BY age DESC LIMIT 10;这条语句涵盖了几个最重要的子句:SELECT选字段,WHERE过滤行,ORDER BY排序,LIMIT限制条数。执行顺序从逻辑上看是FROM→WHERE→SELECT→ORDER BY→LIMIT。理解这个顺序,你才能解释为什么WHERE里不能用别名,而ORDER BY里可以。
LIKE模糊查询是新手经常玩出问题的点。比如查用户名包含“张”的人,写成WHERE username LIKE '%张%'。如果用例测试没问题,等上线数据量大之后你才会发现,前面的通配符会让索引失效,导致全表扫描。所以能用=精确查询就不用LIKE,非要用模糊匹配,也尽量写成'张%'这种前后缀可预测的模式,比如只查“张开头”的用户,这样索引可能还有机会用上。
分组统计也是日常需求。比如统计每个年龄段的用户数:
SELECT age, COUNT(*) AS cnt FROM users GROUP BY age HAVING cnt > 1;我特别想强调WHERE和HAVING的区别:WHERE在分组前过滤行,HAVING在分组后过滤组。很多初学者一开始分不清,但只要想想执行顺序就不容易混了。GROUP BY之后,SELECT 后面能出现的字段基本就只能是分组字段或聚合函数了,刚才我提到的 sql_mode 里的ONLY_FULL_GROUP_BY管的就是这件事。
JOIN 关联查询,是新手最难啃的骨头。用一个简单的例子:订单表 orders 里有 user_id,要查出每个订单的用户名,用 INNER JOIN:
SELECT o.order_no, o.amount, u.username FROM orders o INNER JOIN users u ON o.user_id = u.id;JOIN的本质是笛卡尔积的过滤,ON 条件就是过滤条件。左连接LEFT JOIN则以左表为主,右表没有匹配的行就补 NULL。初学的时候,我建议你脑子里把两张表摆开,自己“画”一遍连接的过程,比死记硬背图管用。大多数慢查询问题,根源多半是关联字段没有索引。所以写 JOIN 之前,先检查两表的关联字段是否都建了索引,这一点比任何优化手段都实在。
4.3 UPDATE 和 DELETE:手一抖就是事故
UPDATE 和 DELETE 在业务里最危险,因为一旦操作不当,影响的不是一两行,而是整张表。我曾经在一个测试环境里,一条没带 WHERE 条件的 UPDATE,直接把全表的 age 更新成了同一个值。虽然测试环境无所谓,但它让我养成了一个条件反射:写 UPDATE 和 DELETE 之前,先写明 WHERE,并且先 SELECT 一下确认影响范围。
UPDATE users SET age = 26 WHERE username = 'zhangsan';如果你想更新多行,可以用WHERE id IN (1,2,3),或者WHERE age BETWEEN 20 AND 30。删数据同理:
DELETE FROM users WHERE id = 10086;DELETE 和 UPDATE 一样,事务里可以回滚,但这也依赖你是不是开启了事务。默认情况下,MySQL 的 InnoDB 引擎在执行单条语句时会自动提交,这意味着一条DELETE下去,数据立刻生效,没有后悔的余地。想要更安全,可以手动控制事务:
START TRANSACTION; DELETE FROM users WHERE id = 10086; -- 检查一下结果,如果不对 ROLLBACK; -- 如果没问题 COMMIT;这个习惯在操作生产数据时极其重要。我做线上数据处理任务时,永远都是先 SELECT 确认目标行数,再开事务 DELETE,查一遍结果,最后才 COMMIT。这套流程看着繁琐,但出过事的人才知道它的价值。
5. 索引与查询优化基础
5.1 索引到底解决了什么问题
很多人把索引理解成书的目录,这个类比虽然粗浅,但方向是对的,只是要更精确一些。MySQL 的 InnoDB 引擎使用的 B+ 树索引,本质上是一种有序的数据结构。没有索引的时候,查询一条记录只能全表扫描,一条一条地匹配,时间复杂度是 O(N);有了索引,通过树形结构查找,能迅速定位到目标数据,数据量越大,差距越明显。
你可以做个简单试验:一张没有主键约束的千万级别大表,做一条等值查询,可能要扫几百毫秒甚至几秒;建上索引之后,同样的查询常常是个位数毫秒。索引不是优化技巧,而是关系型数据库的基本功。面试题里必问的,基本都围绕“哪些场景索引会失效”展开。
最经典的失效场景是前置通配符。索引是按照值的前缀顺序排列的,你写LIKE '%abc',没办法从前缀开始匹配,索引自然就没用了。还有一个高频错误是在索引列上用函数。比如对日期字段使用DATE(created_at) = '2025-01-01',这时候 MySQL 无法直接使用索引。正确写法是改成范围查询created_at >= '2025-01-01' AND created_at < '2025-01-02'。隐式的类型转换也会造成失效。比如索引字段是字符串varchar,你却拿数字去匹配,MySQL 会自动做类型转换,索引就用不上了。
5.2 联合索引与最左前缀原则
建索引的两个简单命令是:
CREATE INDEX idx_username ON users(username); CREATE INDEX idx_age_username ON users(age, username); DROP INDEX idx_username ON users;第二条命令创建了一个联合索引。这里的核心规则是“最左前缀原则”:联合索引 (age, username) 会先按 age 排序,age 相同的再按 username 排序。所以WHERE age = 20能用上索引,WHERE age = 20 AND username = 'zhangsan'也能用上,但如果只有WHERE username = 'zhangsan',索引就用不上了,因为 username 不是索引的最左列。
很多人的误区是:不管查询是什么,先给经常查询的字段都加上索引。这不对。索引能加速查询,但会拖慢写入,因为每次 INSERT、UPDATE、DELETE 都要同步维护索引结构。一张表如果索引太多,写性能会被严重拖累。我见过的线上事故里,有张表被加了十几个索引,结果写入延迟飙升。慎重建索引,宁缺毋滥。
查看一条查询是否走了索引,最常用的手段是用 EXPLAIN:
EXPLAIN SELECT username, age FROM users WHERE age > 20;输出的结果里,type字段是关键。如果看到ALL,说明是全表扫描,基本意味着没走索引;如果是index或者range,说明至少用上了索引的一部分;如果是const,说明是主键等值查询,性能最好。key字段会告诉你实际用的索引名,rows是预估扫描的行数。通过这几个字段,你基本能定位出一条慢查询问题出在哪。
5.3 一次慢查询的排查复盘
有一次,某项目上线后反馈一个报表页面越来越慢,一开始是 1 秒,后来变成 8 秒。我用 EXPLAIN 分析了一下查询,发现是对一张订单明细表做 GROUP BY 统计,但是type列是ALL,即全表扫描。当时这张表没有建任何统计字段的索引。解决办法也很简单:在订单明细表的 user_id 和 status 字段上建一个联合索引。索引一建立,同样的查询从 8 秒降到了 0.3 秒。
这个案例我想说明一个排查思路:遇到“慢”,不要急着改 SQL 结构,先用 EXPLAIN 看一下是否走索引、走了哪个索引、扫描了多少行。很多时候,一条索引的差异比任何 SQL 技巧都管用。当然,SQL 本身也要规范,比如避免在 WHERE 子句中对字段做表达式的运算,那种写法属于“从一开始就把索引掐死了”。
6. 常见问题与排查技巧实录
6.1 一个问题速查表
积累过程中的坑太多了,我把新手最容易遇到的几种问题整理成一张速查表:绝对能帮你省下大量翻论坛的时间。
| 问题现象 | 常见原因 | 排查思路 | 快速解决 |
|---|---|---|---|
| 登录时报 Access denied | 密码不对或认证插件不匹配 | 确认账号、密码,查看 user 表 plugin 字段 | 用 root 登录后重置密码,或改用 mysql_native_password |
| 中文乱码 | 客户端、连接、表、库字符集不一致 | 依次检查 server、database、table、connection 字符集 | 建库建表统一 utf8mb4;连接参数加 characterEncoding=utf8 |
| 端口 3306 被占用 | 本机其他进程占用 | netstat -ano查看占用进程 | 修改 MySQL 端口或停掉占用进程 |
| Too many connections | 连接数超过 max_connections | SHOW VARIABLES LIKE 'max_connections';查当前设置 | 临时调大连接数,排查应用是否存在连接池泄露 |
| 查询特别慢 | 没走索引 / 大表全扫 | 执行 EXPLAIN 看 type、rows | 优化索引、优化 SQL 写法 |
ERROR 1175在 UPDATE/DELETE 时 | 安全模式要求带 WHERE | 确认是否在安全更新模式下 | 写清楚 WHERE 条件,不要盲目关掉安全模式 |
| 表数据占空间很大 | 历史数据堆积、大字段太多 | 查看表大小information_schema | 清理归档旧数据,评估字段是否需要瘦身 |
这张表想表达的核心观念是:排查问题不是靠猜,而是靠一步步确认。我遇到问题时的顺序永远是:先看错误日志 → 再查配置文件 → 然后用命令行手工验证 → 最后才去查资料。新手容易反过来,一报错就复制粘贴到搜索引擎,结果越查越晕。
6.2 忘记密码怎么办
忘记 root 密码,应该是所有新手都经历过的坎。MySQL 8.0 的处理思路和旧版略有不同,但核心原理一样:跳过授权表的验证,重启服务再修改密码。
在 Linux 下,先编辑配置文件,在[mysqld]段加上一句skip-grant-tables,然后重启 MySQL。此时你执行mysql -u root不需要密码就能直接进来,然后执行FLUSH PRIVILEGES;,再执行ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';。改完密码之后,一定要记得删掉配置文件里skip-grant-tables这一行,再重启服务。如果你忘了删就直接重启,MySQL 会保持无密码登录状态,这是一个非常大的安全隐患。我在实操中遇到过有人把这事忘了,结果整台服务器被扫了,教训极其深刻。
Windows 下的思路一样,只是改配置文件的位置不同。我这里特别提醒:skip-grant-tables只是应急方案,不是日常配置。平时千万别为了省事长期开着它。
6.3 数据备份与恢复:基本功里的保命技能
最后一个基础能力是备份。MySQL 最常用的逻辑备份工具是mysqldump。最基础的全量备份命令是:
mysqldump -u root -p shop > shop_backup_2026_01_01.sql恢复也很简单:
mysql -u root -p shop < shop_backup_2026_01_01.sql这条命令是把你导出的 SQL 脚本重新执行一遍。实际操作中,我一般会给 mysqldump 加上--single-transaction参数。这个参数的作用是在导出过程中不锁表,保证线上业务能继续写入,而导出的数据是一致性快照。不加这个参数时,InnoDB 表默认可能锁表或者导出的数据不一致,这在线上环境是不可接受的。
数据恢复还有个细节:导入之前要确认目标库存在。如果shop库不存在,导入会报错。所以恢复流程应该是:先建库CREATE DATABASE shop;,然后USE shop;,再执行导入。备份这件事,你练得越勤,真出事的时候越不慌。我有一次帮同事恢复误删的数据,就是靠一个每天凌晨自动跑的 mysqldump 定时脚本,整个过程 20 分钟搞定,同事眼睛都直了。
定时备份我建议大家从第一天就养成习惯。在 Linux 下可以直接用 crontab 配置一个每日任务:
0 2 * * * mysqldump -u root -p123456 shop > /backup/shop_$(date +\%F).sql但要注意,密码写在命令行里是不安全的,生产环境建议用--defaults-extra-file把密码写在配置文件里,并设置文件权限为 600。这些都是细节,但安全就是靠细节堆起来的。
优化收藏这一步也很重要。有时候你会觉得自己的 SQL 写得没问题,还是一直卡,那大概率是表结构或者索引设计的问题。这种时候别再纠结 SQL,回去看建表语句、看字段类型、看查询频率,甚至重新梳理业务逻辑,比硬写一条“神仙 SQL”强得多。MySQL 基础不深奥,但每一层都需要你亲手敲一遍 SQL,才能真正变成自己的东西。遇到一个报错就记一个坑,时间长了,你就是别人眼里的“MySQL 老司机”。