
ShardingSphere分库分表schema名称导致NPE问题排查记录
前段时间把 ShardingSphere 升级到了 5.1.1 版本,奈何官方版本升级太快跟不上速度,这不最近又发现了一个 BUG。
问题现象
数据库做了分库分表,在需要查询多表数据进行 merge 的时候发生了一个 NPE 的异常。
问题排查
跟踪到报错的地方,发现是这个地方的schema
是个null
,从而引发了 NPE。
一路往上看代码,最终定位到了这个获取schema
的地方,也就是元数据去getDefaultSchema
获取默认的schema
名称改的时候拿到了一个空值。
进入这个方法后发现通过schema
去schemas
这个map
里获取名称的时候是个空值,debug
到这个地方其实发现了问题。
我们的schemaName
配置的是orderTrade
包含有大写字符的,所以name
传进来的是orderTrade
,但是问题是这个schemas
确是ordertrade
。
所以很显然,这里获取不到正确的schema
名称,导致了这个 NPE 的异常,那么问题是这个schemas
是怎么加载进来的呢?
我们发现schemas
是在创建元数据的时候,通过构造函数赋值的,那么只要找到这个赋值的地方应该就能发现问题了。
通过一番查找,找到了调用的地方,这个schemas
值就是databaseMap
中的value
,那么我们要继续看这个databaseMap
是如何初始化来的。
继续看源码,找到了databaseMap
进行初始化的地方,原来是通过DatabaseLoader
去加载元数据的时候初始化的,那么这个load
方法是怎么处理的呢?
从代码来看他包含了两部分的信息,第一个是我们自己通过schema
配置的一些分库分表的配置信息,另外一部分则是数据库默认的一些表的元数据,比如mysql
、information_schema
这些,那我们只要看自己配置的那部分就可以了,也就是SchemaLoader.load(dataSourceMap, rules, props)
方法。
看他实际上就是获取数据库是什么类型,比如mysql
,然后去加载表的元数据,最后new
出来ShardingSphereSchema
,直接看最后的new
部分代码就行了。
进入这个方法,瞬间就真相大白了,原来在put
的时候对所有的schemaName
进行了小写处理,所以在最上面我们去get
的时候肯定会拿到一个空值,最终导致merge
的时候发生了 NPE 异常。
解决方案
现在问题原因已经发现了,那么该如何解决呢?总不能不让别人配置的时候不让写大写吧,本着能不能白嫖一个 PR 的想法,又去给 Sharding 提了一个 Issue。
就我点了根烟的功夫,回头就给我回复说新版本已经修复了,希望落空了,修复方案就是查询的时候也做小写处理了,好吧,那就这样吧。
文章转载自公众号:艾小仙
