公司网站建设需求说明书,烟台专业网站推广,新网站百度有审核期,怎样创建自己的网站一、场景概述
想象一个用户注册流程#xff1a;
保存用户基本信息#xff08;核心操作#xff09;初始化用户账户#xff08;重要但可独立失败#xff09;发送欢迎邮件#xff08;非关键操作#xff09; 二、代码事务传播分析
1. 主事务#xff1a;用户注册#xf…一、场景概述
想象一个用户注册流程
保存用户基本信息核心操作初始化用户账户重要但可独立失败发送欢迎邮件非关键操作 二、代码事务传播分析
1. 主事务用户注册REQUIRED Transactional(propagation Propagation.REQUIRED)
public void register(User user) {// 保存用户主事务操作userDao.save(user);// 初始化账户嵌套事务accountService.initAccount(user.getId());// 发送邮件非事务操作emailService.sendWelcomeEmail(user.getEmail());
}2. 子事务账户初始化NESTED
Transactional(propagation Propagation.NESTED)
public void initAccount(Long userId) {// 初始化账户操作
}三、事务传播机制详解
1. REQUIRED主事务
行为有则加入无则新建当前场景当register()被调用时 没有现有事务 → 创建新事务事务A所有操作都在事务A中执行
2. NESTED嵌套事务
行为在现有事务中创建嵌套事务关键特性 设置数据库保存点savepoint可独立回滚不影响主事务主事务回滚会连带回滚嵌套事务 四、场景执行分析
场景1完美流程全部成功
保存用户 → 成功初始化账户 → 成功发送邮件 → 成功提交主事务 → 所有操作生效
结果用户创建成功账户初始化完成邮件已发送
场景2账户初始化失败
保存用户 → 成功初始化账户 → 失败抛出异常捕获异常 → 记录日志发送邮件 → 成功提交主事务 → 仅保存用户操作生效
结果
✅ 用户创建成功❌ 账户初始化失败但被捕获✅ 邮件已发送
场景3主事务失败
保存用户 → 成功初始化账户 → 成功发送邮件前系统崩溃 → 主事务回滚
结果
❌ 用户创建回滚❌ 账户初始化回滚连带回滚❌ 邮件未发送
五、嵌套事务的本质
1. 数据库保存点Savepoint
START TRANSACTION; -- 主事务开始-- 主操作
INSERT INTO users (...) VALUES (...);SAVEPOINT sp1; -- 设置保存点-- 嵌套操作
INSERT INTO accounts (...) VALUES (...);-- 如果嵌套操作失败
ROLLBACK TO sp1; -- 回滚到保存点-- 继续其他操作...COMMIT; -- 提交主事务2. 嵌套事务特性
特性说明示例独立回滚嵌套事务可单独回滚账户初始化失败不影响用户保存依赖提交嵌套操作随主事务提交主事务成功才真正生效连带回滚主事务回滚导致嵌套回滚用户保存失败导致账户初始化回滚
六、为什么这样设计
1. 业务需求分析
操作重要性事务要求保存用户关键必须成功初始化账户重要但可重试可独立失败发送邮件非关键无需事务
2. 事务选择依据
REQUIRED主操作必须保证原子性NESTED重要但可失败的操作无事务非关键操作 七、对比其他传播行为
1. 如果使用REQUIRES_NEW
// 账户服务
Transactional(propagation Propagation.REQUIRES_NEW)
public void initAccount(Long userId) { ... }问题
账户初始化完全独立事务即使主事务回滚账户操作仍可能提交导致数据不一致用户不存在但账户存在
2. 如果使用SUPPORTS
// 账户服务
Transactional(propagation Propagation.SUPPORTS)
public void initAccount(Long userId) { ... }问题
没有独立事务控制账户失败会导致主事务回滚用户保存也会被回滚
八、最佳实践总结
1. 事务传播选择指南
场景推荐传播行为核心操作必须成功REQUIRED重要但可失败的操作NESTED非关键操作无事务或NOT_SUPPORTED完全独立操作REQUIRES_NEW
2. 嵌套事务使用要点
数据库支持MySQL InnoDB等支持保存点的引擎异常处理必须捕获嵌套事务异常性能考虑不宜嵌套过深业务对齐嵌套事务必须属于同一业务单元
九、扩展思考
1. 如果邮件服务需要事务
// 邮件服务
Transactional(propagation Propagation.NOT_SUPPORTED)
public void sendWelcomeEmail(String email) {// 记录邮件发送日志需要事务emailLogDao.save(new EmailLog(email));// 实际发送邮件emailClient.send(email);
}解决方案
Service
public class EmailService {// 邮件日志服务使用REQUIRES_NEWTransactional(propagation Propagation.REQUIRES_NEW)public void logEmail(String email) {emailLogDao.save(new EmailLog(email));}// 发送服务无事务public void sendWelcomeEmail(String email) {logEmail(email); // 独立事务记录日志emailClient.send(email); // 非事务操作}
}2. 多服务嵌套场景
public void register(User user) {userDao.save(user); // 主事务accountService.initAccount(user.getId()); // 嵌套事务profileService.initProfile(user.getId()); // 另一个嵌套事务
}处理原则
每个嵌套事务设置独立保存点分别捕获处理异常确保主事务不受影响
十、总结
在这个用户注册场景中我们通过合理的事务传播机制设计
REQUIRED 保证核心操作用户保存的原子性NESTED 处理重要但可失败的操作账户初始化无事务 执行非关键操作邮件发送
这种设计实现了
核心业务100%可靠重要业务可独立失败不影响主流程非关键业务不阻塞主事务 事务传播机制的本质是根据业务重要性为不同操作匹配合适的事务保证级别