Skip to content

Commit

Permalink
bugfix: fix tablemeta refresh after closed (#7044)
Browse files Browse the repository at this point in the history
  • Loading branch information
LegGasai authored Dec 4, 2024
1 parent db1567c commit b44c626
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
1 change: 1 addition & 0 deletions changes/en-us/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7010](https://github.com/apache/incubator-seata/pull/7010)] fix error while the "context" is key word in DM8 when delete undolog
- [[#7022](https://github.com/apache/incubator-seata/pull/7022)] fix `store.mode` property in `application.raft.example.yml`
- [[#7025](https://github.com/apache/incubator-seata/pull/7025)] fix vGroupMappingManager is NOT init
- [[#7044](https://github.com/apache/incubator-seata/pull/7044)] fix tableMeta refresh after closed
-
### optimize:
- [[#6826](https://github.com/apache/incubator-seata/pull/6826)] remove the branch registration operation of the XA read-only transaction
Expand Down
1 change: 1 addition & 0 deletions changes/zh-cn/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [[#7010](https://github.com/apache/incubator-seata/pull/7010)] 修复使用达梦数据库时删除undolog发生SQL语法错误
- [[#7022](https://github.com/apache/incubator-seata/pull/7022)] 修复 `application.raft.example.yml``store.mode`属性
- [[#7025](https://github.com/apache/incubator-seata/pull/7025)] 修复vGroupMappingManager未初始化的问题
- [[#7044](https://github.com/apache/incubator-seata/pull/7044)] 修复TableMeta在数据源关闭后刷新错误问题

### optimize:
- [[#6826](https://github.com/apache/incubator-seata/pull/6826)] 移除只读XA事务的分支注册操作
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.seata.rm.datasource.sql.struct;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
Expand All @@ -29,6 +30,7 @@
import org.apache.seata.common.loader.EnhancedServiceLoader;
import org.apache.seata.common.thread.NamedThreadFactory;
import org.apache.seata.common.util.CollectionUtils;
import org.apache.seata.common.util.StringUtils;
import org.apache.seata.config.ConfigurationFactory;
import org.apache.seata.rm.datasource.DataSourceProxy;
import org.apache.seata.sqlparser.struct.TableMetaCache;
Expand Down Expand Up @@ -99,6 +101,14 @@ public static void tableMetaRefreshEvent(String resourceId) {
}
}

/**
* Remove the TableMetaRefreshHolder from the map.
*/
private static void removeHolderFromMap(String resourceId) {
TABLE_META_REFRESH_HOLDER_MAP.remove(resourceId);
LOGGER.info("Removed TableMetaRefreshHolder for resourceId: {}", resourceId);
}

static class TableMetaRefreshHolder {
private long lastRefreshFinishTime;
private DataSourceProxy dataSource;
Expand Down Expand Up @@ -133,6 +143,16 @@ static class TableMetaRefreshHolder {
}
lastRefreshFinishTime = System.nanoTime();
}
} catch (SQLException ex) {
if (isDataSourceClosedException(ex)) {
LOGGER.info("DataSource is closed, exiting refresh task for resourceId: {}", dataSource.getResourceId());
removeHolderFromMap(dataSource.getResourceId());
return;
} else {
// other error, avoid high CPU usage due to infinite loops caused by database exceptions
LOGGER.error("Table refresh SQL error: {}", ex.getMessage(), ex);
lastRefreshFinishTime = System.nanoTime();
}
} catch (Exception exx) {
LOGGER.error("table refresh error:{}", exx.getMessage(), exx);
// Avoid high CPU usage due to infinite loops caused by database exceptions
Expand All @@ -142,7 +162,20 @@ static class TableMetaRefreshHolder {
});
}



/**
* Helper method to determine if the exception is caused by the data source being closed.
*
* @param ex the SQLException to check
* @return true if the exception indicates the data source is closed; false otherwise
*/
private boolean isDataSourceClosedException(SQLException ex) {
String message = ex.getMessage().toLowerCase();
String sqlState = ex.getSQLState();
// Most jdbc drivers use '08006' as the datasource close code.
if ("08006".equals(sqlState)) {
return true;
}
return StringUtils.isNotBlank(message) && message.contains("datasource") && message.contains("close");
}
}
}

0 comments on commit b44c626

Please sign in to comment.