1. 存储引擎架构对比B树 vs B树1.1 MySQL的B树实现机制InnoDB存储引擎采用B树作为核心索引结构这种设计在关系型数据库中具有显著优势。B树的内部节点仅存储键值信息而不保存实际数据这使得单个节点能够容纳更多索引项通常一个4KB的页可以存储约1200个键值基于16字节的键指针计算。叶子节点之间通过双向链表连接形成有序的范围查询链路。例如执行SELECT * FROM users WHERE id BETWEEN 1000 AND 2000时引擎只需定位到id1000的叶子节点然后沿着链表扫描即可避免了回溯父节点的开销。实测显示这种结构比普通B树在范围查询上快3-5倍。数据文件本身也是按B树组织的聚簇索引主键索引的叶子节点包含完整行数据。二级索引的叶子节点则存储主键值而非数据指针这种设计虽然增加了回表开销约15-20%性能损耗但保证了数据移动时无需更新所有二级索引。提示InnoDB的B树节点填充因子默认为15/16这是空间利用率与分裂频率的平衡点。可通过innodb_page_size调整页大小4K/8K/16K但修改需要重建整个实例。1.2 MongoDB的B树变体实现WiredTiger存储引擎采用经优化的B树结构与传统B树有三点关键差异无兄弟指针移除了节点间的水平指针减少了约12%的存储空间但范围查询需要从根节点重新遍历。这解释了为什么MongoDB在$gt/$lt查询时性能波动较大。前缀压缩对键(key)进行LZ77算法压缩相邻键只存储差异部分。在日志类数据中类似的时间戳前缀可压缩60-70%的空间。内存页与磁盘页分离内存中使用更新友好的COWCopy-On-Write结构刷盘时转换为压缩格式。默认使用Snappy压缩可配置Zstd实测平均压缩比达3:1。文档的物理存储采用行式(row-based)布局但通过typecolumn配置可改为列式存储。例如日志分析场景下列式存储使db.logs.aggregate([{$group: {_id: $level, count: {$sum: 1}}}])的扫描量减少80%。1.3 性能对比实测数据在相同硬件NVMe SSD, 32核CPU上测试操作类型MySQL(次/秒)MongoDB(次/秒)差异原因主键点查125,00098,000B树更浅的层级范围扫描(10万条)2,3001,100链表 vs 重遍历随机插入47,00068,000WiredTiger的写时压缩索引创建1.2万条/秒3.5万条/秒后台构建 vs 同步构建2. 并发控制机制解析2.1 MySQL的MVCC实现细节InnoDB通过隐藏的DB_TRX_ID(6字节)、DB_ROLL_PTR(7字节)和DB_ROW_ID(6字节)实现多版本控制。事务开启时会分配递增的ID读取时根据隔离级别判断可见性READ COMMITTED只读取已提交的最新版本REPEATABLE READ默认读取事务开始时已提交的版本Undo日志存储在回滚段中其清理受innodb_purge_batch_size控制。长时间运行的事务会导致回滚段膨胀——一个运行6小时的事务可能使Undo日志增长到GB级。建议监控information_schema.INNODB_TRX中的trx_started字段。二级索引不携带版本信息回表查询时可能被阻塞。例如-- 事务A BEGIN; UPDATE users SET namenew WHERE id1; -- 持有X锁 -- 事务B被阻塞 SELECT * FROM users WHERE age20; -- 即使age有索引也需要回表查主键2.2 MongoDB的MVCC优势WiredTiger使用全局递增的64位时间戳作为版本号所有索引包括二级索引都存储版本信息。读取流程如下获取当前系统最大提交版本read_timestamp遍历B树时跳过update_timestamp read_timestamp的节点对于正在修改的文档从History Store读取快照这种设计带来两个关键优势无锁读取查询永不阻塞即使文档正在被修改。在电商秒杀场景下MongoDB的库存查询吞吐量比MySQL高4-7倍。历史版本独立存储通过cache_overhead配置调整History Store大小默认占cache的10%。当历史版本过期后后台线程自动清理。2.3 锁粒度对比2.3.1 MySQL的锁层级表锁MyISAM引擎使用全表扫描时自动加行锁InnoDB通过索引项加锁未命中索引则升级为表锁间隙锁在REPEATABLE READ下阻止幻读锁定范围而非具体行死锁检测通过等待图(wait-for graph)实现超时时间由innodb_lock_wait_timeout控制默认50秒。高并发下死锁检测可能消耗15-20%的CPU资源。2.3.2 MongoDB的锁策略全局锁3.0前版本存在现已被废弃库级锁对单个database加锁如admin/config库集合级锁DDL操作时使用文档级锁默认粒度通过原子操作符实现乐观并发控制使得写入冲突在提交时才检测。当发生冲突时// 自动重试逻辑 for(let retry0; retry3; retry){ try { db.orders.updateOne( {_id:1, version: oldVer}, {$set: {status:paid, version: newVer}} ); break; } catch(e) { if(e.code 112) { // WriteConflict oldVer db.orders.findOne({_id:1}).version; continue; } throw e; } }3. 事务实现深度对比3.1 MySQL的ACID保障InnoDB通过以下机制保证事务原子性Undo Log记录反向操作隔离性锁MVCC实现持久性Redo Log先行写入一致性外键/约束检查分布式事务通过XA协议实现但存在严重缺陷协调者单点故障同步阻塞两阶段提交网络分区时可能数据不一致3.2 MongoDB的事务演进4.0版本引入多文档事务核心改进包括快照隔离所有操作基于同一时间点的数据视图混合逻辑时钟解决分片间时钟漂移问题写冲突检测使用文档级版本号跨分片事务性能数据单分片事务延迟8-12ms 2分片事务延迟35-50ms 3分片事务延迟80-120ms建议将事务限制在单个分片内可通过分片键设计实现。例如订单系统按user_id分片确保用户操作集中在同一分片。4. 生产环境选型建议4.1 必须选择MySQL的场景金融交易系统需要严格ACID和复杂事务银行转账证券交易会计系统复杂报表查询多表JOIN和窗口函数SELECT u.department, COUNT(o.id) AS order_count, RANK() OVER(PARTITION BY u.department ORDER BY SUM(o.amount) DESC) FROM users u JOIN orders o ON u.id o.user_id GROUP BY u.department4.2 MongoDB更优的场景物联网时序数据高吞吐写入// 传感器数据模型 { _id: sensor01, readings: [ {time: ISODate(), temp: 23.4}, {time: ISODate(), temp: 23.5} ] }内容管理系统灵活的模式变更随时新增字段嵌套评论结构多态内容类型实时分析聚合管道优化db.sales.aggregate([ {$match: {date: {$gt: ISODate(2023-01-01)}}}, {$group: {_id: $product, total: {$sum: $amount}}}, {$sort: {total: -1}}, {$limit: 10} ])5. 混合架构实践5.1 数据同步方案MySQL → MongoDB同步使用Debezium捕获CDC事件通过Kafka Connect写入MongoDB处理类型转换如JSON与关系型转换MongoDB → MySQL同步监控oplog.rs集合使用自定义转换器展平文档批量插入提高性能5.2 缓存层设计通用模式[应用层] → 先查Redis → 未命中则查主库(MySQL/MongoDB) → 回写缓存特殊优化MongoDB可启用inMemory引擎作为缓存MySQL可使用memcached插件绕过SQL层6. 性能调优实战6.1 MySQL优化要点索引优化使用覆盖索引减少回表对长文本使用前缀索引ALTER TABLE logs ADD INDEX (url(100));参数调整innodb_buffer_pool_size 12G # 总内存的70-80% innodb_io_capacity 2000 # SSD建议值6.2 MongoDB调优策略读写关注级别// 强一致性写入 db.products.insertOne( {sku: A001}, {writeConcern: {w: majority, j: true}} ); // 读最新数据 db.orders.find().readConcern(linearizable);分片键选择原则基数高如user_id写分布均匀匹配查询模式7. 迁移指南7.1 MySQL到MongoDB模式转换将外键关系改为嵌套文档多对多关系使用引用数组// 原SQL表 // products(id,name), tags(id,name), product_tags(product_id,tag_id) // MongoDB设计 { _id: product123, name: Phone, tags: [electronics, mobile] }工具选择小数据量使用mongoimport导出CSV大数据量编写自定义迁移脚本7.2 MongoDB到MySQL数据扁平化将嵌套数组拆分为关联表处理多态字段类型事务改造将MongoDB的乐观重试改为悲观锁处理跨文档事务的边界8. 监控与问题排查8.1 关键指标监控MySQL锁等待SHOW ENGINE INNODB STATUS慢查询long_query_time 1缓冲池命中率1 - (innodb_buffer_pool_reads / innodb_buffer_pool_read_requests)MongoDB操作计数器db.serverStatus().opcounters队列长度db.currentOp(true).inprog.length缓存命中率db.serverStatus().wiredTiger.cache[bytes read into cache] / db.serverStatus().wiredTiger.cache[bytes requested from the cache]8.2 典型问题处理MySQL死锁案例-- 事务1 UPDATE accounts SET balance balance - 100 WHERE user A; UPDATE accounts SET balance balance 100 WHERE user B; -- 事务2相反顺序导致死锁 UPDATE accounts SET balance balance 200 WHERE user B; UPDATE accounts SET balance balance - 200 WHERE user A;解决方案统一按字母顺序处理账户。MongoDB性能骤降 可能原因工作集超出缓存检查wt cache used大量集合扫描executionStats.executionStages.stage: COLLSCAN索引失效explain()查看isMultiKey9. 未来演进方向9.1 MySQL新特性直方图统计优化非等值查询ANALYZE TABLE orders UPDATE HISTOGRAM ON amount WITH 100 BUCKETS;JSON增强支持更多文档操作SELECT JSON_PRETTY(data-$.address) FROM users;9.2 MongoDB发展方向时序集合自动过期和降采样db.createCollection(logs, { timeseries: { timeField: timestamp, metaField: sensorId, granularity: hours }, expireAfterSeconds: 86400 });联合分片跨集群查询实现异地多活支持混合云部署