本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
DruidXADataSource分布式的事务处理机制
druid增加了分布式的事务处理,查看源码中的DruidXADataSource的XA事务的连接池进行源码分析。
DruidXADataSource类图
DruidXADataSource继承了DruidDataSource,重写了getXAConnection方法,通过不同的数据库方言走不同的创建XA连接的方法。
getXAConnection
@Override
public XAConnection getXAConnection() throws SQLException {
// 调用父类的获取连接的方法
DruidPooledConnection conn = this.getConnection();
Connection physicalConn = conn.unwrap(Connection.class);
// 创建物理连接
XAConnection rawXAConnection = createPhysicalXAConnection(physicalConn);
return new DruidPooledXAConnection(conn, rawXAConnection);
}
createPhysicalXAConnection
//获取物理连接
private XAConnection createPhysicalXAConnection(Connection physicalConn) throws SQLException {
// 获取数据库方言
DbType dbType = DbType.of(this.dbTypeName);
if (dbType == null) {
throw new SQLException("xa not support dbType : " + this.dbTypeName);
}
switch (dbType) {
case oracle:
try {
// oracle的创建XA连接
return OracleUtils.OracleXAConnection(physicalConn);
} catch (XAException xae) {
LOG.error("create xaConnection error", xae);
return null;
}
case mysql:
case mariadb:
// mysql的创建XA连接
return MySqlUtils.createXAConnection(driver, physicalConn);
case postgresql:
return PGUtils.createXAConnection(physicalConn);
case h2:
return H2Utils.createXAConnection(h2Factory, physicalConn);
case jtds:
return new JtdsXAConnection(physicalConn);
default:
throw new SQLException("xa not support dbType : " + this.dbTypeName);
}
}
MySqlUtils.createXAConnection
// mysql数据库的创建XA连接
public static XAConnection createXAConnection(Driver driver, Connection physicalConn) throws SQLException {
//获取大版本号 5和8的版本XA连接不一样
final int major = driver.getMajorVersion();
if (major == 5) {
.......
} else if (major == 6 || major == 8) {
......
}
throw new SQLFeatureNotSupportedException();
}
疑问点
XA需要两阶段提交: prepare 和 commit. 第一阶段为 准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向transaction manager报告已准备就绪。
第二阶段为提交阶段(commit)。当transaction manager确认所有参与者都ready后,向所有参与者发送commit命令。
但是在源码中没有看到相关的二阶段提交的操作,后面继续研究一下。