面试题答案
一键面试- 并发控制机制
- 锁机制:
- 共享锁(S锁)与排他锁(X锁):在读取数据时,使用共享锁,允许多个事务同时读取同一数据,保证查询的并发进行。当需要修改数据时,使用排他锁,阻止其他事务对数据的读写操作,保证数据一致性。对于B +树索引节点,在查询时可能加共享锁,在更新索引结构(如插入、删除数据导致索引调整)时加排他锁。
- 意向锁:分为意向共享锁(IS锁)和意向排他锁(IX锁)。当事务要在某行数据上加共享锁或排他锁时,会先在表级别加意向共享锁或意向排他锁。这样可以在锁申请时快速判断是否存在冲突,提高并发性能。例如,一个事务要在B +树某个叶子节点的某条记录上加排他锁,会先在表上加IX锁,其他事务若想在表上加X锁,通过判断表上已有IX锁,就知道存在冲突,无需再遍历整个B +树去检查具体记录的锁状态。
- MVCC(多版本并发控制):
- MySQL的InnoDB存储引擎使用MVCC来提高读写并发性能。MVCC在每行数据中保存两个隐藏列,一个是创建版本号,一个是删除版本号。当事务读取数据时,会根据自身的事务版本号和数据的版本号来判断是否可以读取。在B +树索引中,MVCC允许读操作不阻塞写操作,写操作也不阻塞读操作。例如,一个事务正在更新B +树中某个节点的数据,其他事务可以根据MVCC机制读取旧版本的数据,而无需等待更新事务完成,从而提高查询效率。
- 锁机制:
- 索引结构优化策略
- 非聚簇索引与聚簇索引:
- 聚簇索引:InnoDB表默认使用聚簇索引,数据行和主键索引存储在一起。这种方式对于按主键查询非常高效,因为可以直接定位到数据行。在高并发环境下,由于数据和索引紧密结合,减少了额外的I/O开销。例如,大量按主键的查询操作可以快速定位到数据,提高查询效率。
- 非聚簇索引:叶子节点存储的是主键值,当通过非聚簇索引查询时,需要先找到主键值,然后再通过主键去聚簇索引中查找数据行,称为回表操作。虽然多了一次I/O操作,但在一些场景下,如联合索引,可以通过覆盖索引(索引包含查询所需的所有列)避免回表,提高查询效率。同时,非聚簇索引在插入、删除数据时对索引结构的影响相对较小,减少了并发操作的代价。
- 索引设计原则:
- 最左前缀原则:对于联合索引,MySQL会按照索引定义的顺序从左到右匹配。在高并发查询场景下,合理设计联合索引的顺序可以提高查询效率。例如,如果经常有查询条件是
WHERE col1 = 'value1' AND col2 = 'value2'
,那么创建(col1, col2)
的联合索引可以充分利用索引,避免全表扫描。 - 选择性高的列优先:选择选择性(列中不同值的数量与总行数的比例)高的列先创建索引。这样在查询时可以快速过滤掉大量数据,提高查询效率。例如,对于性别列(只有男、女两种值)和身份证号列(基本唯一),身份证号列的选择性高,应优先考虑将其包含在索引中。
- 最左前缀原则:对于联合索引,MySQL会按照索引定义的顺序从左到右匹配。在高并发查询场景下,合理设计联合索引的顺序可以提高查询效率。例如,如果经常有查询条件是
- 非聚簇索引与聚簇索引:
- 缓存机制
- 查询缓存:MySQL早期版本有查询缓存,它会缓存查询语句和对应的结果。当相同的查询再次执行时,直接从缓存中返回结果,无需再次查询数据库和B +树索引,大大提高查询效率。但由于缓存的维护(如数据更新时需要更新缓存)开销较大,在高并发环境下可能会成为性能瓶颈,在MySQL 8.0版本中已默认禁用。
- InnoDB Buffer Pool:InnoDB存储引擎有一个Buffer Pool,用于缓存索引页和数据页。在高并发读写场景下,经常访问的B +树索引页会被缓存到Buffer Pool中,后续的查询和更新操作可以直接在内存中进行,减少磁盘I/O。例如,当一个事务要查询B +树中某个节点的数据时,如果该节点所在的页已经在Buffer Pool中,就可以直接从内存中读取,提高查询效率。同时,Buffer Pool采用LRU(最近最少使用)算法管理缓存,将长时间未使用的页淘汰出缓存,为新的页腾出空间。