“阅读原文”,在网页里查看,体验更佳。 温馨提示:在微信关注 Python猫,发送一个数字“”,即可领取 折优惠券,订阅专栏可享 ... 📅 发布时间:2026/7/14 17:49:11 👁️ 浏览次数: 谔涸骨刀但是在一些场景中是需要绕过mybatis直接做一些操作的特别是和数据库元数据相关的操作包括表的结构变更。比如我遇到的场景先查询各个分库中有哪些前缀为table_的表并给这些表加一列col_x。我结合现有代码和大语言模型先写了一版线下运行良好但是线上的某些分库死活找不到对应的分表没法进行后续的处理。这个问题查了很久昨天终于解决了因此分享出来。存在问题的代码Componetpublic class TableAlterHandler {Resource private ShardingSphereDataSource dataSource;public List findTablesByPrefix(String prefix, String physicalSchemaName) {if (StringUtils.isBlank(prefix) || StringUtils.isBlank(physicalSchemaName)) {throw new RuntimeException(分表前缀或分库名为空);}List tableNames Lists.newArrayList();try (HintManager hintManager HintManager.getInstance();Connection conn dataSource.getConnection()) {hintManager.setDataSourceName(DBUtil.queryLogicalSchemaName(physicalSchemaName));DatabaseMetaData metaData conn.getMetaData();try (ResultSet rs metaData.getTables(physicalSchemaName, null, prefix %, new String[] {TABLE})) {while (rs.next()) {String tableName rs.getString(TABLE_NAME);tableNames.add(tableName);}}} catch (SQLException e) {throw new RuntimeException(处理大结果集失败, e);}return tableNames;}}逻辑库和物理库在分析问题之前首先要明确两个概念物理库名physicalSchemaName和逻辑库名logicalSchemaName如果用错了可能会让你没办法发现后续问题的本质原因。上面的代码hintManager必须用逻辑库名而metaData.getTables必须用物理库名。所谓物理库和逻辑库可以看作是我定义的概念。正如其名物理库名就是你jdbcUrl里的库名比如一个典型的阿里云Mysql的JDBC链接jdbc:mysql://rm-bpxxxx.mysql.rds.aliyuncs.com/bizcenter_1?useSSLfalseautoReconnecttruecharacterEncodingutf8serverTimezoneAsia/Shanghai其中的bizcenter_1就是物理库名。这个名称也会在MySql元数据中出现比如select * from information_schema.tables;可以看到这个库的所有表而TABLE_SCHEMA列就是物理库名。而逻辑库则是ShardingSphereDataSource对物理库的映射在application的配置文件(properties或yml)里spring.shardingsphere.datasource配置下你需要配置逻辑库名以及对应的JDBC链接。你可以将多个逻辑库配置为同一个物理库这是一种实践方式可以用于后续的扩容。问题现象线下的三个逻辑库分别对应一个物理库而这三个物理库在同一个阿里云RDS实例上可以找到每个库对应的表。而线上的仍然是三个逻辑库对应各自的物理库每个物理库在不同的阿里云RDS实例上会出现有时候能找到某个库对应的表而另外两个库一个表都找不到的情况。排查遇到问题后百思不得其解因为线下环境一切正常线上却总能复现问题。由于线上环境管控比较严既不能远程debug又不能直连线上库很难定位原因。第一阶段排查我反复确认了上面代码中需要传数据库名的地方到底是逻辑库还是物理库。中间某个版本的确搞错了但是为何在写错的前提下还能运行没有做记录。然后我删掉了connection.setAutoCommit(false)、resultSet.setFetchSize(batchSize)这样的用于降低每次查询元数据结果数量的代码也没效果。最后我把代码移到了另一个连接同样数据库的应用中因为那个应用有我之前类似的代码。移过去以后倒是歪打正着地解决了。第二阶段的排查是在一段时间后我在原先的应用中开发新的功能对原先代码进行改动自以为修复好了但是上线后发现还是和之前一样。分析线下线上最大的区别就是线下几个库是同一个MySql实例而线上分属三个。我的代码里疑点最大的是查询元数据metaData.getTables()这段。好巧不巧在我排查的第一阶段和第二阶段中间我写了一个迁移表的功能完全新写了查询表名的代码并且为了不再犯物理库和逻辑库搞混的错误特别地写了对应的工具类/*** 数据源持有组件便于应用直接访问数据源**/Componentpublic class DataSourceHolder {Resource protected ShardingSphereDataSource dataSource;/** 物理库名(jdbc链接里的库名)和数据源的关系 */private Map hikariDataSourceMap;/** 逻辑库名-物理库名关系 多个逻辑库可能对应同一个物理库 */private Map dsNameMap;/*** 通过物理库名获取ds** param physicalSchemaName* return*/public HikariDataSource getDataSourceByPhysicalSchemaName(String physicalSchemaName) {return hikariDataSourceMap.get(physicalSchemaName);}/*** 通过逻辑库名获取对应物理库名** param dsName* return*/public String getPhysicalSchemaName(String dsName) {return dsNameMap.get(dsName);}/*** 通过逻辑库名获取ds** param logicalSchemaName* return*/public HikariDataSource getDataSourceByLogicalSchemaName(String logicalSchemaName) {String physicalSchemaName getPhysicalSchemaName(logicalSchemaName);if (StringUtils.isBlank(physicalSchemaName)) {throw new RuntimeException(逻辑库名找不到对应物理库, logicalSchemaName logicalSchemaName);}return hikariDataSourceMap.get(physicalSchemaName);}PostConstructpublic void initHikariDataSourceMap() {dsNameMap Maps.newHashMap();hikariDataSourceMap Maps.newHashMap();Map dataSourceMap dataSource.getContextManager().getDataSourceMap(dataSource.getSchemaName());dataSourceMap.forEach((dsName, ds) - {HikariDataSource hds (HikariDataSource) ds;try (Connection connection hds.getConnection(); ) {hikariDataSourceMap.put(connection.getCatalog(), hds);dsNameMap.put(dsName, connection.getCatalog());} catch (SQLException e) {throw new RuntimeException(组装数据源map失败, e);}});}}对应地获取数据库Connection的方法是HikariDataSource hikariDataSource dataSourceHolder.getDataSourceByPhysicalSchemaName(dsName);Connection connection hikariDataSource.getConnection();并且也不再使用HintManager指定逻辑库。联想到线上线下MySql实例的差异我猜测是因为线下三个库是同一个MySql实例那么元数据information_schema.tables是一样的在哪个库都能查到对应表。线上则是不同的实例直接使用ShardingSphereDataSource对应Connection的元数据并不总是预期的库。这个猜测原因也在之前第一阶段的排查吻合能正常工作的代码所在应用获取数据源的方式实际是Map allDataSource shardingSphereDataSource.getContextManager().getDataSourceMap(logic_db);Connection connection allDataSouce.get(logicalSchemaName).getConnection();虽然它也用了HintManger但我认为是没有意义的。修复综合以上的分析最终的修复代码如下List tableNames Lists.newArrayList();try (Connection conn dataSourceHolder.getDataSourceByPhysicalSchemaName(physicalSchemaName).getConnection()) {DatabaseMetaData metaData conn.getMetaData();try (ResultSet rs metaData.getTables(physicalSchemaName, null, prefix %, new String[] {TABLE})) {while (rs.next()) {String tableName rs.getString(TABLE_NAME);tableNames.add(tableName);}}} catch (SQLException e) {throw new RuntimeException(处理大结果集失败, e);}return tableNames;这次再部署到生产环境运行符合预期。可见当你需要实际分库对应的元数据时不要用shardingSphereDataSource而是应该用它关联具体分库的dataSource也即shardingSphereDataSource.getContextManager().getDataSourceMap()再用这个分库dataSource获取元数据。否则线下线上不同的MySql实例配置会导致不同的现象难以排查真正的原因。
Lingyuxiu MXJ创作引擎入门必看:safetensors自动扫描与自然排序机制解析 Lingyuxiu MXJ创作引擎入门必看:safetensors自动扫描与自然排序机制解析 1. 项目概述 Lingyuxiu MXJ创作引擎是一款专门为生成唯美真人风格人像而设计的轻量化AI图像生成系统。这个引擎最大的特点就是针对人像摄影的细节进行了深度优化,特别是在五官细… 2026/5/17 12:05:05
Python 潮流周刊#:让我们对 PyPI 温柔一点,好吗? 淌统阎剂概述 go-zero 基于 net/http 标准库实现了一套 rest web 框架。在使用 goctl 快速开发的同时,也需要了解 go-zero 内部做了什么。本文结合 go-zero rest学习其中的源码,力图做到知其所以然。 源码 流程图 image 在阅读源码之前,… 2026/7/14 3:52:38
Java泛型符号T、E、K、V、? 傻傻分不清楚 胁刺构亮如果你经常使用 Docker,可能会在某天发现磁盘空间莫名变小。执行 docker images命令后,列表中那些既没有名字(REPOSITORY)也没有标签(TAG)、显示为 : 的镜像,很可能就是罪魁祸首。这些就… 2026/7/13 17:28:12
影刀RPA 定时采集监控:数据异常时自动告警 影刀RPA 定时采集监控:数据异常时自动告警 RPA不只是"帮人干活",它还能做"帮人盯数据"。流量暴跌了、库存告急了、某个指标超阈值了——等你发现的时候可能已经晚了。让RPA自动盯着,异常时立刻告警。 监控架构 定时触… 2026/7/14 17:48:54
Claude Code图片生成API实战:从原理到错误处理完整指南 如果你正在使用 Claude Code 进行 AI 编程,却发现在调用图片生成 API 时频繁遇到各种错误,那么这篇文章正是为你准备的。很多开发者以为图片生成 API 只是简单的参数调用,但实际上,从上下文长度限制到认证配置,再到模型… 2026/7/14 17:46:54
【单片机毕业设计】 基于 STM32 单片机的土壤温湿度智能灌溉控制系统设计与实现,基于 51 单片机的农田环境监测与自动浇灌系统设计(011702) 文章目录20 个相关毕业设计备选题目项目研究背景摘要总体方案核心功能基础功能核心功能辅助功能技术路线项目演示关于我们项目案例源码获取博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者&… 2026/7/14 17:44:53
高压安全隔离系统设计与实现:ISOM8710与PIC32MZ方案 1. 高压安全隔离系统设计概述在现代工业控制和电力电子系统中,高压安全隔离是确保人员和设备安全的关键技术。ISOM8710数字隔离器与PIC32MZ1024EFE144微控制器的组合,为实现高达5kVrms的安全隔离提供了高性能解决方案。这套系统特别适用于电机驱动、光伏… 2026/7/14 17:44:53
从ONNX到Ryzen AI:Phi-3-mini-128k-instruct_rai_1.7.1_hybrid模型部署优化实战指南 从ONNX到Ryzen AI:Phi-3-mini-128k-instruct_rai_1.7.1_hybrid模型部署优化实战指南 【免费下载链接】Phi-3-mini-128k-instruct_rai_1.7.1_hybrid 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Phi-3-mini-128k-instruct_rai_1.7.1_hybrid 想要在AMD … 2026/7/14 17:44:53
Nebula 1.6.0 发布!跨区域桶自动路由,带来多项功能升级和稳定性修复 Nebula 1.6.0 发布:跨区域桶自动路由,带来预览、传输等多项功能升级!Nebula 1.6.0 重磅发布!此次更新的重头戏是 跨区域桶自动路由。以前“列举桶”虽是全局的,能列出所有区域的桶,但每个桶仅存在于一个区域… 2026/7/14 17:40:52
XUnity.AutoTranslator 游戏实时翻译插件:从原理到实战的完整指南 1. 项目概述:当游戏语言成为一堵墙作为一名玩了十几年日系、欧美独立游戏的“老油条”,我太懂那种面对一款心仪已久、画风玩法都戳中G点的游戏,却因为语言不通而望而却步的痛了。尤其是那些基于Unity引擎开发的、体量不大但内容精良的作品&am… 2026/7/14 0:05:14
2026普通文员学数据分析的价值 一、2026年普通文员学习数据分析的必要性随着数字化转型加速,数据分析技能正逐渐成为职场基础能力。普通文员学习数据分析可以提升工作效率、增强竞争力,并为职业转型提供更多可能性。二、数据分析对文员的价值自动化办公:通过数据分析工具&a… 2026/7/14 0:05:14
2026从计划员到主管,生产管理者学数据分析有用吗? 一、生产管理领域的职业发展路径 从计划员到主管的角色转变,是生产管理者职业发展的典型路径。计划员主要负责生产排程、库存管理和资源协调等基础工作,而主管则需要承担团队管理、决策支持和效率优化等更高级别的职责。这种转变不仅仅是职位的提升&… 2026/7/14 0:05:14
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/13 9:31:08
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/14 5:09:41