🚀 哈啰一面真题
题目来源
🔗 牛客网原帖链接 题目内容

题目截图
事务传播
事务传播行为(propagation behavior)指的是当一个事务方法被另一个事务方法调用时,这个事务方法应如何处理。
例如,Service A 里的一个事务方法调用 Service B 里的一个事务方法,通常有以下几种解决方案:
- 融入事务:直接去掉
serviceB中关于开启事务和提交事务的begin和commit,将其融入到serviceA的事务中(直接使用ServiceA的事务)。不过,B事务出错会导致A事务回滚。 - 挂起事务:若不想让
B事务的错误引发A事务回滚,可以开启两个连接,一个用于执行A,一个用于执行B,二者互不影响。执行到B时,将A挂起,新起连接执行B,B执行完后再唤醒A继续执行。 - 嵌套事务:在 MySQL 中,可通过给
B事务添加savepoint和rollback来模拟嵌套事务,把B设置成伪事务。
Spring 中的事务传播行为如下:
PROPAGATION_REQUIRED(需要):需要事务。若存在事务,就直接使用当前事务;若没有事务,则开启一个新事务。(若A存在事务,B融入A事务;若A没有事务,则为B新起一个事务)PROPAGATION_SUPPORTS(支持):支持A的事务。若存在事务,支持当前事务;若没有事务,则以非事务方式执行。(若A有事务,B融入;若A没有事务,B非事务执行)PROPAGATION_MANDATORY(强制性):强制必须有事务。若当前存在事务,使用该事务;若没有活动的事务,则抛出异常。(若A有事务,B融入;若A没有事务,则抛出异常)PROPAGATION_REQUIRES_NEW(需要新的):若已有事务存在,先将该事务挂起;若没有事务,则新起一个事务执行。(若A有事务,将A事务挂起,新开一个事务执行B,执行完后唤醒A继续执行;若A没有事务,则为B新起一个事务执行)PROPAGATION_NOT_SUPPORTED(不支持):不支持事务。总是以非事务方式执行,并挂起任何存在的事务。(若A有事务,挂起A,B非事务执行,执行完后唤醒A,A继续以事务形式执行)PROPAGATION_NEVER(从不):总是以非事务方式执行,若存在活动事务,则抛出异常。(若A有事务,则抛出异常)PROPAGATION_NESTED(嵌套的):若存在活动事务,则在嵌套事务中运行;若没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED属性执行。(若A有事务,B用savepoint方式嵌套在A中执行)
垃圾回收算法
- 标记清除: 先标记所有存活对象,然后清除未被标记的对象。
- 标记整理: 先标记所有存活对象,清除未被标记的对象,并将存活对象向内存一端移动,使它们连续存放,从而减少内存碎片。
- 复制: 将内存划分为两个等大的区域,每次只使用其中一个;标记存活对象后,将其复制到另一个区域,原区域整体清空。
新生代和老年代
新生代,大多对象都不会存活,使用复制算法 老年代, 大多对象都会存活,使用标记整理算法
分库分表
- 垂直
- 垂直分库: 比如说一个库中有用户表、积分表、订单表... 难以维护,让一个库就是一张表
- 每个数据库负责一个独立的业务域
- 垂直分表: 将一张宽表的字段按访问频率、数据大小或业务相关性进行拆分,形成多个子表,主键保持一致
- 将常用字段与不常用字段分离
- 垂直分库: 比如说一个库中有用户表、积分表、订单表... 难以维护,让一个库就是一张表
- 水平
- 水平分库: 将同一张表的数据按一定规则(如 hash、range、list 等)分散到多个数据库中,每个数据库包含该表的部分数据。
- 各库中表结构相同
- 水平分表: 在同一个数据库内部,将一张大表的数据按规则拆分成多个子表(partition),结构一致,数据分布不同。
- 不同于“分库”,所有子表都在同一个数据库中
- 是一种本地优化手段,不能解决单机容量瓶颈
- 水平分库: 将同一张表的数据按一定规则(如 hash、range、list 等)分散到多个数据库中,每个数据库包含该表的部分数据。
