Skip to content

Commit

Permalink
bugfix: fix mysql-loadbalance resource id error (#4355)
Browse files Browse the repository at this point in the history
  • Loading branch information
funky-eyes authored Feb 8, 2022
1 parent 8274fc4 commit b62f03e
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 18 deletions.
1 change: 1 addition & 0 deletions changes/1.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单
- [[#4302](https://github.com/seata/seata/pull/4302)] 修复其他ORM可能存在获取不到自增主键值的问题
- [[#4308](https://github.com/seata/seata/pull/4308)] 修复Postgresql多个schema下存在相同表的TableMetaCache解析问题
- [[#4326](https://github.com/seata/seata/pull/4326)] 修复使用 mariadb 驱动程序时无法构建 Executor 的问题
- [[#4355](https://github.com/seata/seata/pull/4355)] 修复使用 mysql Loadbalance模式resourceId被误判为resourceIds的问题
- [[#4310](https://github.com/seata/seata/pull/4310)] 修复通过"SELECT LAST_INSERT_ID"获取mysql数据库自增id失败的问题
- [[#4331](https://github.com/seata/seata/pull/4331)] 修复使用ONLY_CARE_UPDATE_COLUMNS配置可能出现的脏写校验异常

Expand Down
1 change: 1 addition & 0 deletions changes/en-us/1.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
- [[#4278](https://github.com/seata/seata/pull/4278)] fix the problem that mysql's Blob/Clob/NClob data type cannot be deserialized
- [[#4308](https://github.com/seata/seata/pull/4308)] fix the TableMetaCache parsing problem with the same table under multiple Postgresql schemas
- [[#4326](https://github.com/seata/seata/pull/4326)] fix inability to build Executor when using mariadb driver
- [[#4355](https://github.com/seata/seata/pull/4355)] fix mysql-loadbalance resource id error
- [[#4310](https://github.com/seata/seata/pull/4310)] fix the problem that failed to obtain the self increment ID of MySQL database through "select last_insert_id"
- [[#4331](https://github.com/seata/seata/pull/4331)] fix dirty write check exception that may occur when using ONLY_CARE_UPDATE_COLUMNS configuration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource

private String jdbcUrl;

private String resourceId;

private String dbType;

private String userName;
Expand Down Expand Up @@ -110,6 +112,7 @@ private void init(DataSource dataSource, String resourceGroupId) {
} catch (SQLException e) {
throw new IllegalStateException("can not init dataSource", e);
}
initResourceId();
DefaultResourceManager.get().registerResource(this);
if (ENABLE_TABLE_META_CHECKER_ENABLE) {
tableMetaExcutor.scheduleAtFixedRate(() -> {
Expand Down Expand Up @@ -163,27 +166,57 @@ public String getResourceGroupId() {

@Override
public String getResourceId() {
if (resourceId == null) {
initResourceId();
}
return resourceId;
}

private void initResourceId() {
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
return getPGResourceId();
initPGResourceId();
} else if (JdbcConstants.ORACLE.equals(dbType) && userName != null) {
return getDefaultResourceId() + "/" + userName;
initDefaultResourceId();
resourceId = resourceId + "/" + userName;
} else if (JdbcConstants.MYSQL.equals(dbType)) {
initMysqlResourceId();
} else {
return getDefaultResourceId();
initDefaultResourceId();
}
}

/**
* get the default resource id
* @return resource id
* init the default resource id
*/
private String getDefaultResourceId() {
private void initDefaultResourceId() {
if (jdbcUrl.contains("?")) {
return jdbcUrl.substring(0, jdbcUrl.indexOf('?'));
resourceId = jdbcUrl.substring(0, jdbcUrl.indexOf('?'));
} else {
return jdbcUrl;
resourceId = jdbcUrl;
}
}

/**
* prevent mysql url like
* jdbc:mysql:loadbalance://192.168.100.2:3306,192.168.100.1:3306/seata
* it will cause the problem like
* 1.rm client is not connected
*/
private void initMysqlResourceId() {
String startsWith = "jdbc:mysql:loadbalance://";
if (jdbcUrl.startsWith(startsWith)) {
String url;
if (jdbcUrl.contains("?")) {
url = jdbcUrl.substring(0, jdbcUrl.indexOf('?'));
} else {
url = jdbcUrl;
}
resourceId = url.replace(",", "|");
} else {
initDefaultResourceId();
}
}

/**
* prevent pg sql url like
* jdbc:postgresql://127.0.0.1:5432/seata?currentSchema=public
Expand All @@ -192,14 +225,13 @@ private String getDefaultResourceId() {
* it will cause the problem like
* 1.get file lock fail
* 2.error table meta cache
* @return resourceId
*/
private String getPGResourceId() {
private void initPGResourceId() {
if (jdbcUrl.contains("?")) {
StringBuilder jdbcUrlBuilder = new StringBuilder();
jdbcUrlBuilder.append(jdbcUrl.substring(0, jdbcUrl.indexOf('?')));
jdbcUrlBuilder.append(jdbcUrl, 0, jdbcUrl.indexOf('?'));
StringBuilder paramsBuilder = new StringBuilder();
String paramUrl = jdbcUrl.substring(jdbcUrl.indexOf('?') + 1, jdbcUrl.length());
String paramUrl = jdbcUrl.substring(jdbcUrl.indexOf('?') + 1);
String[] urlParams = paramUrl.split("&");
for (String urlParam : urlParams) {
if (urlParam.contains("currentSchema")) {
Expand All @@ -215,9 +247,9 @@ private String getPGResourceId() {
jdbcUrlBuilder.append("?");
jdbcUrlBuilder.append(paramsBuilder);
}
return jdbcUrlBuilder.toString();
resourceId = jdbcUrlBuilder.toString();
} else {
return jdbcUrl;
resourceId = jdbcUrl;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
*/
package io.seata.rm.datasource;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.SQLException;

import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.mock.MockDataSource;
import io.seata.rm.datasource.mock.MockDriver;
Expand Down Expand Up @@ -53,21 +52,33 @@ public void getResourceIdTest() throws SQLException, NoSuchFieldException, Illeg
dataSource.setPassword("password");

DataSourceProxy proxy = new DataSourceProxy(dataSource);

Field resourceId = proxy.getClass().getDeclaredField("resourceId");
resourceId.setAccessible(true);
resourceId.set(proxy, null);
Field dbTypeField = proxy.getClass().getDeclaredField("dbType");
dbTypeField.setAccessible(true);
dbTypeField.set(proxy, io.seata.sqlparser.util.JdbcConstants.ORACLE);

String userName = dataSource.getConnection().getMetaData().getUserName();
Assertions.assertEquals(userName, username);

Field userNameField = proxy.getClass().getDeclaredField("userName");
userNameField.setAccessible(true);
userNameField.set(proxy, username);

Assertions.assertEquals(proxy.getResourceId(), "jdbc:mock:xxx/username");

dbTypeField.set(proxy, io.seata.sqlparser.util.JdbcConstants.MYSQL);
resourceId.setAccessible(true);
resourceId.set(proxy, null);
Assertions.assertEquals(proxy.getResourceId(), "jdbc:mock:xxx");
resourceId.setAccessible(true);
resourceId.set(proxy, null);
Field jdbUrl = proxy.getClass().getDeclaredField("jdbcUrl");
jdbUrl.setAccessible(true);
jdbUrl.set(proxy, "jdbc:mysql:loadbalance://192.168.100.2:3306,192.168.100.3:3306,192.168.100.1:3306/seata");
resourceId.setAccessible(true);
resourceId.set(proxy, null);
Assertions.assertEquals(proxy.getResourceId(), "jdbc:mysql:loadbalance://192.168.100.2:3306|192.168.100.3:3306|192.168.100.1:3306/seata");

}
}

0 comments on commit b62f03e

Please sign in to comment.