seata服务端启动需将registry.conf和file.conf置于conf目录并从根目录启动;spring boot集成需引入starter、启用seata.enabled且数据源被代理;globallock失败主因是并发更新同记录或sql无主键;undo_log不清理多因异步线程阻塞或表结构缺失字段。

Seata服务端启动失败:找不到registry.conf或file.conf
Seata服务端(seata-server)启动时默认在当前目录找配置,不是 classpath。很多人把配置文件丢进 resources/ 或打包进 jar,结果报错:Can't find config file: registry.conf。
正确做法是把 registry.conf 和 file.conf 放到 seata-server/conf/ 目录下(即和 seata-server.jar 同级的 conf 文件夹),并确保启动命令在 seata-server 根目录执行:
java -jar seata-server.jar -p 8091 -h 127.0.0.1
-
registry.conf决定注册中心类型(nacos、eureka、file),必须先配好; -
file.conf控制事务日志存储(store.mode=db时需填db.url、db.user); - 若用 Nacos,
registry.type = "nacos"后,registry.nacos.group默认是SEATA_GROUP,客户端也得对齐,否则注册不上。
Spring Boot项目集成@GlobalTransactional没生效
加了注解但事务不回滚,常见原因是没引入正确的 starter 或自动配置被跳过。
必须同时满足三个条件:
立即学习“Java免费学习笔记(深入)”;
- 依赖里有
seata-spring-boot-starter(注意不是旧版seata-all+ 手动配置); -
application.yml中显式开启:seata.enabled: true; - 数据源必须被
DataSourceProxy包装 —— starter 会自动代理标注了@MapperScan或使用DruidDataSource的 Bean,但如果用了 HikariCP 且没声明spring.datasource.type,可能漏掉代理。
验证是否生效:启动后看日志有没有输出 GlobalTransactionScanner register success;调用链路中出现 xid=xxx 字样。
GlobalLock 查询锁失败:Could not acquire lock
这是 AT 模式下典型的“写隔离”问题。Seata 在 update/delete 前会查一遍记录生成 undo log,再加全局锁。如果并发修改同一行,第二个事务会卡住或抛出该异常。
根本原因不是配置错,而是业务没做防重或没控制粒度:
- 避免在
@GlobalTransactional方法里做耗时查询或远程调用,拉长锁持有时间; - 更新语句必须带主键或唯一索引条件,否则 Seata 无法定位行,直接拒绝执行;
- MySQL 表引擎必须是
InnoDB,且事务隔离级别不能是READ_UNCOMMITTED; - 如果确实需要高并发更新同一条记录,考虑改用 TCC 模式,或在应用层加分布式锁(如 Redis),把 Seata 锁降级为最终一致性保障。
分支事务提交后,undo_log 表数据没清掉
正常情况下,分支事务成功后,Seata 会异步清理 undo_log 表里的记录。如果发现表越积越大,说明异步清理线程没跑起来,或者数据库连接池太小导致清理任务排队阻塞。
关键检查点:
-
file.conf中store.db.branch-async-commit-buffer-limit默认是 5000,设太小会导致频繁刷盘,设太大则延迟清理; - 确认
undo_log表有create_time和modify_time字段(Seata 1.5+ 要求),否则清理逻辑跳过; - MySQL 的
binlog_format必须是ROW,否则 Seata 解析 binlog 失败,影响 AT 模式下的快照生成和回滚。
清理不是实时的,只要没报错、没堆积到影响磁盘,不用强干预。真要手动清,只删 log_status = 1(已提交)且 modify_time 超过 7 天的记录。










