读分片 0
在开启事务后 , 执行 SELECT * FROM tb1 WHERE id = 0 时 , 才会真正创建事务对象 。 根据事务与连接中的讨论 , 在 TConnection 中这条逻辑 SQL 的执行入口为 executeSQL , 里面会真正创建事务对象 , 主要执行逻辑为(代码出自 PolarDB-X 5.4.12 release 版本 , 为了方便说明 , 有删减及改动 , 下同):
// TConnection#executeSQL(ByteString Parameters TStatement ExecutionContext)public ResultSet executeSQL(ByteString sql Parameters params TStatement stmt ExecutionContext executionContext) throws SQLException { if (this.trx == null || this.trx.isClosed()) { // 开启事务后 , 直到执行第一条语句 , 才会创建事务对象 。beginTransaction();// 让 executionContext 引用 trx 对象 , 方便后续执行器通过 trx 对象拿物理连接 。executionContext.setTransaction(this.trx); resultCursor = executeQuery(sql executionContext trxPolicyModified);// TConnection#beginTransaction(boolean)private void beginTransaction(boolean autoCommit) { // 根据一些默认的或用户设定的事务变量 , 选择合适的事务策略 , 比如 TSO/XA 等 。trxPolicy = loadTrxPolicy(executionContext); TransactionClass trxConfig = trxPolicy.getTransactionType(autoCommit readOnly); // 根据事务策略 , 创建出对应的事务对象 。this.trx = transactionManager.createTransaction(trxConfig executionContext); 在我们的例子中 , 如果在上述代码打个断点 , 可以看到创建出来的是 TsoTransaction , 其中一些值得关注的变量为:
trx = {TsoTransaction // 此时还没有获取任何时间戳 。snapshotTimestamp = -1 commitTimestamp = -1 // 事务写的第一个物理分片(下称主分片) , 事务日志将会写在这个分片上 。primaryGroup = null // 该事务是否跨分片 , 如果是单分片事务 , 会优化为一阶段提交 。isCrossGroup = false // 事务日志管理器 , 负责写事务日志 。globalTxLogManager = {GlobalTxLogManager // 分布式事务的 connectionHolder 都是 TransactionConnectionHolder ,// 里面分别存储了读写连接 , 读连接和写连接在提交时行为会有所不同 。connectionHolder = {TransactionConnectionHolder // 物理分片到对应写连接的映射 。groupHeldWriteConn = {HashMap // 物理分片到对应读连接集合到映射 。 在 ShareReadView 优化开启时 ,// 可以同时存在多个读连接和一个写连接 , 因此这里读写连接需要分开管理 。// 该优化不在本文展开 。groupHeldReadConns = {HashMap 在执行器阶段 , 会选择给分片 0 下发一条 SELECT 语句 , 此时需要获取分片 0 的物理连接 , 代码入口是 MyJdbcHandler 中的 getPhyConnection(ITransaction ITransaction.RW String DataSource) 方法 。 其中的事务对象 Transaction 则是从 ExecutionContext 里拿到 。 该方法最后会调用 AbstractTransaction (这是所有分布式事务类的基类)中的 getConnection 方法 。
通过事务拿物理连接的代码 AbstractTransaction#getConnection 如下:
// AbstractTransaction#getConnection(String String IDataSource RW ExecutionContext)public IConnection getConnection(String schema String group IDataSource ds RW rw ExecutionContext ec) { if (/* 是事务的第一个写请求 */) { // 把这个分片作为主分片 , 事务日志将写在这个分片上 。this.primaryGroup = group; // 该分片还用于生成 XA 事务的 xid 。this.primaryGroupUid = IServerConfigManager.getGroupUniqueId(schema group);// 通过 connectionHolder 拿到物理连接 。IConnection conn = connectionHolder.getConnection(schema group ds rw); if (/* 是写请求 */!isCrossGroup!this.primaryGroup.equals(group)) { // 事务涉及了多个分片 。this.isCrossGroup = true;return conn; 在我们的例子中 , 上述参数 group 是物理分片 0 , rw 是 READ , 说明需要物理分片 0 上的读连接 , ds 则主要用于生成物理连接 。 由于我们只是读请求 , 因此分片 0 不会作为主分片 , 会直接返回 connectionHolder.getConnection(schema group ds rw) 的结果 。
相关经验推荐
- 空调|一步棋走错!苹果iPhone就有可能被停止销售
- ios15|苹果iOS 15.6正式版体验:4个核心修复,但续航未提升?
- 苹果|苹果官方降价的原因找到了,它也面临销量下滑乃至出现库存问题
- 华为|华为新款笔记本外观、价格对标苹果MAC系列,你会选谁?
- 苹果|今年下半年多款折叠屏手机即将发布,这两家值得期待
- 苹果|手机市场基本没翻过车的四个系列:新品或值得闭眼入
- 一加科技|下半年最值得期待的三大旗舰机,华为苹果一加Ace Pro纷纷上榜
- 芯片|在苹果的压力下,高通也无法挽救国产手机,芯片研发终于被重视
- 华为mate|花粉福利!鸿蒙3.0或与华为Mate 50系列同时到来,9月直接对刚苹果
- 苹果|苹果再次“煽动”中企外迁,这个问题再也压不住了