这几天一直在做zbus和vue的项目前后端分离项目,现有两个服务:基础服务和预告服务,现在预告服务中的订单新增要调用基础服务中的日志模块来保存操作日志。但是调用完了就报错get global lock fail,获取不到全局锁,找遍官方和内部交流群,也不得要领。
调用方代码:
/**
* 提交订单(状态变更为已生效,不可编辑删除)
*
* @param id
* @return com.yorma.entity.YmMsg<com.yorma.cargo.entity.Order>
* @author chao.zhang
* @date 2020/7/16 16:00
**/
@GlobalTransactional
@Override
public YmMsg<Order> submitOrder(Long id) {
Order order = baseMapper.selectById(id);
if (isEmpty(order)) {
return YmMsg.error("订单不存在!");
}
order.setStatus("1"); // 设置已生效
/*提交订单保存操作日志*/
String token = RequestKit.getRequestIn().getHeader(HEADER_TOKEN);
String username = redisUtil.getStringToObject(PREFIX_USER_TOKEN_INFO + token, JSONObject.class)
.getString(USERNAME);
order.setUpdateBy(username);
order.setUpdateDate(new Date());
baseMapper.updateById(order);
PubOperateHistory operateHistory = new PubOperateHistory();
operateHistory.setLogTime(new Date());
operateHistory.setUser(username);
operateHistory.setType("Order");
operateHistory.setNote(Thread.currentThread().getStackTrace()[1].getMethodName());
operateHistory.setContent("提交订单,订单流水号:" + id);
operateHistory.setSourceId(id.toString());
CommonApi commonApi = rpc.createProxy("/basic/common", CommonApi.class);
// 客户端设置请求头
String tenantId = RequestKit.getRequestIn().getHeader(TENANT_ID);
Map<String, Object> headers = new HashMap<>();
headers.put(XID, RootContext.getXID());
headers.put(TENANT_ID, tenantId);
headers.put(HEADER_TOKEN, token);
RequestKit.setRequestHeaders(headers);
// RequestKit.copyHeaders(false, HEADER_TOKEN, TENANT_ID, XID);
commonApi.saveHistory(operateHistory);
Order o = baseMapper.selectById(id);
return YmMsg.ok(o);
}
结果方法执行完以后就会报get global lock fail异常,查询官方文档进行如下设置也无效果:
最后排查,是因为类上开启了本地事务,导致本地事务包着方法上的分布式全局事务导致的!!
将本地事务注释掉:@Transactional(rollbackFor = Exception.class),一切正常了!
附:我亲自做的事务测试:
2021-12-03补充:
很多人私信看不懂,我再补充几句:
此处注释掉的是类上的本地事务注解,正常开发很少会直接加到类上的,而是加到具体的需要事务的方法级别上的。因为类里的可能有查询方法,而查询方法是不需要开启事务的!