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]

Reply via email to