为了能更便捷地使用 PolarDB-X 2.0,PolarDB-X 提供了供 Java 使用的标准 JDBC 驱动,以实现:
直连 PolarDB-X 2.0 标准版,并提供在 HA 后自动连接新主节点的能力 直连 PolarDB-X 2.0 标准版,并在三节点计划切换时提供无感切换能力 直连 PolarDB-X 2.0 企业版,并实现多节点的负载均衡
基本信息
Maven 依赖
驱动为 polardbx-connector-java,同时通过 provided 方式依赖 mysql-connector-java,便于用户自行选择使用的 MySQL JDBC connector。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>com.alibaba.polardbx</groupId>
<artifactId>polardbx-connector-java</artifactId>
<version>2.1.1</version>
</dependency>
使用说明
JDBC URL 样例:
jdbc:polardbx://11.167.60.147:6991/test
驱动包名:com.alibaba.polardbx.Driver 协议标志头:polardbx ip端口指定: 标准版三节点其中一个 IP:port 或者 VIP:port,或者多个 IP0:port0,IP1:port1(必须为同一集群中的节点,以英文逗号分隔),建连时会被路由到 leader 节点。 企业版其中一个 IP:port 或者 VIP:port,或者多个 IP0:port0,IP1:port1(必须为同一集群中的节点,以英文逗号分隔),建连时会负载均衡到集群中随机一个读写节点。
额外参数: clusterId:集群 ID,用于校验避免错连,可以不指定,第一次连接会自动获取 haCheckConnectTimeoutMillis:HA 检测连接超时时间,默认 3000ms haCheckSocketTimeoutMillis:HA 检测查询超时时间,默认 3000ms haCheckIntervalMillis:HA 检测间隔时间,默认 1000ms checkLeaderTransferringIntervalMillis:无感切换状态探测间隔,默认 100ms leaderTransferringWaitTimeoutMillis:无感切换最长阻塞并等待切换时间,默认 5000ms smoothSwitchover:是否支持连接池的无感高可用切换,通过在切换时 isClosed 时返回 true,让连接池抛弃该过时的连接,默认 true
额外行为: connectTimeout 在第一次获取 leader 或者 HA 切换时,会设置为 5000ms,其他情况默认无超时
其他特征 JDK 8 标准编写,适配低版本 参考标准 JDBC connector 以适配各种连接池 在 HA 发生后,对已存在 Connection,会让所有请求报错 拿连接时,会检查 HA 切换状态,实现无感切换
驱动 JDBC URL 兼容 MySQL JDBC connector,支持设置 user、password、useSSL、characterEncoding、connectTimeout、socketTimeout、allowLoadLocalInfile、allowPublicKeyRetrieval、sslMode、characterEncoding、useCursorFetch、rewriteBatchedStatements、netTimeoutForStreamingResults、useServerPrepStmts、useUnicode 等常见参数。
关于无感切换能力
PolarDB-X,结合polardbx-connector-java驱动,提供了面向数据库的无感切换能力。
比如:DBA进行数据库主动主机下线的运维,此时数据库需要发生预期内的HA切换操作,基于PolarDB-X数据库+驱动的无感切换能力,可以提供业务SQL不中断、不报错的无感体验,极大的改善业务使用数据库的体验。
无感切换,工作原理示意:

PolarDB-X提供的无感切换,通过驱动实时感知 PolarDB-X 标准版三节点集群状态,在数据库HA切换动作完成之前:
客户端驱动,阻塞分配连接返回,直到切换完成; 针对业务已经获取连接尽快完成请求,并标记其不可复用
注意事项:
客户端驱动,新增两个无感切换的检查点(获取链接、归还链接),通过实时感知 PolarDB-X 标准版三节点集群状态,实现HA切换后链接的动态重建能力,仅增加了获取新连接时间,但不会导致已有连接上请求报错,实现计划切换时应用无感。 业务获取了数据库Connection链接,推荐使用标准 try-with-resources 实现的数据库操作,只要 try 块中的业务执行时间小于对应 PolarDB-X 设置的HA窗口(consensus_wait_millisecond_before_change_leader时间阈值,默认为1秒),就不会因为计划切换报错。而对于持有连接时长超出时间阈值的长事务,因为横跨切换流程,切换后会因为不能写入而报错。
目前PolarDB-X的无感切换能力,适配链接池:
Druid >= 1.2.24版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.24</version>
</dependency>
druid连接池参数的最佳实践:如何选择应用端连接池 ( https://help.aliyun.com/zh/polardb/polardb-for-xscale/configure-a-connection-pool-for-an-application-to-connect-to-a-polardb-x-instance )
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="com.alibaba.polardbx.Driver" >
<!-- 基本属性 URL、user、password -->
<property name="url" value="jdbc:polardbx://ip:port/db?autoReconnect=true&rewriteBatchedStatements=true&socketTimeout=30000&connectTimeout=3000" >
<property name="username" value="root" >
<property name="password" value="123456" >
<!-- 配置初始化大小、最小、最大 -->
<property name="maxActive" value="20" >
<property name="initialSize" value="3" >
<property name="minIdle" value="3" >
<!-- maxWait 获取连接等待超时的时间 -->
<property name="maxWait" value="60000" >
<!-- timeBetweenEvictionRunsMillis 间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" >
<!-- minEvictableIdleTimeMillis 一个连接在池中最小空闲的时间,单位是毫秒-->
<property name="minEvictableIdleTimeMillis" value="300000" >
<!-- 检测连接是否可用的 SQL -->
<property name="validationQuery" value="select 'z' from dual" >
<!-- 是否开启空闲连接检查 -->
<property name="testWhileIdle" value="true" >
<!-- 是否在获取连接前检查连接状态 -->
<property name="testOnBorrow" value="false" >
<!-- 是否在归还连接时检查连接状态 -->
<property name="testOnReturn" value="false" >
<!-- 是否在固定时间关闭连接。增加此参数可以均衡后端服务节点参数 -->
<property name="phyTimeoutMillis" value="600000" >
<!-- 是否在固定SQL使用次数之后关闭连接,增加此参数可以均衡后端服务节点参数-->
<property name="phyMaxUseCount" value="10000" >
</bean>
快速使用例子(通用场景)
直接使用驱动连接 PolarDB-X
Class.forName("com.alibaba.polardbx.Driver");
try (final Connection conn = DriverManager.getConnection(
"jdbc:polardbx://127.0.0.1:3306/", "root", "*****");
final Statement stmt = conn.createStatement()) {
try (final ResultSet rs = stmt.executeQuery("select 1")) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getObject(i + 1) + "\t");
}
System.out.println();
}
}
}
使用 Druid 连接池
try (final DruidDataSource dataSource = new DruidDataSource()) {
dataSource.setUrl("jdbc:polardbx://127.0.0.1:3306/");
dataSource.setUsername("root");
dataSource.setPassword("*****");
// 当 druid 连接池版本小于等于 1.2.23 时,需要主动调用 setDriverClassName 和 setExceptionSorter,以适配 PolarDB-X 的驱动,新版本 1.2.24 及后续版本能够自动识别驱动
dataSource.setDriverClassName("com.alibaba.polardbx.Driver");
dataSource.setExceptionSorter(new MySqlExceptionSorter());
try (final Connection conn = dataSource.getConnection();
final Statement stmt = conn.createStatement()) {
try (final ResultSet rs = stmt.executeQuery("select 1")) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getObject(i + 1) + "\t");
}
System.out.println();
}
}
}
}
或者通过 xml 设置数据源后,通过代码,新增这两项适配新驱动:
dataSource.setDriverClassName("com.alibaba.polardbx.Driver");
dataSource.setExceptionSorter(new MySqlExceptionSorter());
使用 HikariCP 连接池
Class.forName("com.alibaba.polardbx.Driver");
final HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:polardbx://127.0.0.1:3306/");
config.setUsername("root");
config.setPassword("*****");
config.setMaximumPoolSize(10);
try (HikariDataSource dataSource = new HikariDataSource(config)) {
try (final Connection conn = dataSource.getConnection();
final Statement stmt = conn.createStatement()) {
try (final ResultSet rs = stmt.executeQuery("select 1")) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getObject(i + 1) + "\t");
}
System.out.println();
}
}
}
}
使用 DBCP 连接池
Class.forName("com.alibaba.polardbx.Driver");
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:polardbx://127.0.0.1:3306/");
dataSource.setUsername("root");
dataSource.setPassword("*****");
dataSource.setInitialSize(5);
try (final Connection conn = dataSource.getConnection();
final Statement stmt = conn.createStatement()) {
try (final ResultSet rs = stmt.executeQuery("select 1")) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getObject(i + 1) + "\t");
}
System.out.println();
}
}
}
快速验证样例
在测试开发环境配置 JDK 环境 下载 mysql-connector-j-8.0.33.jar polardbx-connector-java-2.1.1.jar 编写测试文件,注意替换为自己集群的地址、用户名、密码,并确保网络能连通,如下代码展示连接 PolarDB-X 标准版集群,并打印集群的相关信息
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestDriver {
public static void main(String[] args) throws Exception {
Class.forName("com.alibaba.polardbx.Driver");
try (final Connection conn = DriverManager.getConnection(
"jdbc:polardbx://127.0.0.1:3306/", "root", "****");
final Statement stmt = conn.createStatement()) {
try (final ResultSet rs = stmt.executeQuery("select * from information_schema.alisql_cluster_global")) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); ++i) {
System.out.print(rs.getObject(i + 1) + "\t");
}
System.out.println();
}
}
}
}
}
编译运行
$javac TestDriver.java
$ll
total 2812
-rw-r--r-- 1 chenyu.zzy users 2481560 Dec 3 17:26 mysql-connector-j-8.0.33.jar
-rw-r--r-- 1 chenyu.zzy users 384133 Dec 3 17:19 polardbx-connector-java-2.1.1.jar
-rw-r--r-- 1 chenyu.zzy users 2442 Dec 3 17:29 TestDriver.class
-rw-r--r-- 1 chenyu.zzy users 1102 Dec 3 17:29 TestDriver.java
# 第一次运行时,高可用会打印获取到的集群信息到日志接口中
$java -cp .:mysql-connector-j-8.0.33.jar:polardbx-connector-java-2.1.1.jar TestDriver
Dec 03, 2024 5:29:58 PM com.alibaba.polardbx.HaManager info
INFO: Backend cluster state changed to: [{"tag":"127.0.0.1:6991","host":"127.0.0.1","port":6991,"xport":34991,"paxos_port":14991,"role":"Leader","peers":[{"tag":"11.167.60.147:6992","host":"11.167.60.147","port":6992,"xport":-1,"paxos_port":14992,"role":"Follower","version":"8.0.32-X-Cluster-8.4.20-20241014","cluster_id":6990,"update_time":"2024-12-03 17:29:58 GMT+08:00"},{"tag":"11.167.60.147:6993","host":"11.167.60.147","port":6993,"xport":-1,"paxos_port":14993,"role":"Follower","version":"8.0.32-X-Cluster-8.4.20-20241014","cluster_id":6990,"update_time":"2024-12-03 17:29:58 GMT+08:00"},{"tag":"127.0.0.1:6991","host":"11.167.60.147","port":6991,"xport":34991,"paxos_port":14991,"role":"Leader","version":"8.0.32-X-Cluster-8.4.20-20241014","cluster_id":6990,"update_time":"2024-12-03 17:29:58 GMT+08:00"}],"version":"8.0.32-X-Cluster-8.4.20-20241014","cluster_id":6990,"update_time":"2024-12-03 17:29:58 GMT+08:00"}]
SERVER_ID IP_PORT MATCH_INDEX NEXT_INDEX ROLE HAS_VOTED FORCE_SYNC ELECTION_WEIGHT LEARNER_SOURCE APPLIED_INDEX PIPELINING SEND_APPLIED
1 11.167.60.147:14991 264333 0 Leader Yes No 9 0 264332 No No
2 11.167.60.147:14992 264333 264334 Follower Yes No 9 0 264333 Yes No
3 11.167.60.147:14993 264333 264334 Follower Yes No 1 0 264333 Yes No
# 再次运行由于集群信息没有变化,则不会打印相关信息(集群信息会被缓存以加快初始化速度)
$java -cp .:mysql-connector-j-8.0.33.jar:polardbx-connector-java-2.1.1.jar TestDriver
SERVER_ID IP_PORT MATCH_INDEX NEXT_INDEX ROLE HAS_VOTED FORCE_SYNC ELECTION_WEIGHT LEARNER_SOURCE APPLIED_INDEX PIPELINING SEND_APPLIED
1 11.167.60.147:14991 264333 0 Leader Yes No 9 0 264332 No No
2 11.167.60.147:14992 264333 264334 Follower Yes No 9 0 264333 Yes No
3 11.167.60.147:14993 264333 264334 Follower Yes No 1 0 264333 Yes No
文章转载自PolarDB,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




