InnoDB存储引擎对MVCC的实现
MVCC 让读写少冲突:快照读不加锁,当前读才走锁。理解 Read View 是读懂 repeatable read 的关键。 三要素 隐藏列:DB_TRX_ID(最后修改事务 ID)、DB_ROLL_PTR(回滚指针)。 undo log:保存旧版本链,支持回滚与一致性读。 Read View:事务启动时(或首次一致性读)生成,判断行版本可见性。 可见性规则(简化)比较行的 trx_id 与 Read View 的 min/max 及活跃事务列表:若版本对当前事务不可见,沿 undo 链找更早版本。 快照读 vs 当前读1234-- 快照读(普通 SELECT)SELECT * FROM account WHERE id = 1;-- 当前读(加锁读)SELECT * FROM account WHERE id = 1 FOR UPDATE; RR 下快照读可避免不可重复读;幻读靠间隙锁/next-key lock 在当前读场景防护。 实践建议短事务、避免长查询占旧版本导致 undo 堆积;监控 History list length。 版本链长度频...
MySQL高性能优化规范建议总结
性能优化先靠规范预防,再靠监控定位。本文把团队常踩的雷区整理成可执行的 checklist。 建表规范统一 utf8mb4;主键尽量短且单调;字段 NOT NULL + 默认值;大字段拆表;金额用 DECIMAL。 索引规范WHERE/ORDER/JOIN 列建合适联合索引;控制索引数量;避免冗余索引;定期用 sys/performance_schema 查未使用索引。 SQL 规范禁止 SELECT *;分页深翻页改游标或延迟关联;批量操作分批 commit;避免大事务。 1234-- 深分页优化示例SELECT * FROM orders oJOIN (SELECT id FROM orders WHERE user_id=1 ORDER BY id DESC LIMIT 10000, 20) tON o.id = t.id; 连接与缓存合理设置 max_connections 与连接池;8.0 后别指望 query cache;热点读走 Redis 但要有穿透保护。 连接池参数池大小不是越大越好,常设 CPU*2 左右并压测。wait_t...
MySQL事务隔离级别详解
隔离级别是并发正确性与性能的旋钮。InnoDB 默认 RR,但「可重复读」不等于完全无幻读。 四种级别 级别 脏读 不可重复读 幻读 READ UNCOMMITTED 可能 可能 可能 READ COMMITTED 否 可能 可能 REPEATABLE READ 否 否 InnoDB 当前读仍防 SERIALIZABLE 否 否 否 InnoDB 实现要点RC 每次 SELECT 新快照;RR 首次一致性读建 Read View。幻读在 RR 下通过 next-key lock 在当前读场景限制。 1234SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;START TRANSACTION;SELECT * FROM account WHERE id=1 FOR UPDATE;COMMIT; 实践建议大多数 OLTP 用默认 RR;若需要最新已提交读(如报表)可会话级 RC;避免长事务。 死锁与隔离RR 下间隙锁增加死锁概率;应用捕获 1213 重试。锁等待 timeout 调优 inno...
MySQL日期类型选择建议
存时间看起来 trivial,却影响时区、范围、索引与跨系统交换。类型选对,后面少很多 bug。 类型对比 DATETIME:8 字节,范围 1000-9999,与时区无关存字面量,推荐业务时间戳。 TIMESTAMP:4 字节,2038 上限,受 session time_zone 影响,自动 ON UPDATE 方便。 BIGINT:存 Unix 毫秒,跨语言一致,展示需应用层格式化。 12345CREATE TABLE event ( id BIGINT PRIMARY KEY, occurred_at DATETIME(3) NOT NULL COMMENT '业务发生时间 UTC+8 存字面量', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); 选型建议金融/订单用 DATETIME(3) 或 BIGINT 毫秒;日志归档可用 BIGINT 节省比较成本;全球化产品统一 UTC 存储、本地化展示。 跨时区团队规范存储 UTC、展示 local 是通用做法。数据库 server ...
MySQL数据同步到Elasticsearch详解:常见方案与一致性处理
搜索与分析常需要 ES,但主库仍是 MySQL。关键是选对接同步通道并设计好一致性边界。 常见方案 方案 优点 风险 应用双写 简单 不一致、失败补偿复杂 定时扫库 易实现 延迟大、扫库压力 Canal/Debezium 近实时、解耦 运维与顺序性要设计 Flink CDC 流式清洗聚合 架构较重 一致性策略以 MySQL 为准;ES 作最终一致读模型。失败重试+死信队列;全量重建与增量消费分离;版本号或 ts 防乱序覆盖。 实践建议12PUT /orders/_doc/1001{ "order_id": 1001, "status": "PAID", "updated_at": "2026-09-02T10:00:00Z" } mapping 提前定义;bulk 写入;监控 lag 与 rejected 任务。 映射与分词mapping 中 keyword vs text 决定聚合与搜索;中文分词器选型影响召回。全量 ...
MySQL执行计划分析
执行计划是优化器的「路线图」。看懂 type、key、rows、Extra,慢 SQL 排查才算入门。 EXPLAIN 关键列 type:system > const > eq_ref > ref > range > index > ALL,后三者需警惕。 key:实际使用的索引。 rows:估算扫描行数,不是结果行数。 Extra:Using index(覆盖)、Using filesort、Using temporary、Using index condition 等。 1EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id=1 ORDER BY created_at DESC LIMIT 20; 分析套路 是否走预期索引?否 → 谓词/类型/统计信息。 rows 是否过大?是 → 选择性或缺少联合索引。 是否 filesort/temporary?是 → ORDER/GROUP 与索引不匹配。 实践建议生产用 slow log + pt-qu...
MySQL查询缓存详解
Query Cache 曾是「相同 SQL 直接返结果」的尝试,但因锁竞争与失效粒度粗,已在 8.0 彻底移除。 曾经如何工作5.7 及以前,SELECT 命中缓存则跳过解析执行;任何表写操作会使涉及该表的缓存条目失效。缓存 key 由 SQL 文本+库+字符集等构成。 为何被弃用 表级失效:写多读少场景命中率极低。 全局锁竞争:高并发下 cache lock 成为瓶颈。 内存碎片与维护成本高于收益。 现代替代 应用层/Redis 缓存热点对象。 InnoDB buffer pool 缓存数据页(与 SQL 文本无关)。 8.0 移除后 query_cache_type 等变量不再存在。 实践建议别在旧文档里找 query cache 调优;把精力放在 SQL 优化、合适索引与外部缓存策略。 历史调优误区曾建议调 query_cache_size,现应彻底移除相关配置项。文档与旧博客需甄别 MySQL 版本。 应用侧缓存键设计缓存键应含业务维度与版本,避免发布后读旧结构对象。 实践复习清单确认 MySQL 版本无 query cache;应用缓存键规范;buff...
MySQL三大日志(binlog、redo log和undo log)详解
三大日志回答三个问题:崩溃如何恢复、事务如何回滚与 MVCC、主从与 PITR 如何做到。 各 log 职责 日志 层级 作用 redo InnoDB 崩溃恢复,保证已提交事务持久 undo InnoDB 回滚、MVCC 旧版本 binlog Server 复制、审计、时间点恢复 两阶段提交事务提交时 redo prepare → 写 binlog → redo commit,保证引擎与 server 层一致,避免主从数据分叉。 配置关注点123innodb_flush_log_at_trx_commit = 1 # 每次提交刷盘,最安全sync_binlog = 1 # binlog 同步刷盘binlog_format = ROW # 主从一致性与闪回友好 实践建议误删恢复:先停写入,保留 binlog,全量+增量回放。监控 redo 日志等待与 checkpoint。 flashback 思路ROW binlog 可解析为反向 SQL,需工具(binlog2sql)...
MySQL索引失效场景总结
索引失效不是神秘现象,多是谓词写法、类型或统计信息让优化器放弃索引。 高频失效场景 对索引列使用函数或运算:WHERE YEAR(d)=2026。 隐式类型转换(见专题文)。 联合索引不满足最左前缀。 使用 !=、NOT IN、OR(部分可 merge,部分全扫)。 LIKE '%xx' 前缀通配。 优化器判断回表成本高于全表扫(小表或选择性差)。 验证方法123EXPLAIN SELECT * FROM t WHERE ...;SHOW INDEX FROM t;ANALYZE TABLE t; 优化思路改写 SQL 让谓词「索引用得上」;增加覆盖索引减少回表;必要时分区或归档冷数据。 优化器成本模型rows 估算是统计信息驱动,数据分布突变后需 ANALYZE。histogram(8.0)改善选择性估计。 索引合并index merge union/intersection 有时替代联合索引,但不一定稳定。 实践复习清单收集 ten 条失效 SQL 改写对照;ANALYZE 后 replan;覆盖索引设计练习;filesort 告警;冗余索引...
MySQL索引详解
索引是 InnoDB 性能的第一杠杆。理解 B+ 树与聚簇/二级索引差异,设计才不会拍脑袋。 B+ 树为何适合磁盘多路平衡、叶子链表便于范围扫;非叶只存键减少 IO。InnoDB 聚簇索引叶子存整行,二级索引叶子存主键值需回表。 最左前缀与覆盖索引联合索引 (a,b,c) 可支持 a、a+b、a+b+c 前缀查询;覆盖索引指 SELECT 列全在索引内,Extra 出现 Using index。 123CREATE INDEX idx_user_status ON orders(user_id, status, created_at);-- 覆盖列尽量放进索引SELECT user_id, status, created_at FROM orders WHERE user_id=1 AND status=1; 索引下推 ICP5.6+ 在存储引擎层先过滤二级索引条件,减少回表次数。 设计原则高选择性列在前;控制宽度;避免重复索引;监控 duplicate index。 前缀索引与区分度INDEX(name(10)) 要算 distinct prefix 选择性。过...