【Java】Seata全局事务与本地事务的用法

Seata全局事务与本地事务的用法

Seata安装教程

安装教程

AT模式相关

  1. 在数据库本地事务隔离级别是读已提交(Read Committed)或以上的基础上,AT模式的默认全局隔离级别是读未提交(Read Uncommitted)。如果必须要求全局的读已提交,目前seata的方式是通过select for update语句的代理。SELECT FOR UPDATE 语句的执行会查询全局锁,如果全局锁被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。这个过程中,查询是被 block 住的,直到全局锁拿到,即读取的相关数据是已提交的,才返回。

  2. AT 会对写操作的 SQL 进行拦截,提交本地事务前,会向 TC 获取全局锁,未获取到全局锁的情况下,不能进行写,以此来保证不会发生写冲突:

  • 一阶段本地事务提交前,需要确保先拿到全局锁;
  • 拿不到全局锁,不能提交本地事务;
  • 拿全局锁的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。

当只有全局事务,内部没有本地事务的情况

表结构sql:

-- auto-generated definition
create table student
(
    urid int auto_increment
        primary key,
    code varchar(255) null,
    name varchar(255) null
);

代码示例:

package cn.itcast.user.service.impl;

import cn.itcast.user.mapper.StudentMapper;
import cn.itcast.user.pojo.Student;
import cn.itcast.user.service.SeataTestService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class SeataTestServiceImpl implements SeataTestService {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    @GlobalTransactional
    public void withoutLocalTransaction() throws InterruptedException {
        Student student = new Student();
        student.setCode("103");
        student.setName("0206");
        studentMapper.insert(student);

        // 模拟中间的一些业务操作
        Thread.sleep(1000);

        Student studentInDB = studentMapper.getStudentByCode("103");
        System.out.println("此时数据库中的数据:" + studentInDB);
        studentInDB.setName("2311");
        studentMapper.updateById(studentInDB);
        // 模拟中间的一些业务操作
        Thread.sleep(1000);
        studentInDB = studentMapper.getStudentByCode("103");
        System.out.println("修改后数据库中的数据:" + studentInDB);
    }
}

另外使用了一个新的请求来模拟中间的查询调用:

在这里插入图片描述

最后的日志结果全文如下:

02-06 23:32:38:646 DEBUG 1800 --- [nio-8081-exec-3] .s.i.h.TransactionPropagationIntercepter : xid in RootContext[null] xid in HttpContext[null]
02-06 23:32:38:647 DEBUG 1800 --- [nio-8081-exec-3] i.s.c.r.n.AbstractNettyRemotingClient    : offer message: timeout=60000,transactionName=withoutLocalTransaction()
02-06 23:32:38:647 DEBUG 1800 --- [Send_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:SeataMergeMessage timeout=60000,transactionName=withoutLocalTransaction()
, channel:[id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:38:651 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.TmNettyRemotingClient@8fc6ef9 msgId:42, body:MergeResultMessage xid=172.16.11.4:8091:366004859934097408;extraData=;

02-06 23:32:38:651 DEBUG 1800 --- [nio-8081-exec-3] io.seata.core.context.RootContext        : bind 172.16.11.4:8091:366004859934097408
02-06 23:32:38:651  INFO 1800 --- [nio-8081-exec-3] i.seata.tm.api.DefaultGlobalTransaction  : Begin new global transaction [172.16.11.4:8091:366004859934097408]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f9479cf] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@2153924d] will not be managed by Spring
==>  Preparing: INSERT INTO student ( code, name ) VALUES ( ?, ? )
==> Parameters: 106(String), 020600(String)
02-06 23:32:38:655 DEBUG 1800 --- [nio-8081-exec-3] i.s.c.r.n.AbstractNettyRemotingClient    : offer message: xid=172.16.11.4:8091:366004859934097408,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,lockKey=student:11
02-06 23:32:38:655 DEBUG 1800 --- [Send_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:SeataMergeMessage xid=172.16.11.4:8091:366004859934097408,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,lockKey=student:11
, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:38:658 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:46, body:MergeResultMessage BranchRegisterResponse: branchId=366004859967651840,result code =Success,getMsg =null

02-06 23:32:38:659 DEBUG 1800 --- [nio-8081-exec-3] i.s.r.d.undo.AbstractUndoLogManager      : Flushing UNDO LOG: {"@class":"io.seata.rm.datasource.undo.BranchUndoLog","xid":"172.16.11.4:8091:366004859934097408","branchId":366004859967651840,"sqlUndoLogs":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.undo.SQLUndoLog","sqlType":"INSERT","tableName":"student","beforeImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords","tableName":"student","rows":["java.util.ArrayList",[]]},"afterImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"student","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"urid","keyType":"PRIMARY_KEY","type":4,"value":11},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"code","keyType":"NULL","type":12,"value":"106"},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"name","keyType":"NULL","type":12,"value":"020600"}]]}]]}}]]}
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f9479cf]
02-06 23:32:41:257 DEBUG 1800 --- [nio-8081-exec-5] .s.i.h.TransactionPropagationIntercepter : xid in RootContext[null] xid in HttpContext[null]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4b70b320] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@5cca8640] will not be managed by Spring
==>  Preparing: select * from student where code = 106
==> Parameters: 
<==    Columns: urid, code, name
<==        Row: 11, 106, 020600
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4b70b320]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14f8f0f8] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@416739] will not be managed by Spring
==>  Preparing: select * from student where code = 106
==> Parameters: 
<==    Columns: urid, code, name
<==        Row: 11, 106, 020600
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14f8f0f8]
此时数据库中的数据:Student(urid=11, code=106, name=020600)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cd009e2] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@6de996f8] will not be managed by Spring
==>  Preparing: UPDATE student SET code=?, name=? WHERE urid=?
==> Parameters: 106(String), 2325(String), 11(Long)
02-06 23:32:43:733 DEBUG 1800 --- [nio-8081-exec-3] i.s.c.r.n.AbstractNettyRemotingClient    : offer message: xid=172.16.11.4:8091:366004859934097408,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,lockKey=student:11
02-06 23:32:43:733 DEBUG 1800 --- [Send_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:SeataMergeMessage xid=172.16.11.4:8091:366004859934097408,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,lockKey=student:11
, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:43:735 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:48, body:MergeResultMessage BranchRegisterResponse: branchId=366004881262133248,result code =Success,getMsg =null

02-06 23:32:43:736 DEBUG 1800 --- [nio-8081-exec-3] i.s.r.d.undo.AbstractUndoLogManager      : Flushing UNDO LOG: {"@class":"io.seata.rm.datasource.undo.BranchUndoLog","xid":"172.16.11.4:8091:366004859934097408","branchId":366004881262133248,"sqlUndoLogs":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.undo.SQLUndoLog","sqlType":"UPDATE","tableName":"student","beforeImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"student","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"urid","keyType":"PRIMARY_KEY","type":4,"value":11},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"code","keyType":"NULL","type":12,"value":"106"},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"name","keyType":"NULL","type":12,"value":"020600"}]]}]]},"afterImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"student","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"urid","keyType":"PRIMARY_KEY","type":4,"value":11},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"code","keyType":"NULL","type":12,"value":"106"},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"name","keyType":"NULL","type":12,"value":"2325"}]]}]]}}]]}
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cd009e2]
02-06 23:32:46:808 DEBUG 1800 --- [nio-8081-exec-4] .s.i.h.TransactionPropagationIntercepter : xid in RootContext[null] xid in HttpContext[null]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1dc57973] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@1b3aeffb] will not be managed by Spring
==>  Preparing: select * from student where code = 106
==> Parameters: 
<==    Columns: urid, code, name
<==        Row: 11, 106, 2325
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1dc57973]
02-06 23:32:48:658 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.n.AbstractNettyRemotingClient    : will send ping msg,channel [id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091]
02-06 23:32:48:658 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:services ping, channel:[id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:48:659 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.TmNettyRemotingClient@8fc6ef9 msgId:43, body:services pong
02-06 23:32:48:659 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.p.c.ClientHeartbeatProcessor     : received PONG from /127.0.0.1:8091
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@614c4ad4] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@2438f2e] will not be managed by Spring
==>  Preparing: select * from student where code = 106
==> Parameters: 
<==    Columns: urid, code, name
<==        Row: 11, 106, 2325
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@614c4ad4]
修改后数据库中的数据:Student(urid=11, code=106, name=2325)
02-06 23:32:48:784 DEBUG 1800 --- [nio-8081-exec-3] i.s.c.r.n.AbstractNettyRemotingClient    : offer message: xid=172.16.11.4:8091:366004859934097408,extraData=null
02-06 23:32:48:784 DEBUG 1800 --- [Send_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:SeataMergeMessage xid=172.16.11.4:8091:366004859934097408,extraData=null
, channel:[id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:48:786 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.TmNettyRemotingClient@8fc6ef9 msgId:45, body:MergeResultMessage globalStatus=Committed,ResultCode=Success,Msg=null

02-06 23:32:48:786 DEBUG 1800 --- [nio-8081-exec-3] io.seata.core.context.RootContext        : unbind 172.16.11.4:8091:366004859934097408 
02-06 23:32:48:786 DEBUG 1800 --- [nio-8081-exec-3] i.seata.tm.api.DefaultGlobalTransaction  : Suspending current transaction,xid = 172.16.11.4:8091:366004859934097408
02-06 23:32:48:786  INFO 1800 --- [nio-8081-exec-3] i.seata.tm.api.DefaultGlobalTransaction  : [172.16.11.4:8091:366004859934097408] commit status: Committed
02-06 23:32:48:789 DEBUG 1800 --- [nio-8081-exec-6] .s.i.h.TransactionPropagationIntercepter : xid in RootContext[null] xid in HttpContext[null]
02-06 23:32:48:791 DEBUG 1800 --- [nio-8081-exec-6] .s.i.h.TransactionPropagationIntercepter : xid in RootContext[null] xid in HttpContext[null]
02-06 23:32:49:077 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:10, body:xid=172.16.11.4:8091:366004859934097408,branchId=366004859967651840,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,applicationData=null
02-06 23:32:49:078  INFO 1800 --- [h_RMROLE_1_5_32] i.s.c.r.p.c.RmBranchCommitProcessor      : rm client handle branch commit process:xid=172.16.11.4:8091:366004859934097408,branchId=366004859967651840,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,applicationData=null
02-06 23:32:49:078  INFO 1800 --- [h_RMROLE_1_5_32] io.seata.rm.AbstractRMHandler            : Branch committing: 172.16.11.4:8091:366004859934097408 366004859967651840 jdbc:mysql://127.0.0.1:3306/gotest null
02-06 23:32:49:078  INFO 1800 --- [h_RMROLE_1_5_32] io.seata.rm.AbstractRMHandler            : Branch commit result: PhaseTwo_Committed
02-06 23:32:49:078 DEBUG 1800 --- [h_RMROLE_1_5_32] i.s.c.r.p.c.RmBranchCommitProcessor      : branch commit result:xid=172.16.11.4:8091:366004859934097408,branchId=366004859967651840,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null
02-06 23:32:49:078 DEBUG 1800 --- [h_RMROLE_1_5_32] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:xid=172.16.11.4:8091:366004859934097408,branchId=366004859967651840,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:49:079 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:11, body:xid=172.16.11.4:8091:366004859934097408,branchId=366004881262133248,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,applicationData=null
02-06 23:32:49:079  INFO 1800 --- [h_RMROLE_1_6_32] i.s.c.r.p.c.RmBranchCommitProcessor      : rm client handle branch commit process:xid=172.16.11.4:8091:366004859934097408,branchId=366004881262133248,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/gotest,applicationData=null
02-06 23:32:49:079  INFO 1800 --- [h_RMROLE_1_6_32] io.seata.rm.AbstractRMHandler            : Branch committing: 172.16.11.4:8091:366004859934097408 366004881262133248 jdbc:mysql://127.0.0.1:3306/gotest null
02-06 23:32:49:079  INFO 1800 --- [h_RMROLE_1_6_32] io.seata.rm.AbstractRMHandler            : Branch commit result: PhaseTwo_Committed
02-06 23:32:49:079 DEBUG 1800 --- [h_RMROLE_1_6_32] i.s.c.r.p.c.RmBranchCommitProcessor      : branch commit result:xid=172.16.11.4:8091:366004859934097408,branchId=366004881262133248,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null
02-06 23:32:49:079 DEBUG 1800 --- [h_RMROLE_1_6_32] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:xid=172.16.11.4:8091:366004859934097408,branchId=366004881262133248,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:49:823 DEBUG 1800 --- [AsyncWorker_1_1] i.s.r.d.undo.AbstractUndoLogManager      : batch delete undo log size 2
02-06 23:32:58:810 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.n.AbstractNettyRemotingClient    : will send ping msg,channel [id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091]
02-06 23:32:58:810 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:services ping, channel:[id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:58:810 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.TmNettyRemotingClient@8fc6ef9 msgId:46, body:services pong
02-06 23:32:58:811 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.p.c.ClientHeartbeatProcessor     : received PONG from /127.0.0.1:8091
02-06 23:32:59:106 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.r.n.AbstractNettyRemotingClient    : will send ping msg,channel [id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091]
02-06 23:32:59:106 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:services ping, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:32:59:107 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:49, body:services pong
02-06 23:32:59:107 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.r.p.c.ClientHeartbeatProcessor     : received PONG from /127.0.0.1:8091
02-06 23:33:08:829 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.n.AbstractNettyRemotingClient    : will send ping msg,channel [id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091]
02-06 23:33:08:829 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:services ping, channel:[id: 0xad179dd9, L:/127.0.0.1:54807 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:33:08:830 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.TmNettyRemotingClient@8fc6ef9 msgId:47, body:services pong
02-06 23:33:08:830 DEBUG 1800 --- [ctor_TMROLE_1_1] i.s.c.r.p.c.ClientHeartbeatProcessor     : received PONG from /127.0.0.1:8091
02-06 23:33:09:125 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.r.n.AbstractNettyRemotingClient    : will send ping msg,channel [id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091]
02-06 23:33:09:125 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : write message:services ping, channel:[id: 0x0107a5c3, L:/127.0.0.1:52087 - R:/127.0.0.1:8091],active?true,writable?true,isopen?true
02-06 23:33:09:126 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.rpc.netty.AbstractNettyRemoting    : io.seata.core.rpc.netty.RmNettyRemotingClient@cee3f84 msgId:50, body:services pong
02-06 23:33:09:126 DEBUG 1800 --- [ctor_RMROLE_1_1] i.s.c.r.p.c.ClientHeartbeatProcessor     : received PONG from /127.0.0.1:8091

能够明显的看到当内部没有本地事务的时候每个数据库操作都会是一个事务。

在这里插入图片描述

且在全局事务提交之前能够读取到数据库更新后的内容。

在这里插入图片描述

当内部嵌入本地事务的情况

to be continue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值