ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 分库分表 ## 说明 Zebra 微服务框架引入了 [ShardingSphere](https://shardingsphere.apache.org/) 的 Sharding-JDBC 组件来支持分库分表功能。 Sharding-JDBC 相关说明请参考[官方文档](https://shardingsphere.apache.org/document/current/en/overview)。 ## 样例 参考 [https://gitee.com/gszebra/zebra/tree/master/zebra-sample/db-sharding](https://gitee.com/gszebra/zebra/tree/master/zebra-sample/db-sharding) ## 开发 ### 依赖引入 引入如下依赖 ```markup <dependency> <groupId>com.guosen</groupId> <artifactId>zebra-database</artifactId> <version>${zebra.version}</version> </dependency> ``` _注:将 ${zebra.version} 替换为使用的 Zebra 版本_ ### 配置 #### 配置样例 ```text zebra.database.url[0]=jdbc:sqlserver://ip:port;database=dbName01 zebra.database.username[0]=sa zebra.database.pwd[0]=password zebra.database.dataSourceName[0]=ds0 zebra.database.url[1]=jdbc:sqlserver://ip:port;database=dbName02 zebra.database.username[1]=sa zebra.database.pwd[1]=password zebra.database.dataSourceName[1]=ds1 zebra.database.shardingcfg.shardDs01.datasource.names=ds0,ds1 zebra.database.shardingcfg.shardDs01.basePackage=com.guosen.zebra.demo.sharding.dao zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.actual-data-nodes=ds$->{0..1}.t_credit_$->{2019..2039}0$->{1..9},ds$->{0..1}.t_credit_$->{2019..2039}$->{10..12} zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.table-strategy.inline.sharding-column=m_month zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.table-strategy.inline.algorithm-expression=t_credit_$->{m_month} zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.database-strategy.inline.sharding-column=fund_id zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.database-strategy.inline.algorithm-expression=ds$->{fund_id % 2} zebra.database.shardingcfg.shardDs01.props.sql.show=true ``` 如上图,上述配置项配置了一个逻辑表 t\_credit 的分库分表规则。 三个关键的配置项说明如下: * **zebra.database.shardingcfg.shardDs01.datasource.names** 组成分库分表的原始数据源名称,一个到多个,以逗号分隔。 比如上述配置 ```text zebra.database.shardingcfg.shardDs01.datasource.names=ds0,ds1 ``` **ds0** 对应数据源配置项 _zebra.database.dataSourceName\[0\]=_**ds0** 的值。 **ds1** 对应数据源配置项 _zebra.database.dataSourceName\[1\]=_**ds1** 的值。 * **t\_credit.database-strategy相关的配置项** 配置了分库规则 t\_credit.database-strategy.inline.algorithm-expression=ds$-&gt;{fund\_id%2}表示根据 SQL 中的 fund\_id 字段对 2 取模来确定该 SQL 要路由到哪个数据源对应的数据库执行。 比如 SQL ```sql select * from t_credit where m_month = 201908 and fund_id = 8888 ``` 那么最后分库 SQL 会变为(仍和上面分表 SQL 一致) ```sql select * from t_credit_201908 where m_month = 201908 and fund_id = 8888 ``` 路由到的数据源为ds$-&gt;{8888%2} = ds0,该 SQL 会被路由到 ds0 对应的数据库中执行。 * **t\_credit.table-strategy 相关的配置项** 配置了分表规则 t_credit.table-strategy.inline.algorithm-expression=t\_credit_$-&gt;{m\_month} 表示根据SQL中 **m\_month** 进行分表。 比如 SQL ```sql select * from t_credit where m_month = 201908 and fund_id = 8888 ``` 那么最后分表 SQL 会变为 ```sql select * from t_credit_201908 where m_month = 201908 and fund_id = 8888 ``` #### 配置说明 和 Sharding-JDBC 基本保持一致,但是配置前缀修改为 zebra.database.shardingcfg._${分库分表数据源名称}_ 关键配置项 | 配置项 | 说明 | | :--- | :--- | | datasources.name | 组成分库分表的原始数据源名称,一个到多个,以逗号分隔。 原始数据源名称为 **zebra.database.dataSourceName\[k\]=dsName** 对应的值 | | basePackage | 分库分表对应 MyBatis 的 basePackage,此为 Zebra 定制配置项 | | tables.tableName.actual-data-nodes | 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。缺省表示使用已知数据源与逻辑表名称生成数据节点。用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况 | | props.sql.show | 表示是否开启分库分表SQL打印。 true : 开启; false : 不开启(默认值) 开启时,会打印出逻辑SQL和分库分表之后实际的SQL。一般用于开发阶段的问题定位。生产环境不要打开此开关 | | 其他配置项 | 参考 [ShardingSphere SpringBoot 配置](https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/configuration/config-spring-boot/),将前缀“spring.shardingsphere”修改为 zebra 的前缀“zebra.database.shardingcfg.${分库分表数据源名称}” 即可。 | ### 代码 代码开发和已有 Zebra 数据库开发方式保持一致。但是相关业务 SQL **必须带上分库分表字段**,如果没有带,则 Sharding-JDBC 会扫描配置的所有表,速度很可能就非常慢。 ## 相关限制 参考官方文档 1. [不支持的sql](https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/#不支持的sql) 2. [JDBC不支持项](https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/unsupported-items/) 下面仅列出 Zebra 开发验证时发现的问题。 ### SQLServer 的限制 如果使用的数据为 SQLServer,则应该注意如下问题。 * 分页 Sharding-JDBC 对 SQLServer 的分页支持不完整,官网宣称可以 2 种分页方式:TOP + ROWNUMBER和 OFFSET FETCH。经验证,2 种都有不同程度的 bug。 分页查询当前实际只支持 OFFSET FETCH 方式,必须同时带上包含了分表分库字段的 where 条件,若不带分库分表字段条件,则返回的数据可能会比实际的多。 已经在 GitHub 上面提了 issue 1. [SQLServer OFFSET FETCH pagination return wrong results](https://github.com/apache/incubator-shardingsphere/issues/2987) 2. [SQLServer TOP + ROW\_NUMBER\(\) pagination SQL error](https://github.com/apache/incubator-shardingsphere/issues/2989) * 字段不能为 SQLServer 保留字 当字段名称和保留字一样时,Sharding-JDBC 解析业务 SQL 会报错,但仅仅只是打印错误信息,不终止后续步骤,分库分表会失效,变成在逻辑表的所有物理表上执行 SQL。所以使用分库分表的表,一定不能使用保留字作为字段名称(其实不使用分库分表也应该遵循这个规则)。