MySQL从安装到精通:避坑指南与核心概念全解析
1. 从“安装即放弃”到“丝滑上手”:一个老DBA的MySQL避坑心法
我见过太多新手,兴致勃勃地下载了MySQL,结果在安装配置的第一步就卡壳,要么服务起不来,要么连不上,最后只能无奈放弃,转头去找那些一键安装的“全家桶”。但说实话,那些封装好的工具虽然省事,却也让你错过了理解数据库运行环境的最佳时机。今天,我就以一个踩过无数坑的“老炮儿”身份,带你从零开始,把MySQL的安装、配置到核心概念,掰开揉碎了讲清楚。这不是一份冷冰冰的官方文档翻译,而是我十多年运维和开发工作中,那些手册里不会写、但关键时刻能救命的实战经验。无论你是想转行做后端开发、数据分析,还是运维工程师,搞定MySQL都是你的必修课。收藏这篇,下次遇到问题,你很可能直接在这里找到答案。
2. 安装不是点“下一步”:Windows与Linux下的抉择与精校
很多人觉得安装数据库就是一路“Next”,但魔鬼藏在细节里。不同的操作系统、不同的安装方式,直接决定了后续使用的稳定性和便利性。
2.1 Windows平台:MSI安装包与ZIP解压版的终极对比
在Windows上,你主要会面临两个选择:官方的MSI安装包和ZIP压缩包(解压版)。
MSI安装包:这是最“傻瓜式”的方式。运行安装程序,它会帮你完成所有事情:安装MySQL Server、配置Windows服务、甚至提供一个图形化的配置向导。对于绝大多数只想快速用起来的初学者,我推荐这个方式。但是,它有个“坑”:默认的安装路径可能比较深(如C:\Program Files\MySQL\...),并且对安装目录的权限控制比较严格,有时手动修改配置文件会遇到权限问题。
ZIP解压版:这才是高手和追求灵活性的开发者的选择。你下载的是一个压缩包,解压到任意目录(比如D:\mysql-8.0.33)即可。这种方式完全由你掌控,但所有事情都需要手动完成。你需要:
- 手动创建配置文件
my.ini。 - 用命令行初始化数据目录(
mysqld --initialize-insecure或--initialize)。 - 手动安装Windows服务(
mysqld --install MySQL)。 - 手动启动服务(
net start MySQL)。
注意:网上很多教程会教你用
mysqld -install,但在MySQL 8.0中,更推荐使用mysqld --install [服务名]的格式。如果启动服务时提示“服务没有报告任何错误”,这通常意味着MySQL的日志文件(通常是数据目录下的.err文件)里有真正的错误信息,比如端口被占用、配置文件有语法错误、或者缺少必要的VC++运行库。务必去查看错误日志!这是排查问题的第一步,也是最重要的一步。
我个人的习惯是,在开发机上使用ZIP解压版,因为我可以把它放在非系统盘,重装系统也不怕,并且方便同时管理多个版本的MySQL。而在生产环境的Windows服务器上,为了省心,我会使用MSI安装包。
2.2 Linux平台:包管理器与离线Tarball的生存指南
在Linux世界,选择更多,也更能体现你的功底。
使用包管理器(Yum/Dnf/Apt):在CentOS/RHEL或Ubuntu/Debian上,通过系统包管理器安装是最快捷的。例如在CentOS 7上,你可以添加MySQL官方仓库后,直接yum install mysql-community-server。好处是依赖自动解决,服务管理集成(systemctl)。但缺点是你安装的版本受仓库限制,且文件布局遵循Linux的FHS标准(配置文件在/etc/my.cnf,数据在/var/lib/mysql),对于深度定制不太友好。
使用离线Tarball安装:这是最纯粹、最可控的方式,尤其适用于没有外网的生产环境。你需要下载对应版本的.tar.xz压缩包,解压到如/usr/local/mysql目录。接下来的步骤和Windows的ZIP版类似:创建用户组、修改目录权限、初始化数据目录、编辑配置文件。这种方式步骤繁琐,但你能100%掌控MySQL的每一个文件放在哪里。对于“centos 7 安装 mysql 5.7.44离线包”这类需求,这就是唯一解。
关于国内镜像:从MySQL官网下载速度可能很慢。国内一些高校和云厂商提供了镜像源,可以显著提升下载速度。在下载时,可以搜索“MySQL国内镜像下载”来找到可用的源,但务必从可信的镜像站下载,核对文件MD5或SHA256校验和,确保文件未被篡改。
2.3 核心配置初探:my.cnf/my.ini里的大学问
安装完成后,无论哪种方式,你都会面对一个核心配置文件:Linux上是/etc/my.cnf或/etc/mysql/my.cnf,Windows上是my.ini。很多初级问题都源于这里配置不当。
几个你必须了解的基础配置项:
[mysqld]:这是服务器配置段,大部分设置在这里。port = 3306:监听端口。如果端口冲突,就在这里改。datadir = /var/lib/mysql:数据目录。所有数据库文件、表数据、日志都存在这里。这个目录的权限必须正确,通常要求属于mysql用户(Linux)或具有完全控制权(Windows)。socket = /tmp/mysql.sock(Linux):本地连接使用的套接字文件。character-set-server = utf8mb4:设置默认字符集。强烈建议使用utf8mb4而不是utf8,因为utf8mb4才是真正的UTF-8,支持所有emoji和生僻字。default-storage-engine = InnoDB:默认存储引擎。除非有特殊理由,否则永远用InnoDB。
一个常见的启动错误“The MySQL server has a timezone offset (0 seconds ahead of UTC) which does n...”通常与系统时区设置有关。你可以在配置文件中设置default-time-zone = '+8:00'(东八区),或者在启动后执行SET GLOBAL time_zone = '+8:00';来解决。
3. 连接与操作入门:告别图形界面依赖
安装配置好后,我们得连上去操作。很多人一上来就找图形化工具,如MySQL Workbench、DBeaver、Navicat。工具固然方便,但作为一名合格的开发者或DBA,你必须熟练掌握命令行客户端mysql,这是理解MySQL、进行故障排查和编写自动化脚本的基础。
3.1 命令行客户端:你的瑞士军刀
在终端或CMD中,使用以下命令连接:
mysql -h 主机名 -P 端口 -u 用户名 -p例如:mysql -h 127.0.0.1 -P 3306 -u root -p,然后输入密码。
连接成功后,你会看到mysql>提示符。这里就是你的战场。让我们完成几个最核心的操作:
1. 数据库级操作:
-- 查看所有数据库 SHOW DATABASES; -- 创建数据库,并指定字符集和排序规则 CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用(切换)到某个数据库 USE mydb; -- 删除数据库(谨慎!) -- DROP DATABASE mydb;2. 表级操作:假设我们要创建一个学生表,这就是“学生课程成绩信息实体表设计mysql”的简单实现。
CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, -- 主键,自增 student_no VARCHAR(20) UNIQUE NOT NULL, -- 学号,唯一且非空 name VARCHAR(50) NOT NULL, -- 姓名 gender CHAR(1), -- 性别 enrollment_date DATE -- 入学日期 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生信息表';这里用到了几个关键概念:PRIMARY KEY(主键)、AUTO_INCREMENT(自增)、UNIQUE(唯一约束)、NOT NULL(非空约束)、ENGINE(存储引擎)、COMMENT(注释)。好的表设计从清晰的字段和约束开始。
3. 经典的增删改查(CRUD):
-- 增(Insert) INSERT INTO student (student_no, name, gender, enrollment_date) VALUES ('2023001', '张三', 'M', '2023-09-01'), ('2023002', '李四', 'F', '2023-09-01'); -- 查(Select) SELECT * FROM student; -- 查询所有字段 SELECT id, name FROM student WHERE gender = 'M'; -- 条件查询 SELECT name, enrollment_date FROM student ORDER BY enrollment_date DESC; -- 排序 -- 改(Update) UPDATE student SET name = '王五' WHERE student_no = '2023001'; -- 删(Delete) DELETE FROM student WHERE id = 2;SELECT语句是SQL的灵魂,后面我们会深入讲。
3.2 图形化工具:效率加速器
命令行强大,但图形化工具在数据浏览、可视化建模、导入导出时效率更高。
- MySQL Workbench:MySQL官方工具,功能全面,尤其擅长ER图设计和数据库迁移。对于“mysql workbench使用教程”,核心就是学会用它的“Migration Wizard”进行数据迁移,以及用“Modeling”功能进行数据库设计。
- DBeaver:一个免费开源的通用数据库工具,支持MySQL、PostgreSQL、Oracle等几十种数据库。界面友好,功能强大,社区版完全够用。配置“dbeaver mysql驱动”很简单,通常它会自动下载,如果网络有问题,需要手动指定JDBC驱动jar包的位置。
- Navicat:商业软件,体验非常好,但需要付费。
我的建议是:日常简单查询和紧急故障排查用命令行;进行复杂的表结构设计、数据对比或大量数据浏览时,使用图形化工具。
4. SQL核心语法深潜:从“会用”到“精通”
掌握了基本操作,我们进入核心区。SQL语法是操作数据库的桥梁,理解深度直接决定你的效率。
4.1 查询的艺术:SELECT及其伙伴们
SELECT语句远不止SELECT *。
- 去重:DISTINCT
SELECT DISTINCT department FROM employees;可以去除重复的部门名。有人问“mysql的or能去重吗?”,OR是逻辑运算符,用于连接条件(如WHERE age > 30 OR salary < 5000),不能用于去重。去重是DISTINCT或GROUP BY的工作。 - 聚合函数:COUNT, SUM, AVG, MAX, MIN
SELECT COUNT(*) AS total_students, -- 总学生数 AVG(score) AS average_score, -- 平均分 MAX(score) AS top_score -- 最高分 FROM exam_results; - 分组与过滤:GROUP BY 和 HAVING
GROUP BY用于将数据分组,HAVING则是对分组后的结果进行过滤,类似于WHERE,但作用对象不同。-- 查询每个班级的平均分,且只显示平均分大于80的班级 SELECT class_id, AVG(score) AS avg_score FROM exam_results GROUP BY class_id HAVING avg_score > 80; - 排序:ORDER BY
ORDER BY score DESC按分数降序排。ORDER BY column1 ASC, column2 DESC先按column1升序,再按column2降序。
4.2 联表查询:JOIN的四种舞步
当需要从多个表组合数据时,JOIN就上场了。
- INNER JOIN(内连接):只返回两个表中匹配的行。是最常用的连接。
SELECT s.name, c.course_name, sc.score FROM student s INNER JOIN score sc ON s.id = sc.student_id INNER JOIN course c ON sc.course_id = c.id; - LEFT JOIN(左连接):返回左表所有行,即使右表没有匹配。右表无匹配则为NULL。
-- 查询所有学生及其选课成绩(没选课的学生成绩显示为NULL) SELECT s.name, sc.score FROM student s LEFT JOIN score sc ON s.id = sc.student_id; - RIGHT JOIN(右连接):与左连接相反,返回右表所有行。
- FULL OUTER JOIN(全外连接):MySQL不直接支持,但可以通过
LEFT JOIN和RIGHT JOIN的UNION模拟。返回左右两表的所有行。
4.3 子查询与常用函数
子查询是把一个查询的结果作为另一个查询的条件或数据源。
-- 查询比平均工资高的员工 SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);常用函数:
- 字符串函数:
CONCAT(),SUBSTRING(),LENGTH(),UPPER(),LOWER(),TRIM()。 - 日期函数:
NOW(),CURDATE(),DATE_ADD(),DATEDIFF(),DATE_FORMAT()。SELECT name, DATE_FORMAT(enrollment_date, '%Y年%m月%d日') AS fmt_date FROM student; - 条件函数:
CASE WHEN ... THEN ... ELSE ... END, 非常强大的流控制函数,可以实现行级的数据转换。SELECT name, score, CASE WHEN score >= 90 THEN '优秀' WHEN score >= 60 THEN '及格' ELSE '不及格' END AS grade_level FROM exam_results; - 窗口函数(MySQL 8.0+):这是高级功能,可以在不减少行数的情况下进行聚合计算,如
ROW_NUMBER(),RANK(),SUM(...) OVER(...)。对于“mysql 行转列”这类复杂需求,在MySQL 8.0之前通常用CASE WHEN或GROUP_CONCAT模拟,而8.0之后可以使用ROW_NUMBER()配合条件聚合更优雅地实现。
5. 进阶特性与性能基石:存储引擎、索引与事务
如果你只想做基础操作,前面就够了。但要想深入,必须理解存储引擎、索引和事务,这是MySQL性能与可靠性的核心。
5.1 存储引擎:InnoDB为何是绝对王者
存储引擎决定了数据如何存储、索引如何组织、事务是否支持等底层特性。MySQL是插件式存储引擎架构。
- MyISAM:古老,不支持事务和外键,表级锁。在只读或读多写极少的历史场景可能有用,现在99%的情况你应该使用InnoDB。
- InnoDB:默认且推荐的存储引擎。支持事务(ACID)、行级锁(高并发下性能好)、外键约束。它的表结构(
.frm文件,8.0后并入系统表空间)和数据索引都存储在表空间(ibdata文件或独立的.ibd文件)中。 - Memory:数据全放在内存,速度快,但服务重启数据丢失。可用于临时表或缓存。
创建表时指定引擎:CREATE TABLE ... ENGINE=InnoDB;。修改现有表引擎:ALTER TABLE table_name ENGINE=InnoDB;,但这会重建表,大表操作需谨慎。
5.2 索引:让查询飞起来的关键
没有索引,SELECT就是全表扫描(Full Table Scan),数据量一大就慢如蜗牛。索引就像书的目录。
索引类型:
- PRIMARY KEY(主键索引):唯一且非空,一张表只有一个。InnoDB中,表数据就是按主键顺序组织的(聚簇索引)。
- UNIQUE KEY(唯一索引):保证列值唯一,允许NULL。
- INDEX / KEY(普通索引):最基本的索引,仅用于加速查询。
- FULLTEXT(全文索引):用于全文搜索,针对文本内容。
- 复合索引:在多个列上建立的索引,如
INDEX idx_name_age (name, age)。复合索引有最左前缀原则:查询条件必须包含索引最左边的列,才能利用该索引。例如,idx_name_age索引对WHERE name='张三'和WHERE name='张三' AND age=20有效,但对WHERE age=20无效。
创建与管理索引:
-- 创建表时指定 CREATE TABLE user ( id INT PRIMARY KEY, email VARCHAR(100), UNIQUE KEY uk_email (email), -- 唯一索引 INDEX idx_name (name) -- 普通索引 ); -- 为已存在表添加索引 CREATE INDEX idx_created_at ON orders(created_at); ALTER TABLE orders ADD INDEX idx_status (status); -- 删除索引 DROP INDEX idx_name ON user;索引使用技巧与避坑:
- 不要过度索引:索引会降低写操作(INSERT/UPDATE/DELETE)速度,因为数据变更时需要维护索引。只为经常出现在
WHERE、ORDER BY、JOIN条件中的列创建索引。 - 区分度高的列适合建索引:像“性别”这种只有两三种值的列,建索引效果微乎其微。
- 使用EXPLAIN分析查询:在SELECT语句前加上
EXPLAIN,可以查看MySQL的执行计划,这是优化查询的神器。看type列(访问类型,从好到坏:system > const > eq_ref > ref > range > index > ALL),key列(实际使用的索引),rows列(预估扫描行数)。 - 避免索引失效:对索引列进行函数操作(如
WHERE YEAR(create_time)=2023)、类型转换、使用!=或<>、OR连接非索引列条件,都可能导致索引失效。
- 不要过度索引:索引会降低写操作(INSERT/UPDATE/DELETE)速度,因为数据变更时需要维护索引。只为经常出现在
5.3 事务与锁:数据安全的守护神
事务是一组不可分割的SQL操作,要么全部成功,要么全部失败。通过BEGIN或START TRANSACTION开始,COMMIT提交,ROLLBACK回滚。
事务的ACID特性:
- 原子性(Atomicity):事务内的操作是一个整体。
- 一致性(Consistency):事务使数据库从一个一致状态变为另一个一致状态。
- 隔离性(Isolation):并发事务之间相互隔离。这引出了事务隔离级别(READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE)。MySQL InnoDB默认是REPEATABLE READ(可重复读),通过MVCC(多版本并发控制)实现,能在很大程度上避免幻读。
- 持久性(Durability):事务提交后,修改永久保存。
锁是管理并发访问的机制。InnoDB实现了行级锁,大大提高了并发性能。但使用不当会导致“mysql锁表”,即死锁或长时间锁等待。
- 共享锁(S锁):
SELECT ... LOCK IN SHARE MODE。允许其他事务读,但不允许写。 - 排他锁(X锁):
SELECT ... FOR UPDATE。不允许其他事务读和写。
常见的“mysql锁面试题”会考察如何避免死锁:保持一致的访问顺序(例如,总是先更新A表再更新B表)、尽量使用索引减少锁定的范围、在事务中尽快提交以减少锁持有时间。
6. 高级对象与运维管理
当基础夯实后,你会接触到一些更高级的数据库对象和运维任务。
6.1 存储过程、函数与触发器
这些是存储在数据库服务器端的一组SQL语句,可以被应用程序调用。
存储过程:封装复杂的业务逻辑,通过
CALL调用。它可以有输入输出参数。DELIMITER // -- 修改分隔符,因为过程体内有分号 CREATE PROCEDURE GetStudentCount(IN classId INT, OUT total INT) BEGIN SELECT COUNT(*) INTO total FROM student WHERE class_id = classId; END // DELIMITER ; -- 调用 CALL GetStudentCount(1, @count); SELECT @count;注意“mysql中触发器中分隔符”这个问题:在定义存储过程、函数或触发器时,因为其主体包含多条以分号结尾的SQL语句,我们需要先用
DELIMITER命令临时修改语句分隔符(如改为//),定义结束后再改回分号。函数:与存储过程类似,但必须有返回值,且可以在SQL语句中直接使用,如
SELECT MyFunction(column) FROM table;。触发器:在表发生INSERT、UPDATE、DELETE事件时自动执行的一段代码。常用于审计、数据一致性校验(如复杂的业务约束)。
CREATE TRIGGER before_employee_update BEFORE UPDATE ON employees FOR EACH ROW BEGIN IF NEW.salary < OLD.salary THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Salary cannot be decreased!'; END IF; END;触发器要慎用,因为它隐蔽在数据库里,逻辑复杂后难以调试,且会增加性能开销。
6.2 备份与恢复:数据生命的保险绳
“mysql全库备份与恢复命令”是DBA的保命技能。备份分为逻辑备份和物理备份。
逻辑备份(mysqldump):将数据库结构和数据导出为SQL语句。最常用,可移植性强,适合中小型数据库。
# 备份单个数据库 mysqldump -u root -p --databases mydb > mydb_backup.sql # 备份所有数据库 mysqldump -u root -p --all-databases > all_backup.sql # 带事务一致性备份(推荐) mysqldump -u root -p --single-transaction --routines --triggers --databases mydb > mydb_backup.sql--single-transaction:在事务中执行,确保备份的一致性(针对InnoDB)。--routines:包含存储过程和函数。--triggers:包含触发器。
恢复逻辑备份:
mysql -u root -p < all_backup.sql或者先连接MySQL,然后
source all_backup.sql;。物理备份:直接拷贝数据文件(
datadir)。速度更快,适合超大数据库,但恢复时要求MySQL版本和配置与原环境高度一致。常用工具有Percona XtraBackup(开源热备工具)。
6.3 用户、权限与连接池
用户与权限管理:永远不要用root账户进行应用连接。应该为每个应用创建专属用户,并授予最小必要权限。
CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPassword123!'; -- 创建用户,'%'允许从任何主机连接 GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'%'; -- 授予特定数据库的增删改查权限 FLUSH PRIVILEGES; -- 刷新权限 SHOW GRANTS FOR 'app_user'@'%'; -- 查看用户权限数据库连接池:在Java等应用中,直接频繁创建和关闭数据库连接开销巨大。“mysql的数据库连接池”如HikariCP、Druid等,负责管理一批预先建立的连接,应用需要时从池中获取,用完后归还,极大地提升了性能。配置连接池时,关键参数包括初始连接数、最大连接数、最小空闲连接、连接超时时间等,需要根据应用负载进行调整。
7. 实战排坑与性能调优思维
最后,我们聊聊那些真正让人头疼的问题和调优思路。很多问题搜索出来都是一两句话的答案,但背后的原理和排查过程才是精华。
问题1:“MySQL服务无法启动。服务没有报告任何错误。”这是最经典的Windows平台问题。服务管理器提示模糊,真正的错误在日志里。你需要:
- 找到MySQL的错误日志文件。通常在数据目录(
datadir)下,文件名类似主机名.err。 - 打开它,查看最后的错误信息。常见原因有:端口3306被占用;配置文件
my.ini中有语法错误(比如缺少一个括号);basedir或datadir路径配置错误;或者缺少必要的运行库(如Microsoft Visual C++ Redistributable)。
问题2:关于“mysql自动忽略大小写?”这由系统变量lower_case_table_names控制。在Linux/Unix系统上,默认值为0,表示表名大小写敏感(MyTable和mytable是两个不同的表)。在Windows上,默认值为1,表示表名在存储和查找时都会被转换为小写,即大小写不敏感。这个参数在初始化数据库(mysqld --initialize)时就必须确定,后期更改需要重建数据文件,非常麻烦。建议在跨平台开发时,统一约定使用小写表名,避免问题。
问题3:数据迁移——“windows服务器怎么讲oracle数据库表结构及表数据迁移到mysql上”这是一个典型的异构数据库迁移。没有一键完美工具,思路如下:
- 导出Oracle元数据:使用Oracle的工具或第三方工具,将表结构(DDL)导出。注意数据类型转换(如Oracle的
NUMBER转MySQL的DECIMAL或INT,DATE转DATETIME等)。 - 转换DDL:将导出的Oracle DDL语句手动或通过脚本(如Python)转换为MySQL兼容的DDL。需要处理自增、注释、索引、约束等差异。
- 在MySQL中创建表。
- 导出Oracle数据:使用
expdp(数据泵)或sqlplusspool导出为CSV或文本文件。 - 导入MySQL数据:使用MySQL的
LOAD DATA INFILE或mysqlimport命令,速度最快。也可以使用ETL工具(如Kettle)或编写自定义脚本。
问题4:性能突然下降,如何排查?这是一个系统工程,不是单一答案。可以遵循以下思路:
- 检查当前状态:运行
SHOW PROCESSLIST;查看当前所有连接正在执行的SQL,有没有慢查询或锁等待。 - 监控慢查询:确保已开启慢查询日志(
slow_query_log = ON),并设置合理的long_query_time(如2秒)。定期分析慢日志,找出最耗时的SQL。 - 分析单条慢SQL:对找到的慢SQL,使用
EXPLAIN或EXPLAIN FORMAT=JSON详细分析其执行计划。关注是否全表扫描(type=ALL)、是否使用了合适的索引(key列)、扫描行数是否过多(rows列)。 - 检查系统资源:使用
top、vmstat、iostat等命令,查看服务器CPU、内存、磁盘I/O是否达到瓶颈。特别是磁盘I/O,数据库是I/O密集型应用。 - 检查InnoDB状态:运行
SHOW ENGINE INNODB STATUS\G,查看SEMAPHORES(信号量,反映锁竞争情况)、LATEST DETECTED DEADLOCK(最近死锁信息)等。
问题5:关于“mysql proxysql orchestra 高可用”这是一个高可用(HA)架构话题。MySQL本身的主从复制(Replication)是基础。ProxySQL是一个高性能的MySQL中间件,可以实现读写分离、连接池、故障转移、查询路由等。Orchestrator(现在常指github.com/openark/orchestrator)是一个MySQL复制拓扑管理工具,能可视化拓扑、自动故障转移。它们组合可以构建一个自动化的高可用集群:通常由Orchestrator监控主库健康,一旦主库故障,自动选举并提升一个从库为新主库,然后通知ProxySQL更新后端服务器配置,将写流量指向新主库。这套方案比传统的MHA等更灵活和自动化。
学习MySQL,动手实践远比只看文档重要。我建议你按照这个教程,从安装开始,亲手创建数据库、表,插入数据,执行复杂的查询,尝试建立索引并观察执行计划的变化,模拟一个事务场景。遇到错误不要慌,仔细阅读错误信息,善用搜索引擎(但要学会甄别过时信息),最重要的是养成查看官方文档(dev.mysql.com/doc)的习惯。这条路没有捷径,每一个坑踩过去,你的功底就扎实一分。