MyBatis 相关面试题整理 更新中 

Mybatis 执行流程 mybatis-config.xml (总规) ↓ SqlSessionFactory (总管) ↓ SqlSession (服务员) —— 包含所有执行方法 ↓ Executor (大管家) —— 优先查缓存(一级/二级) ↓ MappedStatement (菜谱) —— 持有SQL、参数映射、结果映射 ↓ 输入参数映射 (备菜) → JDBC执行 → 输出结果映射 (装盘) ↓ 返回POJO/集合 (上菜) Mybatis 是否支持延迟加载 支持,默认不开启 collection fecthType=“lazy” mybatis配置文件延迟加载 lazyLoadingEnabled 延迟加载的原理 CGLIB创建目标对象的代理对象 调用目标方法 getOrderList 调用对象 invoke 方法 判断 orderList 是否为空 为空,执行SQL 不为空获取结果 封装 orderList Mybatis 的一级缓存 二级缓存 用过吗 本地缓存 - 基于 PerpetualCache 本质是一个 HashMap 一级缓存 - 作用域是 session 级别 二级缓存 - 作用域是namespace 和 mapper的作用域,不依赖于 session 二级缓存默认关闭 settings name=“cacheEnabled” value=“true” 当某个作用域进行了增删改操作,该作用域下的所有select的缓存将被clear

2026-07-15 12:46:10 AM · 1 分钟

Redis 相关面试题整理 更新中 

你的项目的哪些场景使用了 redis 如果发生了缓存击穿、穿透、雪崩如何解决 redis 作为缓存, mysql的数据如何与redis进行同步? 先介绍业务,看看业务符合什么场景 一致性较高场景 双写一致 读 写 | 延迟双删 分布式锁 读多写少 共享锁 排它锁 允许延迟一致 介绍一下你的异步方案 允许延时一致的业务,采用异步通知 MQ消息中间件 Canal中间件 强一致性(Redisson读写锁) 共享锁 阻塞写操作 排它锁 阻塞读和写操作 Redis作为缓存,数据的持久化是怎么做的? RDB save bgsave AOF RDB 的执行原理? fork主进程得到子进程 子进程共享主进程的内存数据(复制页表) copy-on-write AOF 的执行原理 配置项 always everysec no 重写触发 bgrewriteaof RDB 和 AOF 对比 持久化方式 数据完整性 文件大小 宕机恢复速度 数据恢复优先级 系统资源占用 使用场景 redis 的key过期了会立即删除吗 惰性删除 定期删除 SLOW(10hz) FAST Redis的过期策略:惰性删除+定期删除 配合使用 Redis 数据淘汰策略 noeviction volatile-ttl allkeys-random volatile-random allkeys-lru volatile-lru allkeys-lfu volatile-lfu 数据库有1000万数据,redis只能缓存20万,如何保证redis中的数据都是热点数据? 使用 allkeys-lru ...

2026-07-15 12:46:10 AM · 1 分钟

消息中间件 面试题整理 更新中 

消息队列通识 为什么需要消息队列 解耦 削峰填谷 异步调用 消息队列如何保持幂等 重复源泉 生产端重发 发送ACK没有回复继续发送 消费端重复 解决方案 唯一消息ID,生产者发送时携带messageId 幂等表 状态机校验 乐观锁 / 版本号 分布式锁 核心原则 消费逻辑天然幂等 为什么需要消息队列 解耦 异步 削峰 消息队列的模型有哪些 点对点模型 发布订阅模型 如何保证消息不丢失 生产端 ack broker 持久化 生产环境副本因子 >= 3 消费端 手动提交 offset 如何保证消息有序 让需要保持有序的消息落到同一个分区 给唯一的key,且key以后不会重复 Kafka保证唯一分区内有序,跨分区无序 RabbitMQ RabbitMQ 如何保证消息不丢失 哪些情况会丢失 publisher -> exchange 生产者确认机制 ack publish-confirm nack publish-confirm ack publish-return 消息失败之后如何处理 回调方法 记录日志 保存到数据库中然后定时重发 exchange -> queue 消息持久化 交换机持久化 队列持久化 消息持久化 queue queue -> consumer 消费者确认机制 RabbitMQ 消息的重复消费问题是如何解决的 重复消费的原因 ...

2025-03-23 01:21:54 PM · 2 分钟

Spring Cloud 面试题整理 更新中 

SpringCloud 问题 springcloud 五大组件 Eureka / nacos Ribbon Feign / dubbo Hystrix / sentinel Zuul/Gateway 服务注册和发现是什么意思,SpringCloud 如何实现服务注册和发现? nacos 和 eureka 的区别? 相同点 服务提供者 注册 服务信息 到 注册中心 服务消费者 定时从 注册中心 拉取 服务消费者 对 服务提供者 进行远程调用 服务提供者 临时实例 采用心跳检查 什么是临时实例? 默认实例都是临时实例 临时实例心跳模式 非临时主动探测 临时实例没有心跳会被剔除 非临时不会被剔除 ephemeral: false 变成非临时实例 非临时实例,nacos会主动询问服务提供者是否存活 不同点 非临时实例 nacos集群AP,如果存在非临时实例,采用CP eureka采用AP nacos还有配置中心 你们项目中负载均衡是如何实现的? Ribbon Ribbon 负载均衡流程 微服务发起请求 Ribbon 从注册中心拉取 根据策略进行转发 Ribbon 负载均衡策略有哪些? RoundRobinRule 简单轮询 WeightedResponseTimeRule 按照权重来选择服务器,响应时间越长,权重越小 RandomRule BestAvailableRule 忽略短路的服务器,选择并发数较低的服务器 RetryRule 重试机制的选择逻辑(基于轮询) AvailabilityFilteringRule 可用性敏感策略。先过滤非健康的,再选择连接数比较小的 ZoneAvoidanceRule 以区域可用的服务器为基础对服务器选择。 如果想自定义负载均衡策略,如何实现? 自己创建类实现 IRule 接口, 再通过配置类或配置文件配置 @Bean IRule 全局生效 NFLoadBalancerRuleClassName 局部生效 什么是服务雪崩?如何解决这个问题? 服务雪崩 一个服务失败,导致整条链路都失败的情形 解决方案 降级(接口) Feign 接口走fallback 熔断(整个服务) Hystix @EnableCircuitBreaker 断路器关闭 - 打开 - 半开 你们的微服务是怎么监控的? skywalking apache顶级项目 问题定位 性能分析 服务关系 服务告警 业务相关 项目中有没有做过限流?怎么做的? 限流情况 ...

2025-02-23 01:20:18 PM · 2 分钟

Java 面试题整理 更新中 

集合 为什么数组索引要从 0 开始?从 1 开始不行吗? 回答大纲 数组在内存中是连续存储的,CPU 通过寻址公式访问元素 从 0 开始:a[i]_address = base_address + i * typeSize 从 1 开始:base_address + (i-1) * typeSize,多一次减法 正式回答 数组在内存中是连续存储的,CPU 通过寻址公式来访问指定下标的元素:a[i] 的地址 = 数组首地址 + i * 元素大小。当数组下标从 0 开始时,直接套用上述公式即可计算偏移量;如果下标从 1 开始,则需要先执行 i - 1 再做乘法,多了一次减法运算。虽然单次访问的差异可以忽略不计,但数组通常会出现在循环、遍历等高频访问的场景中,这笔额外开销会被无限放大。这也是 C 语言沿用下来的历史约定,Java 作为一门追求高效的系统级语言,继承了这一设计。 时间复杂度如何计算的? 回答大纲 口诀:常 对 幂 指 阶 常见复杂度 常数复杂度 O(1):不随 n 变化 对数复杂度 O(logN):二分查找、树操作 正式回答 时间复杂度用于衡量算法执行时间随数据规模 n 增长的变化趋势,是大 O 表示法下对最坏情况的抽象描述。常见的大小关系可用口诀"常对幂指阶"来记忆,即 O(1) < O(logN) < O(N) < O(N*logN) < O(N²) < O(2ⁿ) < O(n!),越靠后算法越慢。 ...

2025-01-23 08:50:54 AM · 21 分钟

Spring 面试题整理 更新中 

面试题从互联网各个角落收集而来 谈一谈 Spring IOC 的底层实现? 反射 工厂的价值 设计模式 关键的几个方法 createBeanFactory getBean doGetBean createBean doCreateBean createBeanInstance(getDeclaredConstructor, newInstance)「方案选单」 populateBean flowchart TD A[开始] --> B["createBeanFactory()创建 DefaultListableBeanFactory"] B --> C[加载 BeanDefinition解析 XML/注解] C --> D["getBean(beanName)外部调用入口"] D --> E["doGetBean(beanName)"] E --> F{从缓存获取单例?} F -->|是| G[返回缓存的 Bean] F -->|否| H["createBean(beanName, mbd)"] H --> I["doCreateBean(beanName, mbd)"] I --> J["createBeanInstance()getDeclaredConstructor + newInstance"] J --> K["populateBean()属性填充/依赖注入"] K --> L["initializeBean()初始化回调"] L --> M[注册销毁方法] M --> N[返回完整 Bean 实例] 谈谈 SpringIOC 的理解,原理和实现? IOC 思想 DI 实现手段 什么是容器 什么是Bean BeanDefination 从哪里读 XML 注解 存哪里 所有 BeanDefinition 都存在 DefaultListableBeanFactory 里的一个 Map 中 容器的生命周期 flowchart TD START([🚀 程序启动]) --> REFRESH["AbstractApplicationContext.refresh()"] REFRESH --> PHASE1 subgraph PHASE1["🔵 第一阶段:准备工作"] direction TB A1["prepareRefresh()\n记录启动时间\n设置容器状态为「活跃」\n初始化环境变量"] --> A2 A2["obtainFreshBeanFactory()\n创建 DefaultListableBeanFactory\n这是容器的核心仓库"] --> A3 A3["prepareBeanFactory()\n注册基础 BeanPostProcessor\n注册 Aware 相关处理器\n注册默认环境 Bean(environment)"] end PHASE1 --> PHASE2 subgraph PHASE2["🟢 第二阶段:加载 BeanDefinition(读图纸)"] direction TB B1["扫描 @ComponentScan 指定的包\n或读取 XML 配置文件"] --> B2 B2["解析注解 / XML\n识别 @Component @Service\n@Repository @Controller @Bean"] --> B3 B3["为每个 Bean 生成 BeanDefinition\n记录:类名、作用域、是否懒加载\n初始化方法、销毁方法、依赖关系"] --> B4 B4[("存入 beanDefinitionMap\nkey = beanName\nvalue = BeanDefinition")] end PHASE2 --> PHASE3 subgraph PHASE3["🟡 第三阶段:修改 BeanDefinition(修图纸)"] direction TB C1["invokeBeanFactoryPostProcessors()\n执行所有 BeanFactoryPostProcessor"] --> C2 C2["ConfigurationClassPostProcessor\n处理 @Configuration @Import\n@PropertySource @ComponentScan\n👉 SpringBoot 自动装配在此触发"] --> C3 C3["PropertySourcesPlaceholderConfigurer\n替换 BeanDefinition 中\n所有 ${xxx} 占位符为真实值"] --> C4 C4[/"所有 BeanDefinition 最终确定\n图纸不再变动"/] end PHASE3 --> PHASE4 subgraph PHASE4["🌸 第四阶段:注册 BeanPostProcessor(工人就位)"] direction TB D1["registerBeanPostProcessors()\n按优先级顺序注册\nPriorityOrdered → Ordered → 普通"] --> D2 D2["AutowiredAnnotationBeanPostProcessor\n负责处理 @Autowired @Value"] --> D3 D3["CommonAnnotationBeanPostProcessor\n负责处理 @PostConstruct @PreDestroy @Resource"] --> D4 D4["AnnotationAwareAspectJAutoProxyCreator\n负责检测切面、生成 AOP 代理对象"] --> D5 D5[/"所有工人就位\n等待 Bean 创建时介入\n此时不开工"/] end PHASE4 --> PHASE5 subgraph PHASE5["🟣 第五阶段:容器基础设施初始化"] direction TB E1["initMessageSource()\n初始化国际化资源 i18n"] --> E2 E2["initApplicationEventMulticaster()\n初始化事件广播器"] --> E3 E3["onRefresh()\n⭐ SpringBoot 在此启动\nTomcat / Jetty / Undertow\nWeb 容器开始监听端口"] --> E4 E4["registerListeners()\n注册所有 ApplicationListener\n监听容器事件"] end PHASE5 --> PHASE6 subgraph PHASE6["🟠 第六阶段:实例化所有单例 Bean"] direction TB F1["finishBeanFactoryInitialization()\npreInstantiateSingletons()\n遍历所有非懒加载单例 BeanDefinition"] --> F2 F2["逐个执行 getBean()\n触发每个 Bean 的生命周期\n实例化 → 属性填充 → Aware回调\n→ 前置处理 → init方法 → 后置处理"] --> F3 F3[("所有单例 Bean 存入\nsingletonObjects 一级缓存\n✅ 全部就绪")] end PHASE6 --> PHASE7 subgraph PHASE7["✅ 第七阶段:容器就绪"] direction TB G1["finishRefresh()\n清理启动时占用的资源\n初始化生命周期处理器"] --> G2 G2["发布 ContextRefreshedEvent\n通知所有监听者:容器启动完成"] --> G3 G3[/"容器进入运行状态\n可以处理业务请求"/] end G3 --> RUNNING([🎉 容器正常运行中]) RUNNING -.->|"收到关闭信号\nCtrl+C / kill / close()"| PHASE8 subgraph PHASE8["🔴 第八阶段:容器销毁"] direction TB H1["发布 ContextClosedEvent\n通知所有监听者:容器即将关闭"] --> H2 H2["停止 Web 容器\nTomcat 停止接受新请求"] --> H3 H3["执行所有 Bean 的销毁逻辑\n@PreDestroy → destroy() → destroy-method\n按注册顺序逆序销毁"] --> H4 H4["清空所有缓存\nsingletonObjects 清空\nbeanDefinitionMap 清空"] --> H5 H5["容器状态设置为「关闭」\nactive = false / closed = true"] end H5 --> END([💀 容器销毁完成]) style START fill:#43A047,color:#fff style RUNNING fill:#43A047,color:#fff style END fill:#e53935,color:#fff style REFRESH fill:#1E88E5,color:#fff bean 的生命周期 flowchart TD START([🌱 开始创建 Bean]) --> A A["① 实例化\nInstantiation\n反射调用构造方法\nnew 出空壳对象\n此时所有字段都是 null"] --> B B["② 放入三级缓存\nsingletonFactories\n提前暴露半成品\n为循环依赖做准备"] --> C C["③ 属性填充\npopulateBean()\n处理 @Autowired @Value\n把依赖的 Bean 注入进来"] --> D subgraph AWARE["④ Aware 回调"] direction TB D["BeanNameAware\n告诉 Bean 自己叫什么名字"] --> E E["BeanFactoryAware\n把 BeanFactory 塞给 Bean"] --> F F["ApplicationContextAware\n把 ApplicationContext 塞给 Bean"] end subgraph INIT["⑤ 初始化 initializeBean()"] direction TB G["前置处理\npostProcessBeforeInitialization()\n所有 BeanPostProcessor 挨个执行\n📌 @PostConstruct 在这里被调用"] --> INITMETHOD subgraph INITMETHOD["init 方法(按顺序执行)"] direction TB H1["第1个:@PostConstruct\n(已在前置处理中执行)"] --> H2 H2["第2个:afterPropertiesSet()\n实现 InitializingBean 接口"] --> H3 H3["第3个:init-method\n@Bean(initMethod='xxx') 或 XML 配置"] end INITMETHOD --> I I["后置处理\npostProcessAfterInitialization()\n所有 BeanPostProcessor 挨个执行\n⭐ AOP 代理在这里生成"] end AWARE --> INIT I --> J subgraph CACHE["⑥ 存入缓存"] direction TB J["从三级缓存 singletonFactories 移除\n从二级缓存 earlySingletonObjects 移除"] --> K K["存入一级缓存 singletonObjects\n✅ 完整 Bean 就绪"] end K --> READY([🎉 Bean 可以正常使用了]) READY -.->|"容器关闭"| DESTROY subgraph DESTROY["⑦ 销毁阶段(容器关闭时)"] direction TB D1["第1个:@PreDestroy\n方法被调用"] --> D2 D2["第2个:destroy()\n实现 DisposableBean 接口"] --> D3 D3["第3个:destroy-method\n@Bean(destroyMethod='xxx') 或 XML 配置"] end D3 --> END([💀 Bean 销毁完成]) spring 三级缓存依赖流程 sequenceDiagram participant Spring as Spring容器 participant L3 as 三级缓存singletonFactories participant L2 as 二级缓存earlySingletonObjects participant L1 as 一级缓存singletonObjects Note over Spring: 开始创建 A Spring->>Spring: ① new A 空壳对象 Spring->>L3: ② 存入 A 的 ObjectFactory lambda Note over Spring: 给 A 注入属性,发现需要 B Spring->>Spring: ③ new B 空壳对象 Spring->>L3: ④ 存入 B 的 ObjectFactory lambda Note over Spring: 给 B 注入属性,发现需要 A Spring->>L1: ⑤ getBean(A),查一级缓存 L1-->>Spring: ❌ 没有 Spring->>L2: 查二级缓存 L2-->>Spring: ❌ 没有 Spring->>L3: 查三级缓存 L3-->>Spring: ✅ 找到 A 的 lambda! Spring->>Spring: ⑥ 执行 lambda(需要代理则生成代理 A) Spring->>L2: ⑦ 早期引用放入二级缓存 Spring->>L3: 删除三级缓存中的 A Note over Spring: B 拿到 A 的早期引用,B 完成初始化 Spring->>L1: ⑧ B 放入一级缓存 ✅ Spring->>L3: 删除三级缓存中的 B Note over Spring: 回到 A 的流程,B 已就绪,A 完成初始化 Spring->>L1: ⑨ A 放入一级缓存 ✅ Spring->>L2: 删除二级缓存中的 A Note over L1: 最终:一级缓存中有完整的 A 和 B ✅ 情况 三级缓存 lambda 执行 二级缓存 无循环依赖,无 AOP 存了 lambda ❌ 不执行 不经过 无循环依赖,有 AOP 存了 lambda ❌ 不执行 不经过 有循环依赖,无 AOP 存了 lambda ✅ 执行 存原始对象 有循环依赖,有 AOP 存了 lambda ✅ 执行 存代理对象 spring bean 缓存的放置时间和删除时间 Spring Bean 三级缓存的放置与删除时间 缓存 存的是什么 放入时机 删除时机 三级 singletonFactories Bean 的工厂 lambda 实例化完成后立刻放入 工厂被调用时(升级到二级)或 Bean 完成时 二级 earlySingletonObjects 早期暴露的半成品 Bean 三级工厂被调用的瞬间 Bean 完全初始化完成放入一级时 一级 singletonObjects 完整可用的 Bean 初始化全部完成后 容器关闭销毁时 BeanFactory 和 FactoryBean 的区别? FactoryBean 是什么 public interface FactoryBean<T> { // 返回 Bean 的实例(可以是复杂创建逻辑) T getObject() throws Exception; // 返回 Bean 的类型 Class<?> getObjectType(); // 是否单例 default boolean isSingleton() { return true; } } 相同点 都是用来创建Bean对象的 不同点 使用 BeanFactory 创建对象的适合必须遵循严格的生命周期流程,太复杂了。如果想简单自定义某个对象的创建,同时想交给spring管理,那么必须实现 FactoryBean 接口 isSingleton 是否是单例对象 getObjectType 获取返回对象的类型 getObject 自定义创建对象的过程 对比维度 BeanFactory FactoryBean 角色 容器/工厂接口 特殊的 Bean 功能 管理所有 Bean 的生命周期 自定义某个 Bean 的创建逻辑 定位 基础设施(IOC 容器) 业务扩展(创建复杂对象) 使用方式 由 Spring 框架实现和使用 由开发者实现,注册到容器中 常见实现 DefaultListableBeanFactory SqlSessionFactoryBean、ProxyFactoryBean 谁创建谁 BeanFactory 创建并管理 FactoryBean FactoryBean 创建业务对象 flowchart LR subgraph BeanFactory[BeanFactory - IOC容器] direction LR Bean1[普通 Bean] Bean2[普通 Bean] FB[FactoryBean特殊 Bean] end FB -->|调用 getObject| Result[业务对象] User[开发者] -->|getBean| BF[BeanFactory] BF -->|返回| Bean1 BF -->|返回| Bean2 BF -->|返回 getObject 结果| Result BF -->|加 & 前缀| FB Spring中用到的设计模式 单例模式 原型模式(指定作用域为prototype) 工厂模式 BeanFactory 模板方法 JdbcTemplate TransactionTemplate RestTemplate RedisTemplate 策略模式 XmlBeanDefinitionReader PropertiesBeanDefinitionReader 观察者模式 listener event multicast 适配器模式 HandlerAdapter 装饰者模式 BeanWrapper 责任链模式 使用aop的时候会先生成一个拦截器链 SpringMVC 的filter责任链 代理模式 动态代理 委托者模式 delegate Spring AOP 底层实现原理 🥇 第一层:一句话定性(开场) “Spring AOP 的底层本质是动态代理。Spring 在容器初始化 Bean 的时候,通过 BeanPostProcessor 机制拦截,判断这个 Bean 是否需要被增强,如果需要,就用动态代理生成一个代理对象,替换掉原始 Bean 注册进容器。后续所有对这个 Bean 的调用,实际上都是在走代理对象。” ...

2024-10-19 11:19:24 PM · 8 分钟

MySQL 面试题整理 更新中 

面试题从互联网各个角落收集而来 如何定位慢查询? 方案1 开源工具 Arthas 运维工具 Prometheus Skywalking 方案2 MySQL自带慢日志(mysql性能损耗) 开启慢日志方法 /etc/my.conf slow_query_log long_query_time SQL语句执行很慢,如何分析 慢的原因 聚合查询 多表查询 表数据量过大查询 深度分页查询 如何分析慢 explain, desc 命令 如何分析执行结果? extra 的额外优化建议 using where; using index 查找使用了索引,需要的数据在索引列都能找到,不需要回表查询数据 using index condition 查找使用了索引 type index,all 需要优化 了解过索引吗?什么是索引? 索引(index)是帮助 MySQL 高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构(如 B+ 树),这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。 帮助MySQL高效获取数据的数据结构 索引的底层数据结构了解过吗? 二叉搜索树 红黑树 B树 B+树 阶数更多,路径更短 磁盘读写代价B+树更低,叶子节点才能真正存储数据 便于扫库和区间查询,叶子节点是双向链表 什么是聚簇索引?什么是非聚簇索引? 聚簇索引 二级索引 什么是回表查询? 知道什么是覆盖索引吗? 通过该索引查询能够一次找到所有数据,且无需回表的,就是覆盖索引 MySQL超大分页怎么处理? 使用覆盖索引加上子查询 select * from tb_sku t, (select id from tb_sku order by id limit 9000000,10) a where t.id = a.id 索引创建的原则有哪些? 单表超过10万条数据且查询比较频繁的表建立索引 常常作为查询条件的字段要建立索引 使用区分度高的列作为索引,尽量建立唯一索引 字符串类型的字段长度较长可以建立前缀索引 尽量使用联合索引,减少单列索引 索引列使用NOT NULL方便优化器确定哪个索引更好用于查询 什么情况下索引会失效? 违反了最左前缀法则 查询范围右边的列,不能使用索引 索引列上进行运算操作,索引列失效 字符串不加单引号,索引失效(索引类型转换导致的失效) 字符串非尾部匹配,索引失效 谈一谈对SQL优化的经验 表设计优化 我们参考了 阿里开发手册《嵩山版》 根据实际存储数值长短设计数据类型 索引的优化 SQL语句的优化 select 语句务必指明字段名称 为了覆盖索引 尽量用 union all 代替 union 避免对 where 子句中对字段进行表达式操作 能用 innerjoin 就不用 left join , right join。如必须,要以小表为驱动 主从复制,读写分离 分库分表 事务的特性详细说一说 并发事务带来哪些问题,如何解决这些问题?MySQL的默认隔离级别是? 并发事务的问题 脏读 读已提交 不可重复读 值问题 可重复读 幻读 数量问题 串行化 隔离级别 未提交读 读已提交 可重复读* 串行化 undo log 和 redo log 的区别 缓冲池 数据页 redo log 物理 持久 undo log 逻辑 原子 一致 事务的隔离性底层是如何保证的? 锁:排他锁 MVCC 多版本并发控制 依赖于 隐式字段 DB_TRX_ID DB_ROLL_PTR DB_ROW_ID undo log 版本链 版本链数据访问规则 readview 快照读 Read Committed 每次 select都生成一个快照读 Repeatable Read 开启事务后第一个 select 语句才是快照读的地方 核心字段 m_ids min_trx_id max_trx_id creator_trx_id RC隔离级别下,在事务中每次执行快照读时生成 ReadView MySQL 的主从同步原理 核心:二进制日志 BINLOG DDL DML 主数据库在事务提交时,变更记录写入 Binlog 从库 binlog -> 中继日志 从库 中继日志读取事件 -> 从库数据库 你们项目用过分库分表吗? 什么时候分库分表 单表数据量达到1000W 或者 20GB 优化解决不了性能问题 IO、CPU瓶颈 如何拆分 垂直拆分 垂直分库 不同表拆分到不同库 适用于微服务 垂直分表 不常用字段单独放在一张表 水平拆分 水平分库 一个库的数据拆分到多个库中 路由规则 根据id节点取模 按id范围路由 水平分表 一个表的数据拆分到多个表中 新的问题 分布式事务一致性问题 跨节点关联查询 跨节点分页、排序函数 主键去重 解决方案 分库分表中间件 mycat sharding-sphere 深入问题 为什么 InnoDB 主键建议自增? 为什么非自增主键会导致页分裂? 为什么 MyISAM 和 InnoDB 索引结构不同? 为什么 B+树适合磁盘而红黑树不适合?

2024-09-19 11:19:24 PM · 2 分钟