ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

MySQL 8.0学习笔记:从安装到索引、锁与事务调优全记录

MySQL 8.0学习笔记:从安装到索引、锁与事务调优全记录 记录一下2026年3月16日上午的MySQL学习过程。主要围绕安装、基础操作、索引、锁与事务、存储过程、常见报错排查这几个方面展开。上午的MySQL学习是因为近期想把手头的一个旧项目从5.7迁移到8.0加上团队里好几个新同事对InnoDB锁和事务隔离级别理解得比较模糊就索性把从安装到调优的链路重新过了一遍。这篇笔记适合MySQL初学者做系统性梳理也适合有几年经验但没时间深抠底层原理的开发或DBA快速查漏补缺。说实话MySQL相关的资料网上到处都是但能真正做到“从装到用从用到调优每个坑都有现场记录”的内容不多。我今天尽量把上午遇到的所有坑、疑点、细节判断都写下来还原真实操作过程。1. 版本、安装与环境准备这次选型背后的考量1.1 版本怎么选5.7.44、8.0还是8.4 LTS先聊一个很多人在下载页面前纠结很久的问题到底装哪个版本我之前习惯用5.7因为业务代码相对老旧很多生成SQL的组件没有针对8.0做兼容测试。上午特别去官网确认了一下5.7在2023年10月左右停止社区版支持5.7.44是5.7系列的最后一个版本。所以现在新项目还用5.7除非是存量迁移需要保持版本一致否则我不建议再选。8.0延续的是创新版本路线功能更新快像窗口函数、公共表表达式CTE、不可见索引、直方图等特性都在8.0里很成熟。8.4是LTS版本意味着更长的官方维护周期对追求稳定、不频繁升大版本的生产环境更友好。我最终选择8.0.44上午最新的8.0小版本之一原因有两点第一8.0的生态资料最多踩坑时搜索成本最低第二同事们的开发环境基本都在8.0.x统一版本可以减少“本地能跑、测试环境挂了”的尴尬。8.4虽然适合长期维护但部分老工具和监控脚本需要额外适配在没有明确LTS诉求的前提下先用8.0。1.2 Linux上用rpm还是源码包我选了rpm我的主力环境是Linux服务器CentOS 7.9兼容环境安装方式大概有三种rpm包安装、二进制tar包解压、源码编译。源码编译我不是特别推荐除非要定制特殊功能或者想在低配机器上极限优化性能参数。对于大多数情况rpm或tar包足够。rpm安装最大的好处是自动注册systemd服务会创建mysql用户、初始化数据目录配合yum localinstall还能自动解析一些依赖。具体步骤# 1. 下载rpm包。注意要包含server和client不能只装server。 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-server-8.0.44-1.el7.x86_64.rpm wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-client-8.0.44-1.el7.x86_64.rpm # 2. 安装如果已存在老版本会冲突先检查 rpm -qa | grep mysql yum localinstall -y mysql-community-*.rpm # 3. 初始化 mysqld --initialize-insecure # 4. 启动 systemctl start mysqld这里有个细节--initialize会在日志里生成一个临时root密码而--initialize-insecure会直接生成一个无密码的root账号。测试环境用--initialize-insecure更方便生产环境必须用--initialize并马上改密。rpm方式安装后配置文件默认在/etc/my.cnf数据目录在/var/lib/mysql日志在中/var/log/mysqld.log。如果你更习惯二进制tar包方式比如MySQL 8.0.44的tar包下载后解压到/usr/local/mysql然后手动创建mysql用户、初始化数据目录、配置/etc/my.cnf再用mysqld_safe启动。这种方式灵活性高很多运维脚本喜欢用但新手容易漏掉权限配置导致服务起不来。我用rpm装的另一个原因是团队里新同事对Linux不熟rpm方式出问题的概率小。1.3 Windows 10上的安装exe安装包与zip解压的区别Windows上则完全是另一套逻辑。如果只是本地开发我推荐直接下载MySQL Installer的exe版本图形界面勾选MySQL Server、MySQL Workbench、ODBC驱动等组件一路Next就行。上午帮同事处理了一个Windows 10下安装8.0.44的案例他下载的是zip版结果没有my.ini、没有服务注册启动全靠手动非常容易踩坑。zip解压版其实也很简单适合想完全控制安装路径的开发者前提是配置文件必须自己写。下面这个my.ini是经过实测可用的最小配置[mysqld] basedirD:/mysql-8.0.44-winx64 datadirD:/mysql-8.0.44-winx64/data port3306 character-set-serverutf8mb4 # 8.0默认是caching_sha2_password老客户端会连接不上 default-authentication-pluginmysql_native_password [client] port3306 default-character-setutf8mb4配置完成后:: 以管理员身份打开cmd cd D:\mysql-8.0.44-winx64\bin mysqld --initialize-insecure mysqld -install net start mysqlmysqld --install是把MySQL注册为Windows服务之后开机自启。有些教程说mysqld --install之后再net start mysql会报“服务无法启动”我遇到了两次基本是data目录没初始化或者my.ini里的路径有斜杠问题。Windows下路径建议用正斜杠或者双反斜杠特别是8.0版本路径解析更严格。1.4 Docker部署镜像拉取失败和数据卷权限问题Docker部署MySQL其实比物理机更省心但上午卡了两个点一个是用Docker Desktop拉镜像时老是报failed to decode referrers index: invalid这个报错的本质是镜像仓库返回的元数据不兼容通常是Docker引擎版本太旧或者镜像源同步出现问题。我是先把Docker Desktop升级到最新版本然后把镜像源切回官方源再执行docker pull mysql:8.0.44就成功了。另一个是数据卷权限问题。比如这样启动docker run -d --name mysql8 \ -p 3306:3306 \ -v /data/mysql:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORDroot123 \ mysql:8.0.44如果宿主机的/data/mysql目录没有给mysql用户uid 999写权限容器起不来日志里会看到chown: operation not permitted类似信息。我踩过之后习惯先创建目录并给权限mkdir -p /data/mysql chown -R 999:999 /data/mysql如果是Arm架构机器或者需要在离线环境装arm版镜像尽量用mysql:8.0.44-oraclelinux8这类多架构镜像或者直接下载对应架构的tar包做本地导入不要用默认latest标签latest的架构和注册表索引偶尔会有兼容问题。2. 库里那些容易记混的基础操作排序、去重、update与结构变更2.1 排序不止是order by那么简单上午复习排序时发现一个重点MySQL排序不仅受order by影响还受字符集排序规则collation影响。比如utf8mb4_general_ci和utf8mb4_unicode_ci对不同语言字符的排序结果不完全一样。更隐蔽的问题是order by与索引方向的一致性如果查询条件是where a1 order by b而索引是(a,b)那排序可以直接用索引如果是order by b desc而索引默认是asc就需要额外的filesort。有人问MySQL排序有没有默认规则如果不指定order by查询结果顺序是不保证的。同一条SQL有时候稳定有时候不稳定跟执行计划、并行度、存储引擎都有关系。我一般会明确写order by包括分页查询否则LIMIT取出的数据可能不符合预期。另外order bylimit可以直接利用索引做优化比如select * from t order by id limit 10这在大分页场景下比limit 100000, 10快一个量级。真遇到深分页就换成“先定位上一页最后一条id再用where id ? order by id limit 10”的方式。2.2 去重和or一个容易被误解的组合MySQL的去重有两个关键词distinct和group by。distinct是整行去重它的语义是把所有查询列放在一起所有列完全一样才算重复如果只对单列去重但查询里还有别的列distinct就会失效。or能不能去重当然不能or只是条件组合。网上有人问“MySQL的or能去重吗”其实是把“去重”和“条件筛选”搞混了。要按状态过滤where status1 or status2没问题要去重就用select distinct status或group by status。很多人or查询变慢是因为两个条件字段没走同一个索引或者其中一个字段没有索引。MySQL 8.0有index merge优化where a1 or b2在a、b分别有索引时可以合并但这个优化在复杂条件下常常不如union all来得稳定。建议能用in就用inwhere a in (1, 2)比or的优化要稳定得多如果or的两边来自不同表直接拆成union all去重就有union。2.3 update误操作没有后悔药的现场上午特别练习了一下update的还原思路。MySQL默认开autocommit1这意味着每条update语句自动提交。如果没开事务就执行了update t set status2 where id1然后发现有条件写错了或者忘了where数据已经被改掉没法像Oracle那样闪回查询。一种常见的补救方式是依赖binlog做时间点恢复。前提是开启了binlog且设置binlog_formatROW。恢复思路先把出错的binlog解析成SQL找出那一条update对应的前镜像before image然后反向update回去。比如mysqlbinlog --base64-outputdecode-rows -vv /var/lib/mysql/binlog.000012解析出来的内容里能看到### UPDATE t ### WHERE id1 ### SET status01这种记录。手工生成还原SQL的过程很痛苦所以我建议实际的操作方法是在应用层做兜底把需要更新的主键和旧值先查出来在一个事务里更新同时把变更记录写入另一个表。更简单的习惯是update语句先加where再检查一下影响行数甚至可以先select一遍再update尤其是生产环境大表。另外用DBeaver、Navicat这类工具时WHERE条件为空的情况下会有安全提示这个不能关掉特别是刚接手新库的时候。2.4 修改表结构与默认值在线DDL的细节修改表结构最常见的语句是alter table。在8.0里很多alter操作是online的不像5.7那样动不动锁表。但“online”不等于“完全不阻塞”也不是所有操作都instant。比如alter table t add column c int在8.0里可以instant只修改元数据速度快但alter table t modify column c bigint可能会重建表数据量大的时候耗时很长。上午特意试了“设置默认值为0”alter table t alter column status set default 0;这是标准做法。注意alter column和modify column不一样前者只改默认值、不动其他列属性后者会重新定义整列容易覆盖已有注释、类型等。还有个小坑如果一个字段本来没有默认值或者默认值是NULL你insert时不传值得到的是NULL而不是0。只有在建表或改表时设置default 0并且列不允许为NULL才能确保插入不传值时是0。关于修改结构时的锁8.0新增了INSTANT算法ALTER TABLE t ADD COLUMN d int, ALGORITHMINSTANT;这是最快的方式。但也不是什么都能instant比如加索引、修改列类型、修改字符集这些还得走INPLACE。DBA在生产环境做变更前我都会先用ALTER TABLE ... ALGORITHMINPLACE, LOCKNONE测试一遍避免把业务卡死。3. 索引从分类到执行计划建立一个够用的索引观3.1 索引的分类B树、全文、哈希、空间MySQL索引按数据结构分主要有B树索引、哈希索引、全文索引和空间索引。InnoDB默认的B树索引又分为聚簇索引和二级索引。聚簇索引就是主键索引叶子节点直接存整行数据二级索引叶子节点存的是索引列和主键值。所以“回表”的本质是二级索引查到主键后再通过主键回聚簇索引取整行数据。哈希索引在InnoDB里是自适应哈希索引由存储引擎根据热点数据自动创建不能认为指定hash index。Memory引擎支持显式哈希索引适合等值查询但不适合范围查询。全文索引适合大文本的模糊搜索比如match(content) against(...)比like %...%快得多。3.2 索引失效执行计划里的“三不管”上午翻了一堆面试题其实面试官最想听的不是“什么是索引”而是“什么时候索引会失效”。常见的失效场景有在索引列上进行函数运算比如where date(create_time)2026-03-16这种情况下索引失效应该改成where create_time 2026-03-16 00:00:00 and create_time 2026-03-17隐式类型转换比如字符串字段where phone13800138000数字常量会触发类型转换导致索引失效最左前缀原则被破坏联合索引(a,b,c)只用b或c查索引根本没法用。我平时定位这些问题就是看执行计划里的type列和key列。typeALL是走全表扫描keyNULL说明没用上索引rows估算扫了多少行。还要额外关注Extra列如果出现Using filesort、Using temporary说明排序和分组不能有效利用索引需要优化。3.3 索引设计原则创建索引不是越多越好创建索引是个技术活太少了查询慢太多了写入慢、占空间。常用的原则是常用于where条件、join关联、order by、group by的字段适合建索引区分度低的字段比如性别、状态不适合单独建索引联合索引优先把等值查询的字段放前面范围查询字段放后面。上午设计了一张订单表的联合索引(user_id, status, create_time)。为什么这么排列因为业务上最常见的查询是“某个用户的某个状态下的订单”然后按时间排序。这样排等值匹配user_id和statuscreate_time用于排序一次索引扫描就能完成排序不走filesort。如果反过来建(create_time, user_id, status)按人查时就用不上最左前缀等于白建。索引还有个隐藏特性叫做“索引下推”Index Condition PushdownMySQL 5.6之后才支持。比如联合索引(a,b)查询where a1 and b like x%b的like条件可以在索引遍历过程中直接过滤减少回表次数。这是面试常考点也是实际调优经常受益的点。4. 锁与事务为什么并发高的时候会出现锁等待4.1 从锁的分类说起MySQL的锁可以按粒度分为全局锁、表级锁、行级锁。全局锁是flush tables with read lock一般只用于全库备份。表级锁包括表锁和元数据锁MDLMDL是MySQL 5.5引入的机制用于保护表结构增删改查自动加MDL读锁alter table会加MDL写锁。晚上跑批量任务的时候如果和一个DDL撞在一起很容易出现“所有查询堵住”的现象本质就是MDL写锁排队。InnoDB的行级锁才是日常高并发场景的主角。按锁的类型又分共享锁S锁和排他锁X锁。S锁与S锁兼容S锁与X锁不兼容X锁与X锁不兼容。select ... for update加X锁select ... lock in share mode加S锁。普通select不加锁靠MVCC读快照。4.2 InnoDB行锁的具体玩法记录锁、间隙锁、临键锁InnoDB行锁不是笼统的“锁住一行”而是细分为记录锁Record Lock、间隙锁Gap Lock、临键锁Next-Key Lock。记录锁锁的是索引记录间隙锁锁的是两个索引记录之间的区间目的是防止幻读临键锁是记录锁和间隙锁的组合锁住当前记录和它前面的间隙。这些锁的加锁范围取决于隔离级别和SQL条件。在RR可重复读隔离级别下范围查询where id between 10 and 20会锁定扫描到的区间包括不存在的记录这就是为什么一个简单的update可能会阻塞其他insert。RC读已提交级别只锁记录不锁间隙所以插入不受阻塞但可能出现幻读。上午实际操作中遇到过一次行锁等待两个事务一个执行update t set status1 where id100另一个执行update t set status2 where id100第二个事务一直处于LOCK WAIT状态。排查语句是SELECT * FROM performance_schema.data_lock_waits\G SELECT * FROM sys.innodb_lock_waits\G能看到阻塞者是哪个事务、持有什么锁、等待者是哪个事务。如果业务上实在无法避免两条update同时更新同一行必须在前置环节做分布式锁或者调整事务顺序。4.3 事务ACID与隔离级别理解了原理才能用好事务的ACID是面试必问但实际使用中更关键的是隔离级别。MySQL默认是REPEATABLE READRR这和Oracle默认的READ COMMITTED不同。RR通过MVCC加间隙锁解决了部分幻读问题但仍然存在“当前读”下的幻读场景。四个隔离级别隔离级别脏读不可重复读幻读Read Uncommitted可能可能可能Read Committed不会可能可能Repeatable Read不会不会可能当前读下可能Serializable不会不会不会有人问可以直接用Serializable吗可以但并发能力会大大下降因为读写互相阻塞。实际项目里如果对数据一致性要求很高且并发量不大可以考虑但高并发互联网应用还是默认RR配合合理的锁顺序和事务长度控制。4.4 死锁的判定与处理死锁不是单纯“锁等待超时”而是两个或多个事务循环等待对方持有的锁。InnoDB内部有死锁检测机制检测到后会主动回滚其中一个事务报错信息里通常包含Deadlock found when trying to get lock; try restarting transaction。死锁现场复盘方式先看错误日志里的LATEST DETECTED DEADLOCK章节里面会显式写出两个事务的SQL、持有的锁、等待的锁。最常见的原因是多表更新的顺序不一致。比如事务A先更新表1再更新表2事务B先更新表2再更新表1两个事务并发时就会死锁。解决思路很简单所有事务都按同一个顺序更新表如果更新条件允许尽量缩小事务范围还可以在异常处理里捕获死锁错误做重试逻辑。我分享一个下午实践的ignored死锁案例批量更新订单状态时同一条SQL一次更新几千条内部加锁顺序不是按照主键id顺序导致两个批次任务互相死锁。改成先查询要更新的id列表并且order by id再分批更新基本彻底解决了死锁。5. 存储过程、函数与自动化脚本什么时候该用什么时候别用5.1 存储过程的优缺点要有数MySQL存储过程是把一段逻辑封装在数据库端创建后用call调用。优点是可以减少网络往返、统一逻辑、便于权限控制缺点是调试麻烦、版本控制难、数据库压力变大。现代应用架构其实不太推荐大量使用存储过程做复杂业务一般是报表统计、数据迁移、定时任务这类场景才适合。上午练习了一个比较常见的存储过程批量归档订单。逻辑是遍历超过180天的已完成订单插入归档表删除原表数据记录执行日志。定义基本框架如下DELIMITER // CREATE PROCEDURE archive_orders() BEGIN DECLARE done INT DEFAULT 0; DECLARE v_id BIGINT; DECLARE cur CURSOR FOR SELECT id FROM orders WHERE statuscompleted AND create_time DATE_SUB(NOW(), INTERVAL 180 DAY) LIMIT 1000; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done 1; OPEN cur; read_loop: LOOP FETCH cur INTO v_id; IF done THEN LEAVE read_loop; END IF; INSERT INTO orders_archive SELECT * FROM orders WHERE id v_id; DELETE FROM orders WHERE id v_id; COMMIT; END LOOP; CLOSE cur; END// DELIMITER ;注意这里用了游标CURSOR和CONTINUE HANDLER这个“NOT FOUND”处理器是存储过程里最容易忘记的少了它游标会一直循环到最后报错。另外LIMIT 1000是刻意加的避免一次处理太多数据导致锁范围过大。5.2 函数大全没必要背掌握常用高频就够很多人问“MySQL函数大全”其实平时用得最多的函数就那几十个。字符串类的CONCAT、SUBSTRING、REPLACE数值类的ROUND、FLOOR、CEILING日期类的NOW、DATE_FORMAT、DATEDIFF聚合类的COUNT、SUM、AVG、MIN、MAX条件类的IF、CASE WHEN。上午使用频率比较高的一个函数是DATE_FORMAT注意它和SQL Server的DATEPART不太一样。SQL Server里DATEPART(year, getdate())获取年份MySQL对应的是YEAR(NOW())或EXTRACT(YEAR FROM NOW())。不能在MySQL里直接写DATEPART会报FUNCTION database.DATEPART does not exist。做跨数据库迁移时要特别注意这类函数差异。JSON相关函数在8.0里也很重要比如JSON_EXTRACT、JSON_UNQUOTE、JSON_ARRAYAG。如果表里存了JSON字段查询时用WHERE JSON_EXTRACT(meta, $.level) 3但这种写法对索引不友好可以在JSON字段上建虚拟列再建索引性能才会好。5.3 和C、Java项目配合时的连接细节热词里有人搜“C链接MySQL”这个场景多见于windows桌面客户端直连数据库。C连接MySQL一般用MySQL Connector/C装这个之前必须先装ODBC驱动或者Connector/C库。编译时链接mysqlcppconn库代码里设置host、port、user、password、database然后执行查询。这里最容易遇到的坑是8.0默认的caching_sha2_password认证插件老版本Connector/C不兼容需要在my.ini或建用户时改成mysql_native_password。不少人用Navicat连不上8.0也是这个原因。JavaWeb项目连接MySQL则相对简单用JDBC URL带上useSSLfalseserverTimezoneAsia/Shanghai基本能避开SSL和时区两个最常见的连接问题。5.4 从MySQL同步到ClickHouse一个正在流行的架构热搜词里有一条“使用Flink实现MySQL同步到ClickHouse”正好上午研究到这儿。这是典型的数仓实时同步链路。流程是用Flink CDC监听MySQL的binlog解析变更数据然后通过JDBC或Flink JDBC sink写入ClickHouse。这种方案的优点是实时性好、代码量不大缺点是ClickHouse不适合频繁单行更新更适合批量写入后查询分析。简单示例架构MySQL binlog - Flink CDC - Flink 流处理 - ClickHouse实际部署时要注意MySQL需要开启binlog并设置binlog_formatROWFlink CDC连接器会自动识别表结构变更写入ClickHouse时尽量攒批比如batch.size1000或flush.interval5s避免每条记录都执行一次insert。上午还试了docker compose部署这套链路核心是三个服务mysql、flink-jobmanager、clickhouse。组合起来稍显复杂但手动把每个服务分别启动后链路跑通没问题。6. 常见报错与排查方法上午踩过的坑全记录6.1 MySQL服务无法启动的各种原因在Windows上用net start mysql启动时报“服务无法启动”这是往期答疑里最高频的问题。排查顺序固定为先查看错误日志Windows下在数据目录的*.err文件Linux下在/var/log/mysqld.log再看端口是否被占用然后确认my.ini配置是否有误。上午帮同事处理的一个报错是[ERROR] [MY-014060] [Server] invalid mysql server upgrade。这个报错出现在数据目录版本和二进制版本不一致时比如用MySQL 8.0.44的程序去启动5.7版本的数据目录。解决办法是备份数据目录用同版本程序重新初始化或者把数据目录的mysql库删掉重新初始化仅限非生产环境。如果升级时出现这个错最好的建议是先不要直接替换二进制而是用mysql_upgrade等官方路径5.7升8.0则建议用mysqldump逻辑导出再导入比原地升级稳得多。还有一类常见启动失败是[ERROR] Cant open the mysql.plugin table通常是数据目录损坏或权限错误。先用chown -R mysql:mysql /var/lib/mysql修正权限再尝试启动如果还是不行检查my.cnf里的datadir是否指向了正确路径。6.2 连不上数据库从网络层到认证层排查SQLyog、Navicat、DBeaver这类客户端连不上MySQL通常有几个层面的原因MySQL默认只监听localhost需要修改bind-address0.0.0.0防火墙放行3306端口用户权限要允许远程登录root%认证插件要兼容客户端。8.0的默认认证插件是caching_sha2_password如果是旧版客户端比如Navicat 11以下、部分旧版pymysql会报Authentication plugin caching_sha2_password cannot be loaded。临时解法是ALTER USER root% IDENTIFIED WITH mysql_native_password BY yourpassword;但我不建议数据库长期使用弱认证插件caching_sha2_password安全性更高。如果客户端太老最好升级客户端而不是降低数据库的安全标准。6.3 连接池与SSL握手时报错热搜词里还有“mysql ssl连接错误”。这个一般分为两种一是客户端启用了SSL但服务端证书有问题二是客户端未开启SSL而服务端要求必须SSL。错误信息会出现SSL connection error或Unable to load certificate。排查时先看服务端SSL状态SHOW VARIABLES LIKE %ssl%; SHOW STATUS LIKE %ssl%;如果服务端确实有证书那就是客户端不认证书或证书链不全。JDBC连接串里加useSSLfalse可以绕开但这只是测试环境做法。生产环境应该正确配置CA证书和主机名校验。如果SHOW VARIABLES LIKE have_ssl是DISABLED则要检查my.cnf里的ssl-ca、ssl-cert、ssl-key三个配置项重启服务。6.4 Flink同步、Sqoop连接和数据导入导出时的坑Sqoop连接不上MySQL有一个高频原因是用jdbc:mysql://ip:3306/db连接8.0时驱动还是老的com.mysql.jdbc.Driver。8.0的驱动类名改成了com.mysql.cj.jdbc.DriverURL上还要带上serverTimezoneAsia/Shanghai否则会报时区异常。如果报Access denied for user就确认Sqoop机器IP在授权范围里。执行SQL脚本时如果遇到中文乱码记得脚本文件保存为utf8连接URL也要带characterEncodingutf8。6.5 性能调优的常规思路上午最后一部分是性能调优笔记。不直接改my.cnf参数先看瓶颈在哪是全表扫描多、锁等待多、还是慢SQL多。最有效的入口是慢查询日志。开启方式slow_query_logON long_query_time2 slow_query_log_file/var/log/mysql-slow.log拿到慢SQL后EXPLAIN看到typeALL、rows很大优先加索引filesort和temporary多从SQL写法或索引设计上调整如果rows小但响应慢可能是锁等待或网络往返太多可以用performance_schema查锁事件。很多参数不建议照抄网上的“最优配置”比如innodb_buffer_pool_size线上8G内存默认用128M明显不够但直接改成6G也可能导致Swap。更稳妥的做法是设为物理内存的50%到70%留足操作系统和其他进程的空间。同时开启innodb_flush_log_at_trx_commit2允许丢失1秒日志换性能还是默认的1每次提交刷盘更安全要看业务对数据丢失的容忍度。金融交易必须1日志分析这种可以2。最后关于上午学习的一点个人感受今天上午这轮操作下来我最大的体会是MySQL的入门门槛不高但用得越深越觉得体系庞大。安装只是第一步真正考验能力的是锁、事务、索引优化、异常排查这些“看不见”的部分。学习过程中我建议多用一个小本子把遇到的每个报错原文抄下来然后写上根因和解决方案。这个方法我坚持了三年比看十篇教程都有用。学习顺序上个人建议先熟练基础SQL再研究索引和事务然后学复制和高可用最后再碰性能优化。上午记性最深的时刻是排查invalid mysql server upgrade这个报错花了一个小时最后发现仅仅是数据目录版本和二进制版本不匹配。类似这种问题日志里面其实写得很清楚关键是要静下心看日志而不是慌乱地重启服务。记录就先写到这里。这篇笔记里的内容直接照着操作大多能复现但不同系统、不同版本之间还会有细微区别。如果你正好卡在某个报错上欢迎带着具体日志来聊我尽量给出可落地的排查建议。
返回列表