首页>>后端>>Spring->实施sharding

实施sharding

时间:2023-11-29 本站 点击:0

在《“分库分表" ?选型和流程要慎重,否则会失控》中,我们谈到处于驱动层的sharding-jdbc。开源做到这个水平,已经超棒了,不像tddl成了个太监。但还是有坑。

不过不能怪框架,毕竟有些sql,只有程序和鬼能懂。

<selectid="getCodes"resultMap="BaseResultMap"parameterType="java.util.Map"><foreachcollection="orderCodes"index="index"item="item"open=""separator="unionall"close="">select<includerefid="Base_Column_List"/>fromorderwhereorderCode=#{item}</foreach></select>

不支持的操作

分库分表后,就成为了一个阉割型的数据库。很多sql的特性是不支持的,需要使用其他手段改进。以下以3.0.0版本进行描述。

distinct

sharding-jdbc不支持distinct,单表可使用group by进行替代。多表联查可使用exists替代

selectDISTINCTa,b,c,dfromtablewheredf=0

改成

selecta,b,c,dfromtablewheredf=0groupbya,b,c,d

having

sharding-jdbc不支持having,可使用嵌套子查询进行替代

union

sharding-jdbc不支持union(all),可拆分成多个查询,在程序拼接

关于子查询

sharding-jdbc不支持在子查询中出现同样的表,如 以下可以==>

SELECTCOUNT(*)FROM(SELECT*FROMt_ordero)

以下报错==>

SELECTCOUNT(*)FROM(SELECT*FROMt_orderoWHEREo.idIN(SELECTidFROMt_orderWHEREstatus=?))

由于归并的限制,子查询中包含聚合函数目前无法支持。

mybatis 注释

sharding-jdbc不支持sql中的<!-- – >注释,如必须使用则写在sql前,或使用/* */

不支持text字段

改为varchar,好几年的bug了,但是没改

case when

某些case when是不支持的,比如不在聚合函数中的case when,需要将这部分sql逻辑写到程序里。

case when不应该是DBA禁用的函数么?我们在填坑

一些奇怪的反应

这个是可以的

selecta-bfromdual

但这个不可以...

select(a-b)cfromdual

sharding 也不支持如下形式查询,解析紊乱

and(1=1or1=1)

关于分页

严禁无切分键的深分页!因为会对SQL进行以下解释,然后在内存运行。

select*fromalimit10offset1000

=======>

ActualSQL:db0:::select*fromalimit1010offset0

关于表名

表名需与sharding-jdbc配置一致,推荐均为小写。因为路由是放在hashmap里的,没有区分大小写...所以如果你的sql写错了会找不到。

配置冗余

每一张表都要配置路由信息才能够被正确解析,如果你库里的表太多,这个配置文件会膨胀的特别大,上千行也是有的。所以在yml中可以将配置文件分开。

selectDISTINCTa,b,c,dfromtablewheredf=00

如何扫多库

比如一些定时任务,需要遍历所有库。

方法1:遍历所有库

使用以下方式拿到真正的数据库列表

selectDISTINCTa,b,c,dfromtablewheredf=01

然后在每一个库上执行扫描逻辑。这种情况下无法使用mybaits,需要写原生jdbc

方法2:根据切分键遍历

此种方法会拿到一个切分键的列表,比如日期等。然后通过遍历这个列表执行业务逻辑。此种方法在列表特别大的时候执行会比较缓慢。

如何验证

分库分表很危险,因为一旦数据入错库,后续的修理很麻烦。所以刚开始可以将路由信息指向到源表,即:只验证SQL路由的准确性。等待所有的SQL路由都验证通过,再切换到真正的分库或者表。

确保能够打印SQL

selectDISTINCTa,b,c,dfromtablewheredf=02

将sql打印到单独的文件(logback)

selectDISTINCTa,b,c,dfromtablewheredf=03

写一些脚本进行SQL文件的验证。我这里有个通用的,你可以改下你的逻辑。

selectDISTINCTa,b,c,dfromtablewheredf=04

其他

你可能要经常切换路由,所以某些时候路由信息要放在云端能够动态修改。

哦对了,我这里还有一段开发阶段的验证代码,能让你快速验证SQL能否正确解析。

selectDISTINCTa,b,c,dfromtablewheredf=05

开源一套以教学为目的系统,欢迎star:github.com/xjjdog/bcmall。它包含ToB复杂业务、互联网高并发业务、缓存应用;DDD、微服务指导。模型驱动、数据驱动。了解大型服务进化路线,编码技巧、学习Linux,性能调优。Docker/k8s助力、监控、日志收集、中间件学习。前端技术、后端实践等。主要技术:SpringBoot+JPA+Mybatis-plus+Antd+Vue3

有SQL规范的团队是幸福的,分库分表简单的很。而动辄几百行,有各种复杂函数的SQL,就只能一步一个坑了。

话说回来,如果不是为了事务这个特性,为了支持老掉牙的业务,谁会用这分完后人不像人,鬼不像鬼的东西。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。


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