使用说明
本文介绍如何使用数据访问代理连接器来进行 SQL 链路追踪、指定分库分表路由和拦截器扩展。
SQL 链路追踪
使用以下 HINT 语句,根据 traceId
和 RpcId
对 SQL 数据库进行追踪:
/*+DBP: $SYS={TRACE(TraceId#RpcId)}*/select*from{table_name}
HINT 语句示例:
/*+DBP: $SYS={TRACE(0a0fe91c1514974353459100919649#0.1)}*/select*from test
数据访问代理连接器会将包括追踪信息在内的 SQL 执行信息输出到本地日志 dbp-connector-digest.log
中。
默认情况下,对于执行时间小于 3ms 且执行成功的 SQL 命令,按照 10/1 的比例抽样打印;
对于执行失败或执行时间大于 3ms 的 SQL 命令,全量打印。
输出的日志格式如下:
日志输出时间,应用名称,traceId,RpcId,SQL 语句,执行结果(success/failed),执行耗时(ms),连接建立时间,数据库执行时间,当前线程名
输出的日志示例如下:
2018-01-0318:12:33.541,xxx,0a0fe91c1514974353459100919649,0.1,select*from test,success,81ms,77ms,4ms,main
分库分表路由指定
使用以下 HINT 语句,指定 SQL 访问某一特定的分库分表:
/*+DBP: $ROUTE={GROUP_ID(分库位),TABLE_NAME(物理表名)}*/ SQL 语句
HINT 语法格式说明:
GROUP_ID
:指定分库位,等同于dbRule
返回的结果;TABLE_NAME
:指定物理表名。
另外,数据访问代理连接器提供了拦截器,当您在工程代码中指定分库分表后,在 SQL 语句执行前自动拼接路由 HINT 语句。当您在脚本中定义以下字段后:
RouteParameters routeParameters =RouteCondition.newRouteParameters();
routeParameters.setGroupId("分库位");
routeParameters.setTargetTables(Collections.singletonList("物理表名"));
cn = dbpDataSource.getConnection();
ps = cn.prepareStatement("select * from xxxx");
数据访问代理连接器会将其自动转换为以下 HINT 语句:
/*+DBP: $ROUTE={GROUP_ID(分库位),TABLE_NAME(物理表名)}*/select*from xxxx
拦截器扩展
您可通过实现拦截器接口获得更多扩展功能。配置方法如下:
在 Spring 的配置文件中,添加以下 bean(以
sqlCountInterceptor
类为例):<bean id="simpleDataSourceConnector" class="com.alipay.sofa.dbp.DbpDataSource" init-method="init"> <property name="delegate" ref="simpleDataSource"/> <property name="securitySpec" ref="securitySpecImpl"/> <property name="interceptors"> <list> <ref bean="sqlCountInterceptor"/> </list> </property> </bean> <bean id="sqlCountInterceptor" class="com.alipay.sofa.dbp.SqlCountInterceptor"/>
为添加的 bean 定义拦截器的代码实现,如下所示:
@NotThreadSafe public class SqlCountInterceptor implements Interceptor { private static final Map<String, Integer> sqlCounter = new HashMap<>(); @Override public Object intercept(Chain chain) throws Exception { String sql = chain.sql(); Integer count = sqlCounter.get(sql); if (count == null) { sqlCounter.put(sql, 1); } else { count += 1; sqlCounter.put(sql, count); } return chain.proceed(); } public int getSqlExecuteCount(String sql) { Integer count = sqlCounter.get(sql); if (count == null) { return0; } return count; } }