lliyuu520 opened a new issue, #39875:
URL: https://github.com/apache/shardingsphere/issues/39875
### Which version of ShardingSphere did you use?
5.2.1 (reproduced and re-verified against 5.5.3 source)
ShardingSphere-JDBC, Cluster mode with ZooKeeper governance
### Which project did you use ShardingSphere-JDBC or ShardingSphere-Proxy?
ShardingSphere-JDBC
### Expected behavior
Sharding tables whose actual-data-node suffix is **alphanumeric** (e.g.
`t_order_mgm`,
`t_order_wz3k9d`) should be routed and validated the same way purely numeric
suffixes
(`t_order_0`, `t_order_2023`) are.
### Actual behavior
`TableRule#createTableDataNode()` (5.5.x:
`ShardingTable#createTableDataNode()`) derives the
table prefix by stripping a suffix from the first actual table name using
`DATA_NODE_SUFFIX_PATTERN`. With a non-numeric suffix the pattern does not
match, `replaceAll("")`
returns the input unchanged, and the computed prefix becomes the **whole
actual table name**
(with the sharding suffix still in it). The computed `suffixMinLength` is
consequently 0 or
negative.
Since `DataNodeInfo#getPrefix()` is consumed by
`ShardingRule#isValidActualTableName()` and
`ShardingRule#getAlgorithmExpression()` during binding table validation (the
`ShardingRule`
constructor asserts
`Preconditions.checkArgument(isValidBindingTableConfiguration(...))`),
the wrong prefix breaks binding table validation/derivation.
In our production environment we expanded a single sharded logic table into
several sharded tables
and configured them as binding tables. After deployment, queries were no
longer routed per tenant
but broadcast to *all* tenant tables, which saturated database
CPU/connections and took the service
down for hours.
### Reason analyze (If you can)
Current code (5.5.3,
`org.apache.shardingsphere.sharding.constant.ShardingTableConstants`):
public static final Pattern DATA_NODE_SUFFIX_PATTERN =
Pattern.compile("\\d+$");
and `ShardingTable#createTableDataNode()`:
String tableName = actualDataNodes.iterator().next().getTableName();
String prefix = tableName.startsWith(logicTable)
? logicTable +
DATA_NODE_SUFFIX_PATTERN.matcher(tableName.substring(logicTable.length())).replaceAll("")
: DATA_NODE_SUFFIX_PATTERN.matcher(tableName).replaceAll("");
int suffixMinLength = actualDataNodes.stream()
.map(each -> each.getTableName().length() - prefix.length())
.min(Comparator.comparing(Integer::intValue)).orElse(1);
return new DataNodeInfo(prefix, suffixMinLength, DEFAULT_PADDING_CHAR);
The pattern only matches a trailing run of digits. Any suffix containing
letters — which is common
when the sharding suffix is a tenant key, a region code or a business code
rather than a sequence
number — never matches.
Note this pattern has already regressed once in a different direction: 5.2.1
used
`(\d+[\-_]){0,}(\d+$)`, which supported multi-segment numeric suffixes such
as `t_order_2023_01`,
while 5.3.x/5.4.x/5.5.x use `\d+$`, which does not. That regression was
reported before in
#32792 and the issue was closed as stale without a fix; the pattern is still
`\d+$` in 5.5.3, so
the advice given there ("try the newer version") does not resolve it either.
### Steps to reproduce the issue
1. Use an alphanumeric sharding suffix:
spring:
shardingsphere:
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds0.t_order_$->{['mgm','wz3k9d']}
table-strategy:
standard:
sharding-column: tenant_id
sharding-algorithm-name: tenant_algorithm
2. Provide a `StandardShardingAlgorithm` that routes by the `tenant_id`
value to the matching
actual table.
3. Put that table together with another table into `binding-tables`.
4. Start the application and run a query joining the bound tables.
Expected: the query is routed to the single matching shard.
Actual: the derived prefix is the full table name, so binding
validation/derivation is wrong.
### Anything else?
Our workaround is to override the class inside our own project source tree
(`src/main/java/org/apache/shardingsphere/sharding/rule/TableRule.java`,
taking classpath
precedence over the jar) and relax the pattern to `[a-zA-Z0-9]+$`.
A more general fix would be to accept any trailing alphanumeric run, e.g.
`Pattern.compile("[a-zA-Z0-9]+$")`, or better, to stop guessing the prefix
with a regex and derive
it from the logic table name when the actual table name follows the
`<logicTable>_<suffix>`
convention (falling back to the current behaviour otherwise).
Note that `[a-zA-Z0-9]+$` would still not handle the multi-segment numeric
case from #32792
(`t_order_2023_01` would still yield the prefix `t_order_2023_`), so a
configurable
`actualTablePrefix` — the property that was removed and that #32792 asked
for — may be the more
robust long-term option.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail:
[email protected]
For queries about this service, please contact Infrastructure at:
[email protected]