尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MySQL性能优化与事务原理:从索引、MVCC到分布式事务实战

MySQL性能优化与事务原理:从索引、MVCC到分布式事务实战 1. 面试准备为什么MYSQL优化与事务是必考题如果你正准备后端开发或数据库相关的面试那么“MYSQL优化”和“MYSQL事务”这两个话题几乎可以肯定会出现在面试官的提问清单里。这不仅仅是因为它们是MYSQL的核心知识点更是因为它们是衡量一个开发者是否具备生产环境思维、能否写出高质量代码的直接标尺。面试官问这些本质上是在考察你第一有没有处理过真实、有压力的数据场景第二是不是只停留在“会用”的层面还是真正理解其内部机理第三面对复杂业务时能否设计出合理、可靠的数据访问方案。我见过不少候选人对基本的CRUD操作对答如流但一深入到“为什么你的SQL慢”、“事务隔离级别怎么选”这类问题时思路就开始模糊回答停留在概念背诵层面。这其实很吃亏。因为在实际工作中数据库层面的问题往往是系统瓶颈的根源也是性能优化收益最大的地方。理解优化和事务意味着你能从源头规避大量潜在的生产事故比如慢查询拖垮整个服务或者并发更新导致的数据错乱。所以这篇内容不是简单的知识点罗列而是结合我过去在面试别人和被面试中那些高频、深入且容易踩坑的问题帮你把散落的知识点串联成一套可以实战的思维框架。我们会从“怎么做”SQL优化实战讲到“为什么”事务原理与选择目标是你离开时不仅能回答面试题更能清晰地向面试官阐述你过去项目中相关的设计决策和权衡思考。2. SQL优化从诊断到根治的实战思路很多人在谈优化时会直接跳到“加索引”这一步。但在我看来优化第一步永远是“诊断”。你不知道问题在哪所有优化都是盲目的。SQL优化的完整链条应该是监控发现 - 定位慢SQL - 解读执行计划 - 针对性优化 - 验证效果。下面我们拆开一步步说。2.1 如何精准定位慢查询在生产环境我们主要依靠MYSQL的慢查询日志Slow Query Log。开启和配置它是最基础的操作-- 查看慢查询相关参数 SHOW VARIABLES LIKE ‘slow_query_log%‘; SHOW VARIABLES LIKE ‘long_query_time%‘; -- 动态设置重启后会失效需在配置文件中修改以持久化 SET GLOBAL slow_query_log ‘ON‘; SET GLOBAL long_query_time 2; -- 设置慢查询阈值为2秒 SET GLOBAL slow_query_log_file ‘/var/lib/mysql/slow.log‘;这里有个关键点long_query_time的设置并非一成不变。对于核心交易接口1秒可能都算慢对于后台报表查询5秒或许可以接受。你需要根据业务场景来定义“慢”的标准。开启后所有执行时间超过阈值的SQL都会被记录到日志文件中。拿到慢日志后直接看文本比较低效。我习惯用mysqldumpslow或pt-query-digestPercona Toolkit 中的工具进行分析。后者功能更强大它能将日志中的SQL进行归类、统计直接告诉你哪些类型的SQL总耗时最长、执行次数最多帮你快速找到“最值得优化”的目标。注意开启慢查询日志对性能有轻微影响主要是I/O在高并发生产环境中建议长期开启但合理设置阈值并定期归档和分析日志文件避免磁盘被写满。2.2 读懂执行计划EXPLAIN是你的X光机找到慢SQL后下一步就是用EXPLAIN命令查看它的执行计划。这就像给SQL语句拍了一张X光片你能看到数据库引擎打算如何执行它。执行计划结果中有几个字段至关重要type访问类型性能从优到劣大致是system const eq_ref ref range index ALL。我们要尽量避免出现ALL全表扫描。key实际使用的索引。如果这里为NULL说明没用到索引。rowsMYSQL预估需要扫描的行数。这个数字越小越好。Extra额外信息这里常藏着“魔鬼”。比如Using filesort表示需要额外的排序操作无法利用索引排序通常在ORDER BY和GROUP BY子句未用对索引时出现。Using temporary表示需要创建临时表来处理查询常见于复杂的GROUP BY或DISTINCT。Using index这是个好信号表示查询使用了覆盖索引无需回表。我举个例子假设你有一条查询SELECT * FROM users WHERE age 20 ORDER BY name;并在age和name上分别建立了单列索引。EXPLAIN后可能发现type是range用上了age索引但Extra里有Using filesort。这说明虽然通过索引找到了年龄大于20的行但排序name时引擎不得不把找到的这些行在内存或磁盘里再排一次序因为(age, name)的联合索引才能同时满足筛选和排序。这就是一个典型的优化点。2.3 索引优化实战如何创建有效的索引知道了问题就要动手解决。索引优化是SQL优化中最核心的部分。但创建索引不是越多越好每个索引都会增加写操作INSERT, UPDATE, DELETE的开销和磁盘占用。你需要像医生开药一样精准地创建索引。原则一考虑索引的选择性。选择性越高即唯一值越多的列索引效果越好。比如给“性别”字段建索引因为只有‘男‘/‘女‘两种值效果就很差而给“用户ID”或“手机号”建索引效果就极佳。原则二遵循最左前缀匹配原则。对于联合索引(a, b, c)它可以用于加速WHERE a ?、WHERE a ? AND b ?、WHERE a ? AND b ? AND c ?的查询但无法加速WHERE b ?或WHERE b ? AND c ?的查询。在设计联合索引时必须把最常用作查询条件的列放在最左边。原则三利用覆盖索引减少回表。如果索引包含了查询所需的所有字段引擎就无需再回到主键索引聚簇索引中去查找数据行这能极大提升性能。例如查询是SELECT id, username FROM users WHERE username ‘xxx‘;那么一个(username, id)的联合索引虽然id是主键但InnoDB的二级索引叶子节点会自动包含主键值或者单独在username上的索引都可以成为覆盖索引。原则四小心索引失效的陷阱。即使创建了索引写SQL时不注意也会导致索引失效对索引列进行函数操作或计算WHERE YEAR(create_time) 2023会导致create_time索引失效。应改为WHERE create_time ‘2023-01-01‘ AND create_time ‘2024-01-01‘。使用!或操作符。使用OR连接条件如果OR前后的条件列并非都有索引那么索引可能会失效。使用LIKE以通配符%开头WHERE name LIKE ‘%张‘。2.4 超越索引语句编写与架构层面的优化优化不止于索引。在编写SQL语句时良好的习惯能避免很多性能问题。**只取所需避免 SELECT ***SELECT *会查询所有列包括不需要的 TEXT/BLOB 大字段增加网络传输和内存开销。明确列出需要的字段。分页查询优化对于LIMIT 100000, 20这种深度分页偏移量越大越慢。优化方法可以是使用子查询先定位主键SELECT * FROM table WHERE id (SELECT id FROM table ORDER BY id LIMIT 100000, 1) LIMIT 20。或者更好的方式是使用游标分页基于上次查询的最后一条记录的ID。关联查询优化确保JOIN的字段上有索引并且小表驱动大表即数据量小的表作为驱动表。多表关联时查询复杂度会几何级增长需要仔细评估。合理使用批处理避免在循环中执行单条SQL。例如插入多条数据时使用INSERT INTO ... VALUES (...), (...), (...)能大幅减少网络交互和事务开销。在架构层面当单表数据量过大时就要考虑分库分表。但分库分表是“核武器”会带来分布式事务、跨分片查询等复杂问题不应作为首选方案。前期可以通过历史数据归档将冷数据迁移到其他存储来维持主表的高性能。3. 事务确保数据正确的基石如果说SQL优化解决的是“快”的问题那么事务解决的就是“对”的问题。在并发环境下多个操作必须作为一个不可分割的整体来执行这就是事务。MYSQL的InnoDB存储引擎完全支持事务。3.1 深入理解ACID特性事务的四大特性ACID是面试必问基础但你不能只背名词。原子性Atomicity事务内的操作要么全部成功要么全部失败。这靠Undo Log回滚日志实现。你每做一个修改Undo Log都会记录相反的操作。如果事务失败或回滚引擎就执行Undo Log里的记录让数据恢复到事务前的状态。一致性Consistency事务执行前后数据库都必须处于一致性状态。这更多是应用层的责任比如转账前后总金额不变。数据库通过保证原子性、隔离性和持久性来辅助实现一致性。隔离性Isolation并发事务之间相互隔离互不干扰。这是最复杂的一点也是下面要重点讲的。它通过锁机制和多版本并发控制MVCC来实现。持久性Durability事务一旦提交对数据的修改就是永久性的。这靠Redo Log重做日志实现。修改数据时先写Redo Log再更新内存中的数据页。即使系统崩溃重启后也能根据Redo Log重做已提交的事务确保数据不丢失。这里有个关键理解Undo Log用于回滚保证原子性Redo Log用于崩溃恢复保证持久性。它们共同构成了InnoDB崩溃恢复能力的核心。3.2 事务隔离级别与并发问题SQL标准定义了四种隔离级别从宽松到严格依次是读未提交Read Uncommitted、读已提交Read Committed、可重复读Repeatable Read、串行化Serializable。隔离级别越低并发性能越高但可能出现的并发问题也越多。三种典型的并发问题是脏读Dirty Read一个事务读到了另一个未提交事务修改的数据。如果那个事务回滚了读到的数据就是无效的。这发生在“读未提交”级别。不可重复读Non-repeatable Read在同一个事务内两次读取同一条记录结果不一样因为被其他已提交事务修改了。这发生在“读未提交”和“读已提交”级别。幻读Phantom Read在同一个事务内两次执行相同的查询返回的记录集合不同因为其他已提交事务插入或删除了数据。注意幻读和不可重复读的侧重点不同不可重复读针对某一行的更新幻读针对结果集的增减。MYSQL InnoDB的默认隔离级别是可重复读Repeatable Read。在这个级别下它通过MVCC机制解决了脏读和不可重复读的问题。对于幻读在“可重复读”级别下InnoDB通过Next-Key Lock临键锁这种锁算法在很大程度上可以避免幻读特别是在当前读即加锁读的场景下。但在一致性非锁定读快照读下仍然可能出现幻读这也是为什么有些场景下需要升级到“串行化”或使用显式锁。3.3 MVCC多版本并发控制的魔法MVCC是InnoDB实现高并发读写的关键。它让读操作不用加锁写操作也可以不阻塞读操作一定程度上。它的核心是为每行数据维护了多个版本。InnoDB会在每行记录后增加两个或三个隐藏字段DB_TRX_ID最近一次修改或插入该行数据的事务ID。DB_ROLL_PTR指向该行数据上一个版本在Undo Log中位置的指针。DB_ROW_ID可选行ID当没有主键时。此外每个事务在开始时会获取一个全局递增的事务ID并生成一个当前系统的活跃事务ID列表的视图。当一个事务执行查询时它只会查找数据行中DB_TRX_ID早于当前事务ID且要么是已提交的事务要么就是事务自身修改的数据。对于DB_TRX_ID在活跃事务列表中的行说明修改它的事务还未提交该版本不可见。通过DB_ROLL_PTR指针在Undo Log中找到符合条件的旧版本数据。这样每个事务读到的都是一个与其启动时间点一致的“快照”从而实现了“可重复读”。这也是为什么在默认隔离级别下你开启一个事务后无论其他事务如何提交修改你多次查询的结果都是一样的。3.4 锁机制详解共享锁、排他锁与间隙锁MVCC主要解决了“读-写”冲突让读不阻塞写写不阻塞读。但对于“写-写”冲突还是需要锁来保证安全。共享锁S Lock允许事务读一行数据。多个事务可以同时获得同一数据行的共享锁。排他锁X Lock允许事务更新或删除一行数据。一个事务获取某行的排他锁后其他事务不能再获取该行的任何锁。在InnoDB中锁的粒度可以到行级这大大提升了并发度。但行锁是基于索引实现的如果一条SQL用不到索引InnoDB就会退化为表锁这是要极力避免的。除了行锁InnoDB在“可重复读”隔离级别下为了解决幻读问题引入了间隙锁Gap Lock和临键锁Next-Key Lock。间隙锁锁住索引记录之间的间隙防止其他事务在这个间隙中插入新记录。例如表中有ID为1510的记录那么间隙锁可能锁住(1,5), (5,10), (10, ∞)这些区间。临键锁是行锁Record Lock和间隙锁Gap Lock的结合锁住某一行以及该行之前的间隙。它是InnoDB默认的行锁算法。实操心得间隙锁是导致死锁的常见原因之一。比如两个事务同时尝试在同一个间隙插入不同的数据它们可能互相等待对方持有的间隙锁从而导致死锁。在设计业务时如果并发插入量很大可以考虑使用不具有唯一约束的索引或者调整隔离级别但会引入幻读风险或者将插入操作设计为顺序的以减少间隙锁的冲突范围。4. 面试高频问题深度剖析与回答思路结合上面的原理我们来看几个面试中经常被深挖的问题以及如何组织你的回答。4.1 “如何优化一条慢SQL”这是一个综合性问题考察你的排查和解决思路。你可以按步骤回答定位“首先我会通过监控或慢查询日志定位到具体的慢SQL语句。”分析“使用EXPLAIN命令分析其执行计划。重点关注type字段是否出现全表扫描ALLkey字段是否用到了索引rows字段预估扫描行数是否过大以及Extra字段是否有Using filesort或Using temporary等不良信息。”针对性解决“如果没用到索引我会检查WHERE、ORDER BY、GROUP BY子句涉及的字段考虑创建合适的单列或联合索引并注意最左前缀原则。”“如果出现了Using filesort我会考虑优化索引使其能同时满足查询条件和排序需求或者评估是否可以在业务侧排序。”“如果出现了Using temporary可能是GROUP BY或DISTINCT的列没有索引或者查询字段太多导致无法使用内存临时表而用到了磁盘临时表。我会尝试优化查询语句或增加tmp_table_size参数。”“我也会检查SQL语句本身是否写了SELECT *是否有多表关联但关联字段类型不一致或者是否有深分页问题。”验证“优化后再次使用EXPLAIN验证执行计划是否改善并在测试环境或低峰期验证实际执行时间。”这样的回答展现了你有方法论而不仅仅是背答案。4.2 “说说MVCC的实现原理”这个问题考察你对InnoDB核心机制的理解。回答要点“MVCC多版本并发控制是InnoDB实现高并发读写的关键机制。它的核心是数据多版本和一致性读视图。”数据多版本“InnoDB的每行记录都有两个或三个隐藏字段事务IDDB_TRX_ID和回滚指针DB_ROLL_PTR。每次更新数据时都会生成一条新的版本记录并通过回滚指针形成一个版本链旧数据存放在Undo Log里。”一致性读视图“事务开始时会生成一个当前系统活跃事务ID的视图。当这个事务执行查询时”可见性判断“它会根据这个视图来判断数据版本的可见性。规则是版本的事务ID必须小于当前事务ID且该事务已提交或就是本事务自身修改的如果版本的事务ID在活跃事务列表中说明该事务还未提交则该版本不可见。引擎会沿着版本链找到第一个对本事务可见的数据版本。”作用“这样每个事务读到的都是一个与其启动时刻一致的‘快照’从而实现了‘可重复读’隔离级别读操作不加锁大大提升了并发性能。”4.3 “RR可重复读隔离级别下如何避免幻读”这个问题有陷阱因为“可重复读”并不完全保证避免幻读在快照读下。一个全面的回答应该是“在MYSQL InnoDB的‘可重复读’隔离级别下它通过两种机制来应对幻读问题。”对于快照读一致性非锁定读“通过MVCC机制实现。事务启动后第一次查询会生成一个一致性视图后续所有普通SELECT都基于这个视图因此看不到其他事务新插入的数据从而在‘读’的层面避免了幻读。”对于当前读锁定读“通过Next-Key Lock临键锁机制实现。当执行SELECT ... FOR UPDATE或UPDATE、DELETE语句时InnoDB会给扫描到的索引记录加上行锁同时给记录之间的间隙加上间隙锁。这样其他事务就无法在这个间隙中插入新的记录从而在‘写’的层面避免了幻读。” “所以在InnoDB的‘可重复读’级别下混合使用快照读和当前读的业务逻辑中幻读被很大程度上避免了。但如果业务逻辑严格要求完全杜绝幻读就需要使用‘串行化’隔离级别或者在整个事务中统一使用当前读加锁。”4.4 “什么是死锁如何排查和避免”死锁是并发系统中经典问题。回答时可以从定义、排查、避免三个层面展开。“死锁是指两个或以上的事务在执行过程中因争夺资源而造成的一种互相等待的现象若无外力干涉它们都将无法进行下去。” “在MYSQL中可以通过SHOW ENGINE INNODB STATUS命令查看最近的死锁信息重点关注LATEST DETECTED DEADLOCK部分它会详细记录导致死锁的事务、SQL语句以及各自持有的锁和等待的锁。” “避免死锁的一些常见实践有”保持事务简短尽快提交或回滚事务减少锁的持有时间。约定访问顺序在业务逻辑上约定对多个资源的访问比如多个表、多行数据都按照相同的顺序进行。这是破坏“循环等待”条件最有效的方法之一。合理使用索引确保SQL语句使用了索引避免行锁升级为表锁也减少锁定的范围。降低隔离级别在业务允许的情况下使用‘读已提交’隔离级别可以减少间隙锁的使用从而降低死锁概率。使用乐观锁对于冲突较少的场景可以使用版本号或时间戳实现乐观锁避免使用数据库的悲观锁SELECT ... FOR UPDATE。5. 分布式事务从本地到跨服务的挑战当系统从单体架构演进到微服务数据库也从单一实例变成了多个这时传统的事务本地事务就失效了。订单服务扣款成功但库存服务扣减失败数据就不一致了。这就是分布式事务要解决的问题。5.1 分布式事务的常见解决方案没有一种方案是完美的各有其适用场景和权衡。两阶段提交2PC这是一个强一致性协议包含协调者和参与者。分为准备阶段投票和提交阶段执行。它的优点是保证了强一致性但缺点是同步阻塞、性能差协调者单点故障。XA协议是2PC在数据库层面的标准实现但在互联网高并发场景下较少直接使用。TCCTry-Confirm-Cancel一种补偿型事务。针对每个服务业务层面需要实现三个操作Try预留资源、Confirm确认执行、Cancel取消释放。例如库存服务在Try阶段先冻结库存在Confirm阶段才真正扣减。它的优点是性能比2PC好数据最终一致但缺点是需要业务代码实现复杂的补偿逻辑开发成本高。本地消息表核心思想是“最终一致性”。发起事务的服务在本地数据库事务中除了执行业务操作还插入一条消息记录到本地消息表。然后有一个后台任务不断轮询消息表将消息发送给下游服务并确保下游消费成功。如果失败则不断重试。这种方式实现简单但消息表会耦合在业务数据库中且保证了最终一致而非实时一致。事务消息以RocketMQ的事务消息为代表。生产者先发送一个“半消息”到MQMQ通知生产者本地事务执行状态。本地事务成功则MQ投递消息给消费者本地事务失败则MQ丢弃消息。它解耦了业务和消息可靠性高是目前比较主流的方案。Saga模式将一个长事务拆分为一系列本地子事务。每个子事务都有对应的补偿操作。事务正常执行时按顺序执行子事务如果某个子事务失败则按反序执行前面所有已成功子事务的补偿操作。适用于业务流程长、步骤多的场景。5.2 Seata框架的原理浅析Seata是阿里开源的分布式事务解决方案它封装了多种模式AT、TCC、Saga、XA其中AT模式最常用对业务侵入小。AT模式Automatic Transaction的核心原理可以概括为“两阶段提交”的自动化版本但无需数据库支持XA协议。一阶段业务数据和回滚日志在同一个本地事务中提交。Seata会拦截业务SQL解析语义保存数据更新前的镜像before image和更新后的镜像after image到undo_log表中。二阶段提交如果全局事务成功TM通知TCTC异步清理各分支的undo_log即可。二阶段回滚如果全局事务失败TM通知TCTC根据XID找到对应的undo_log生成反向补偿SQL根据before image并执行完成数据回滚。AT模式的优点是像使用本地事务一样简单但注意它默认是基于全局行锁来保证隔离性的在高并发场景下可能会有性能瓶颈和死锁风险需要根据业务情况评估。5.3 如何选择分布式事务方案这是一个架构权衡问题面试时可以这样表达你的思考“选择分布式事务方案没有银弹核心是权衡一致性、性能和复杂度。”“如果业务要求强一致性且可以接受一定的性能损耗可以考虑XA或Seata的AT模式注意全局锁。对于跨银行转账这类场景强一致性是必须的。”“如果业务可以接受最终一致性这是互联网高并发场景下的主流选择。我会优先考虑事务消息如RocketMQ它的解耦性好可靠性高。其次可以考虑本地消息表实现更简单但耦合性高。”“如果业务逻辑非常复杂涉及多个步骤且可能失败TCC或Saga这类补偿型事务更合适。TCC对资源控制更精细但开发量大Saga更适合长流程但补偿逻辑的设计要小心必须保证幂等性。” “在实际项目中我们通常会根据不同的业务场景混合使用这些模式。比如核心交易链路用TCC保证实时一致性非核心的积分、通知等操作用消息队列保证最终一致性。”6. 实战中的疑难杂症与排查技巧理论懂了但在真实运维和开发中总会遇到一些稀奇古怪的问题。这里分享几个我踩过的坑和排查思路。6.1 事务不生效检查自动提交与连接池这是Spring Boot项目中一个非常常见的问题。开发者给方法加上了Transactional注解但更新操作就是没回滚。可能原因一默认自动提交。很多新手不知道在一些数据库驱动或连接池默认配置下autoCommit可能被设置为true。这意味着每条SQL语句都是一个独立的事务Transactional注解根本包裹不住它们。你需要确保在数据源配置中将默认自动提交关闭。可能原因二方法内部调用。Spring的声明式事务是基于AOP代理实现的。如果你在同一个类的一个非事务方法A内部直接调用了另一个有Transactional注解的方法B那么B方法的事务注解是不会生效的因为调用走的是this.B()而不是代理对象的B()。解决方法是将B方法放到另一个Service中或者使用AopContext.currentProxy()来获取当前代理对象再调用。可能原因三异常被捕获。Transactional默认只在遇到RuntimeException和Error时回滚。如果你在方法里捕获了异常 (try-catch) 却没有再抛出去或者抛出的异常是Exception而非RuntimeException事务也不会回滚。你需要检查异常类型或使用Transactional(rollbackFor Exception.class)来指定。6.2 慢查询突然增多可能是锁或资源瓶颈监控系统突然报警慢查询激增不要只盯着SQL本身。排查思路一检查锁竞争。使用SHOW ENGINE INNODB STATUS命令查看TRANSACTIONS部分观察是否有大量事务在等待锁。也可以用SELECT * FROM information_schema.INNODB_LOCKS;和SELECT * FROM information_schema.INNODB_LOCK_WAITS;来查看当前的锁和锁等待信息。很可能是一条大事务或设计不佳的更新语句持有了大量的行锁或间隙锁阻塞了其他查询。排查思路二检查系统资源。慢查询可能不是SQL的错。突然的流量高峰可能导致数据库服务器CPU、内存或磁盘IO饱和。使用top,vmstat,iostat等命令快速查看服务器负载。特别是磁盘IO如果awaitIO等待时间很高说明磁盘很忙再快的SQL也跑不动。排查思路三检查查询计划是否改变。有时候因为统计信息过时MYSQL优化器可能会为一个SQL选择了一个更差的执行计划。你可以使用EXPLAIN对比一下慢查询和正常时期的执行计划是否不同。如果不同可以考虑使用ANALYZE TABLE来更新表的统计信息或者使用FORCE INDEX来强制使用某个索引但这应是最后手段。6.3 连接数暴涨连接池配置与慢查询的蝴蝶效应应用出现“Too many connections”错误除了简单调高max_connections参数更要找到根源。根本原因往往是慢查询。一个执行时间很长的SQL会长时间占用一个数据库连接。如果这样的慢查询并发量稍高很快就会耗尽连接池。所以连接数暴涨通常是一个结果而不是原因。你需要立即去分析慢查询日志找到那些执行时间长、消耗资源多的SQL并尽快优化它们。检查连接池配置。应用层的数据库连接池如HikariCP, Druid配置不当也会导致问题。比如maximumPoolSize设置过大超过了数据库的max_connections。connectionTimeout设置过短在高负载时获取连接超时但应用不断重试雪上加霜。没有配置合理的空闲连接超时 (idleTimeout) 和最大生命周期 (maxLifetime)导致连接泄露或数据库端连接堆积。一个稳健的做法是连接池最大连接数应远小于数据库的最大连接数为系统监控、运维等预留空间。同时必须建立完善的慢查询监控和告警机制这是预防此类问题的关键。数据库的知识体系非常庞大一次面试不可能面面俱到。但只要你牢牢抓住“性能”索引、优化和“正确性”事务、锁这两条主线并能结合具体场景说出自己的理解和实践经验就能在面试中展现出扎实的功底和清晰的思路。记住面试官想看到的不是你背下了多少概念而是你如何运用这些知识去解决实际问题。
返回列表