seata 分布式事务propagation为REQUIRES_NEW时,TransactionHook不会被调用

sqyvllje  于 4个月前  发布在  其他
关注(0)|答案(8)|浏览(105)
  • I have searched the issues of this repository and believe that this is not a duplicate.

Ⅰ. Issue Description

Ⅱ. Describe what happened

背景:同一条线程下,全局事务A调用了REQUIRES_NEW的全局事务B

问题:

  • B的TransactionHook会被正常调用
  • A的TransactionHook部分方法不会被调用中,包括:afterPrepare、beforeCommit、afterCommit、beforeRollback、afterRollback、afterCompletion

Ⅲ. Describe what you expected to happen

A、B全局事务的钩子都需要被正常回调

Ⅳ. How to reproduce it (as minimally and precisely as possible)

示例代码如下:

public void test() {
        TransactionHookManager.registerHook(aHook); //注册钩子A
        a(); //调用分布式事务A
    }
    
    @GlobalTransactional
    public void a() {
        TransactionHookManager.registerHook(bHook); //注册钩子B
        b(); //同一个线程调用分布式事务B
    }

    @GlobalTransactional(propagation = Propagation.REQUIRES_NEW)  // propagation为REQUIRES_NEW
    public void b() {
        //do something
    }

Ⅴ. Anything else we need to know?

Ⅵ. Environment:

问题分析:在B事务结束时,清理了所有的TransactionHook,具体代码如下(cleanUp这一行)。这个逻辑会把A事务的钩子也误清理了。

https://github.com/seata/seata/blob/e7fe7f821abf4c51c8e88f1e322624309cef656f/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java#L141-L146

exdqitrt

exdqitrt1#

问题存在,我认为应该把
private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>();
改为
private static final ThreadLocal<Map<String, TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>();
虽然是一个线程但是可以用xid区分开hook,每个xid都是一个新的全局事务

ev7lccsx

ev7lccsx3#

问题存在,我认为应该把 private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 改为 private static final ThreadLocal<Map<String, TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 虽然是一个线程但是可以用xid区分开hook,每个xid都是一个新的全局事务

深入考虑了下,在传播为REQUIRED、NOT_SUPPORTED等级别也是存在问题的。

关于Hook这块社区是否有考虑做成一个完整的特性?包括RM侧的监听器、全局配置监听器等这类比较实用的功能。

z4iuyo4d

z4iuyo4d4#

问题存在,我认为应该把 private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 改为 private static final ThreadLocal<Map<String, TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 虽然是一个线程但是可以用xid区分开hook,每个xid都是一个新的全局事务

深入考虑了下,在传播为REQUIRED、NOT_SUPPORTED等级别也是存在问题的。

关于Hook这块社区是否有考虑做成一个完整的特性?包括RM侧的监听器、全局配置监听器等这类比较实用的功能。

not support下是没有xid,就不会清除hook,改成上面按xid角度通知和清除应该没问题

llmtgqce

llmtgqce5#

问题存在,我认为应该把 private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 改为 private static final ThreadLocal<Map<String, TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 虽然是一个线程但是可以用xid区分开hook,每个xid都是一个新的全局事务

深入考虑了下,在传播为REQUIRED、NOT_SUPPORTED等级别也是存在问题的。
关于Hook这块社区是否有考虑做成一个完整的特性?包括RM侧的监听器、全局配置监听器等这类比较实用的功能。

not support下是没有xid,就不会清除hook,改成上面按xid角度通知和清除应该没问题

继承已有xid的情况,需要注意不能提前被清理。只有GlobalTransactionRole为Launcher时,才可以清理。

xmakbtuz

xmakbtuz6#

问题存在,我认为应该把 private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 改为 private static final ThreadLocal<Map<String, TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>(); 虽然是一个线程但是可以用xid区分开hook,每个xid都是一个新的全局事务

深入考虑了下,在传播为REQUIRED、NOT_SUPPORTED等级别也是存在问题的。
关于Hook这块社区是否有考虑做成一个完整的特性?包括RM侧的监听器、全局配置监听器等这类比较实用的功能。

not support下是没有xid,就不会清除hook,改成上面按xid角度通知和清除应该没问题

继承已有xid的情况,需要注意不能提前被清理。只有GlobalTransactionRole为Launcher时,才可以清理。

not support是先unbind的,理论上在执行hook相关功能不存在xid

1yjd4xko

1yjd4xko7#

rm侧后续会有hook或者listener提供,但不会让其影响分支事务的结果且不保证hook只执行一次

相关问题