VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • [zebra源码]如果定位到多个分库或分表怎么执行的?

假设分库分表情况如下

  • 分库 id0:分表  test_0 、 test_1
  • 分库 id1:   分表  test_2、  test_3

sql语句: select test.* from test

一、路由结果

DefaultRouter#router 路由出来的结果两个 RouterResult, 每个里边有多个分表的sql, 即所有分库下的所有test分表


	
 
dbName: id0
 
sqls:
 
- SELECT test_0.* \nFROM test_0
 
- SELECT test_1.* \nFROM test_1
 
 
 
dbName: id1
 
sqls:
 
- SELECT test_2.* \nFROM test_2
 
- SELECT test_3.* \nFROM test_3

二、执行过程

如果路由定位到多个分库,会根据并发度n,将每个分库的sql语句 拆分成n个任务,放入线程池执行 默认单库并发度 concurrentLevel = 1, 执行过程为

(1) 执行分库id0里各分表的sql

  • 从分库id0 对应的数据源中一个数据连接,创建 (SELECT test_0.* \nFROM test_0)的 statement
  • 从分库id0 对应的数据源中一个数据连接,创建l (SELECT test_1.* \nFROM test_1 )的statement
  • 把这两个statement包裹到一个线程task中

(2) 执行分库id1里各分表的sql

  • 从分库id1 对应的数据源中一个数据连接,创建 (SELECT test_2.* \nFROM test_2 ) 的statement
  • 从分库id1 对应的数据源中一个数据连接,创建l (SELECT test_3.* \nFROM test_3 )的statement
  • 把这两个statement包裹到一个线程task中

(3) 把这两个task 丢到 SQLThreadPoolExecutor 中执行, 阻塞等待执行完毕

三、结果集合并

ShardResultSet#init() -> ShardResultSetMerger.merge 合并这四个 ResultSet

ShardResultSet 内部包含多个sql执行的结果集 ResultSet, 它实现了 ResultSet ,当从它遍历查询结果的时候,会根据 MergeContext( join、limit…etc)来组合结果数据

debug单测入口:

com.dianping.zebra.shard.jdbc.MultiDBPreparedStatementLifeCycleTest#testSingleRouterResult1

总结

路由定位到多个分库或分表的执行逻辑:

ShardPrepardStatement#normalSelectExecute 会依次执行这多个路由目标分库 RouterResult 内的语句,然后 ShardPrepardStatement#executeQueryByOriginal执行单个分库内的所有sql, 如果它发现有多个sql需要执行,则会根据 单库并发度的配置 concurrentLevel=1

(1)  默认concurrentLevel = 1  ,每个分库内不同表的sql, 先创建对应的 statement, 然后会打包到一个task里

(2) 如果 concurrentLevel > 1, 则每个分库会获取 concurrentLevel 个数据库连接,将这几条分表的sql均摊到这几个数据库连接,创建多个statement, 包成 concurrentLevel 个线程task

(3) 然后丢到java线程池中并发执行  ,然后阻塞等待执行完毕,获取结果

完整目录:数据库中间件zebra源码分析

本文来自博客园,作者:mushishi,转载请注明原文链接:https://www.cnblogs.com/mushishi/p/15022072.html



相关教程