全部产品
云市场

使用说明

更新时间:2019-12-26 17:34:37

本文介绍如何使用数据访问代理连接器来进行 SQL 链路追踪指定分库分表路由,以及拦截器扩展

SQL 链路追踪

使用以下 HINT 语句,根据 traceIdRpcId 对 SQL 数据库进行追踪:

  1. /*+DBP: $SYS={TRACE(TraceId#RpcId)}*/select * from {table_name}

HINT 语句示例:

  1. /*+DBP: $SYS={TRACE(0a0fe91c1514974353459100919649#0.1)}*/select * from test

数据访问代理连接器会将包括追踪信息在内的 SQL 执行信息输出到本地日志 dbp-connector-digest.log 中。

  • 默认情况下,对于执行时间小于 3 ms 且执行成功的 SQL 命令,按照 10/1 的比例抽样打印;
  • 对于执行失败或执行时间大于 3 ms 的 SQL 命令,全量打印。

输出的日志格式如下:

  1. 日志输出时间,应用名称,traceId,RpcId,SQL 语句,执行结果(success/failed),执行耗时(ms),连接建立时间,数据库执行时间,当前线程名

输出的日志示例如下:

  1. 2018-01-03 18:12:33.541,xxx,0a0fe91c1514974353459100919649,0.1,select * from test,success,81ms,77ms,4ms,main

分库分表路由指定

使用以下 HINT 语句,指定 SQL 访问某一特定的分库分表:

  1. /*+DBP: $ROUTE={GROUP_ID(分库位),TABLE_NAME(物理表名)}*/ SQL 语句

HINT 语法格式说明:

  • GROUP_ID:指定分库位,等同于 dbRule 返回的结果;
  • TABLE_NAME:指定物理表名。

另外,数据访问代理连接器提供了拦截器,当您在工程代码中指定分库分表后,在 SQL 语句执行前自动拼接路由 HINT 语句。当您在脚本中定义以下字段后:

  1. RouteParameters routeParameters = RouteCondition.newRouteParameters();
  2. routeParameters.setGroupId("分库位");
  3. routeParameters.setTargetTables(Collections.singletonList("物理表名"));
  4. cn = dbpDataSource.getConnection();
  5. ps = cn.prepareStatement("select * from xxxx");

数据访问代理连接器会将其自动转换为以下 HINT 语句:

  1. /*+DBP: $ROUTE={GROUP_ID(分库位),TABLE_NAME(物理表名)}*/select * from xxxx

拦截器扩展

您可通过实现拦截器接口获得更多扩展功能。配置方法如下:

  1. 在 Spring 的配置文件中,添加以下 bean(以 sqlCountInterceptor 类为例):

    1. <bean id="simpleDataSourceConnector" class="com.alipay.sofa.dbp.DbpDataSource" init-method="init">
    2. <property name="delegate" ref="simpleDataSource"/>
    3. <property name="securitySpec" ref="securitySpecImpl"/>
    4. <property name="interceptors">
    5. <list>
    6. <ref bean="sqlCountInterceptor"/>
    7. </list>
    8. </property>
    9. </bean>
    10. <bean id="sqlCountInterceptor" class="com.alipay.sofa.dbp.SqlCountInterceptor"/>
  2. 为添加的 bean 定义拦截器的代码实现,如下所示:

    1. @NotThreadSafe
    2. public class SqlCountInterceptor implements Interceptor {
    3. private static final Map<String, Integer> sqlCounter = new HashMap<>();
    4. @Override
    5. public Object intercept(Chain chain) throws Exception {
    6. String sql = chain.sql();
    7. Integer count = sqlCounter.get(sql);
    8. if (count == null) {
    9. sqlCounter.put(sql, 1);
    10. } else {
    11. count += 1;
    12. sqlCounter.put(sql, count);
    13. }
    14. return chain.proceed();
    15. }
    16. public int getSqlExecuteCount(String sql){
    17. Integer count = sqlCounter.get(sql);
    18. if (count == null){
    19. return 0;
    20. }
    21. return count;
    22. }
    23. }