ShardingSphere分库分表schema名称导致NPE问题排查记录

news2024/11/30 0:50:50

前段时间把 ShardingSphere 升级到了 5.1.1 版本,奈何官方版本升级太快跟不上速度,这不最近又发现了一个 BUG。

问题现象

数据库做了分库分表,在需要查询多表数据进行 merge 的时候发生了一个 NPE 的异常。

Caused by: java.lang.NullPointerException
    at org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByValue.getOrderValuesCaseSensitiveFromTables(OrderByValue.java:73) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByValue.getOrderValuesCaseSensitive(OrderByValue.java:64) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByValue.<init>(OrderByValue.java:58) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByStreamMergedResult.orderResultSetsToQueue(OrderByStreamMergedResult.java:56) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByStreamMergedResult.<init>(OrderByStreamMergedResult.java:50) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.ShardingDQLResultMerger.build(ShardingDQLResultMerger.java:89) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.sharding.merge.dql.ShardingDQLResultMerger.merge(ShardingDQLResultMerger.java:63) ~[shardingsphere-sharding-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.infra.merge.MergeEngine.executeMerge(MergeEngine.java:90) ~[shardingsphere-infra-merge-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.infra.merge.MergeEngine.merge(MergeEngine.java:80) ~[shardingsphere-infra-merge-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.mergeQuery(ShardingSpherePreparedStatement.java:487) ~[shardingsphere-jdbc-core-5.1.1.jar:5.1.1]
    at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.getResultSet(ShardingSpherePreparedStatement.java:435) ~[shardingsphere-jdbc-core-5.1.1.jar:5.1.1]
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getFirstResultSet(DefaultResultSetHandler.java:237) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:187) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109) ~[mybatis-3.5.3.jar:3.5.3]
    at jdk.internal.reflect.GeneratedMethodAccessor346.invoke(Unknown Source) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63) ~[mybatis-3.5.3.jar:3.5.3]
    at com.sun.proxy.$Proxy410.query(Unknown Source) ~[?:?]
    at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:108) ~[pagehelper-5.1.11.jar:?]
    at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) ~[mybatis-3.5.3.jar:3.5.3]
    at com.sun.proxy.$Proxy410.query(Unknown Source) ~[?:?]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147) ~[mybatis-3.5.3.jar:3.5.3]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) ~[mybatis-3.5.3.jar:3.5.3]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.6.jar:2.0.6]
    ... 95 more

问题排查

跟踪到报错的地方,发现是这个地方的schema是个null,从而引发了 NPE。

一路往上看代码,最终定位到了这个获取schema的地方,也就是元数据去getDefaultSchema获取默认的schema名称改的时候拿到了一个空值。

进入这个方法后发现通过schemaschemas这个map里获取名称的时候是个空值,debug到这个地方其实发现了问题。

我们的schemaName配置的是orderTrade包含有大写字符的,所以name传进来的是orderTrade,但是问题是这个schemas确是ordertrade

所以很显然,这里获取不到正确的schema名称,导致了这个 NPE 的异常,那么问题是这个schemas是怎么加载进来的呢?

我们发现schemas是在创建元数据的时候,通过构造函数赋值的,那么只要找到这个赋值的地方应该就能发现问题了。

通过一番查找,找到了调用的地方,这个schemas值就是databaseMap中的value,那么我们要继续看这个databaseMap是如何初始化来的。

继续看源码,找到了databaseMap进行初始化的地方,原来是通过DatabaseLoader去加载元数据的时候初始化的,那么这个load方法是怎么处理的呢?

从代码来看他包含了两部分的信息,第一个是我们自己通过schema配置的一些分库分表的配置信息,另外一部分则是数据库默认的一些表的元数据,比如mysqlinformation_schema这些,那我们只要看自己配置的那部分就可以了,也就是SchemaLoader.load(dataSourceMap, rules, props)方法。

看他实际上就是获取数据库是什么类型,比如mysql,然后去加载表的元数据,最后new出来ShardingSphereSchema,直接看最后的new部分代码就行了。

进入这个方法,瞬间就真相大白了,原来在put的时候对所有的schemaName进行了小写处理,所以在最上面我们去get的时候肯定会拿到一个空值,最终导致merge的时候发生了 NPE 异常。

解决方案

现在问题原因已经发现了,那么该如何解决呢?总不能不让别人配置的时候不让写大写吧,本着能不能白嫖一个 PR 的想法,又去给 Sharding 提了一个 Issue。

就我点了根烟的功夫,回头就给我回复说新版本已经修复了,希望落空了,修复方案就是查询的时候也做小写处理了,好吧,那就这样吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】前缀树/字典树

目录1.概述2.代码实现3.应用本文参考&#xff1a; LeetCode 208.实现 Trie (前缀树) 1.概述 前缀树又称字典树、Trie 树、单词查找树&#xff0c;是一棵有根树&#xff0c;同时也是一种哈希树的变种&#xff0c;其每个节点包含以下字段&#xff1a; 指向子节点的指针数组 chi…

pytorch 分布式调试debug torch.distributed.launch

文章目录一. pytorch 分布式调试debug torch.distributed.launch 三种方式1. 方式1&#xff1a;ipdb调试&#xff08;建议&#xff09;命令行使用pdb未解决&#xff1a;2. 方式2&#xff1a;使用pycharm进行分布式调试&#xff08;侵入式代码&#xff09;3. 方式3&#xff1a;使…

HRNet源码阅读笔记(5),庞大的PoseHighResolutionNet模块-transition1

在stage1的最后&#xff0c;分支了。就是所谓的transition1&#xff0c;详见下面的第13行。def forward(self, x):x self.conv1(x)x self.bn1(x)x self.relu(x)x self.conv2(x)x self.bn2(x)x self.relu(x)x self.layer1(x)x_list []for i in range(self.stage2_cfg[NU…

【前端之旅】Webpack模块打包工具

一名软件工程专业学生的前端之旅,记录自己对三件套(HTML、CSS、JavaScript)、Jquery、Ajax、Axios、Bootstrap、Node.js、Vue、小程序开发(Uniapp)以及各种UI组件库、前端框架的学习。 【前端之旅】Web基础与开发工具 【前端之旅】手把手教你安装VS Code并附上超实用插件…

【图的存储】

更好的阅读体验\color{red}{更好的阅读体验}更好的阅读体验 文章目录1. 邻接矩阵2. 边集数组3. 邻接表4. 链式邻接表5. 链式前向星总结1. 邻接矩阵 思想&#xff1a; 利用二维数组 g[N][N] 存储所有的点到点的权值。其中 N 为点的数量&#xff0c;g[i][j] 表示点 i 到点 j 的权…

【C++】容器适配器

文章目录一. 什么是适配器?什么是容器适配器?二.理解容器适配器stack的模拟实现queue的模拟实现一. 什么是适配器?什么是容器适配器? 适配器是一种设计模式&#xff08;设计模式是一套被反复使用的&#xff0c;多数人知晓的&#xff0c;经过分类编目的&#xff0c;代码设计…

CAD未协调的新图层怎么处理?

在打开CAD图纸时&#xff0c;系统提示图形存在为协调的新图层是什么意思&#xff1f;所谓未协调图层&#xff0c;是指上次打印或者保存之类命令后新增的图层&#xff0c;大部分情况下增加新的外部参照时会把所有外部参照中的图层标记为未协调图层。CAD未协调的新图层怎么处理&a…

2023年底,我要通过这5点,实现博客访问量500W

说实话&#xff0c;这真的是一个非常高远的flag&#xff0c;因为我目前只有35W&#xff0c;但根据我2个月前还是12W的访问量&#xff0c;我觉得我还是可以拼一把的&#xff0c;在这里我想向大家分享一下我的计划&#xff0c;如何达成2023年底&#xff0c;博客访问量达到500W的K…

期刊会议排名、信息检索网站推荐、IEEE Latex模板下载(更新中...)

一.拿到一个期刊或论文&#xff0c;不知道他的影响因子、分区类型等等信息&#xff0c;可以使用以下几个网站搜索一下。二.一些会议期刊搜索1.国外The Latest Information Technology Conference and Journal List - Conference Partner&#xff08;信息技术最新国际会议和期刊…

Java程序员必知四种负载均衡算法

前言 一般来说&#xff0c;我们在设计系统的时候&#xff0c;为了系统的高扩展性&#xff0c;会尽可能的创建无状态的系统&#xff0c;这样我们就可以采用集群的方式部署&#xff0c;最终很方便的根据需要动态增减服务器数量。但是&#xff0c;要使系统具有更好的可扩展性&…

直观理解--马氏距离

首先我们很了解欧氏距离了&#xff0c;就是用来计算欧式空间&#xff08;就是我们常见的坐标系&#xff09;中两个点的距离的。 比如点 x(x1,…,xn)x (x_1,…,x_n)x(x1​,…,xn​) 和 y(y1,…,yn)y (y_1,…,y_n)y(y1​,…,yn​) 的欧氏距离为&#xff1a; d(x,y)(x1−y1)2(x2…

依靠小游戏带动产品增收,app运营这样做

大家都玩过小游戏吧&#xff1f;从小时候的4399游戏平台到现在的微信小游戏&#xff0c;尤其是风靡一时的“跳一跳”和“羊了个羊”都曾上榜热搜&#xff0c;让人印象深刻。在当下小游戏爆火社交平台的不断出现的背景下&#xff0c;小游戏的发展劲头更是强盛。 小游戏的吸引力在…

Memblaze发布大容量企业级SSD:支持32T最大容量,性能更强!

2023年1月10日 —— 今天&#xff0c;北京忆恒创源科技股份有限公司&#xff08;Memblaze&#xff09;正式发布 PBlaze6 6930 系列 PCIe 4.0 企业级 NVMe SSD。PBlaze6 6930 面向企业高性能业务应用开发&#xff0c;有着 1600K/680K IOPS 的 4K 随机读/写性能&#xff0c;具备更…

Mysql常见面试题

Mysql常见面试题汇总①⭐事务的基本特性和隔离级别⭐ACID靠什么保证⭐什么是MVCC⭐mysql的主从同步原理简述MyISAM和InnoDB的区别简述mysql中索引类型以及对数据库的性能影响⭐索引的基本原理Mysql聚簇索引和非聚簇索引的区别⭐B树和B树的区别&#xff0c;为什么Mysql使用B树My…

第04讲:Docker部署MySQL8

MySQL 的 Docker 镜像在 dockerhub 上的地址&#xff1a;https://hub.docker.com//mysql 当前&#xff08;2021-04-02&#xff09;的 latest 和 8.0.23 是同一个镜像 。另外&#xff0c;5.7 版本和 5.7.33 是同一个镜像 第1步&#xff1a;安装mysql 查询中央仓库 docker se…

Kestrel封装在WindowService中(.net5,.net6,.net7三个版本的介绍)

Kestrel封装在WindowServer中背景关于WindowsServer开发服务.NET5版本建项目添加Controller添加引用修改Startup.cs修改Program.cs配置Kestrel监听发布程序通过命令行创建服务关于SC命令启动服务查看效果测试效果.NET6错误1解决办法&#xff1a;错误2运行效果如下图.NET7版本&a…

千锋教育嵌入式物联网教程之系统编程篇学习-01

目录 课程视频链接 笔记目的 什么是系统编程 如何操作内核的系统调用 系统调用的分类​编辑 系统调用的返回值 系统调用IO函数 文件描述符 文件IO文件描述符与标准IO的文件指针对应关系 Man手册使用 open函数 函数调用失败打印错误 close函数 测试一个进程最多能产生多少个…

如何准备pmp考试?

一、考前五准备 1.知识准备&#xff1a;读透教材&#xff0c;仔细回顾知识点&#xff0c;明确知识框架&#xff0c;模考题考前正确率达到95%。 2.精神准备&#xff1a;明确目标&#xff0c;有信心&#xff0c;不要焦虑。 3.精力准备&#xff1a;科学安排考前的复习和休息时间…

【nvivo11plus教程】03_查询+自动编码

注&#xff1a;nvivo11也可以使用自动编码的。我是在第一次使用自动编码的时候&#xff0c;它弹出来一个界面让我下载安装包&#xff0c;但是网速特别慢&#xff0c;需要5、6个小时&#xff0c;然后我电脑开了一个晚上&#xff0c;第二天早上显示下载失败&#xff0c;但是可以使…

十一、路由

一、前端路由的概念与原理 1.1、什么是路由 路由&#xff08;英文&#xff1a;router&#xff09;就是对应关系。 1.2、SPA与前端路由 SPA 指的是一个web网站只有唯一的一个HTML页面&#xff0c;所有组件的展示与切换都在这唯一的一个页面内完成。此时&#xff0c;不同组件…