全部产品
Search
文档中心

指定分库执行SQL

更新时间: 2020-08-18

在使用 DRDS 的过程中,如果遇到某个 DRDS 不支持的 SQL 语句,可以通过 DRDS 提供的NODE HINT,直接将 SQL 下发到一个或多个分库上去执行。此外如果需要单独查询某个分库或者已知分库的某个分表中的数据,也可以使用NODE HINT,直接将 SQL 语句下发到分库中执行。

注意事项

  • 从版本 5.4.1 开始,DRDS 在拆分表的物理表名中增加了4个字符的随机串,请务必使用 SHOW TOPOLOGY 命令获取逻辑表拓扑和实际的物理表名。
  • 从版本 5.4.4 开始,DRDS 提供开关来控制拆分表的物理表名中是否包含随机串,默认为开启,可以在控制台“参数设置”的数据库级别参数中,将“是否启用随机物理表名 ENABLE_RANDOM_PHY_TABLE_NAME”改为 false 来关闭,也可以用 HINT 来实现语句级别的控制:/*+TDDL:cmd_extra(ENABLE_RANDOM_PHY_TABLE_NAME=FALSE)*/

  • DRDS 自定义 HINT 支持 /*+TDDL:hint_command*//!+TDDL:hint_command*/ 两种格式。

  • 如果使用 /*+TDDL:hint_command*/ 格式,在使用 MySQL 官方命令行客户端执行带有 DRDS 自定义 HINT 的 SQL 时,请在登录命令中加上 -c 参数。否则,由于 DRDS 自定义 HINT 是以 MySQL 注释 形式使用的,该客户端会将注释语句删除后再发送到服务端执行,导致 DRDS 自定义 HINT 失效。具体请参见MySQL 官方客户端命令

语法

NODE HINT支持通过分片名指定 SQL 在分库上执行。其中分片名是 DRDS 中分库的唯一标识,可以通过 SHOW NODE 语句得到。

通过分库名指定 SQL 在分库上执行分两种使用方式,分别是指定 SQL 在某个分库上执行和指定 SQL 在多个分库上执行。

如果在目标表包含 Sequence 的 INSERT 语句上使用了指定分库的 HINT,那么 Sequence 将不生效。更多相关信息,请参见Sequence 限制及注意事项

  • 指定 SQL 在某个分库上执行:

    1. /*+TDDL:node('node_name')*/

    node_name 为分片名,通过这个 DRDS 自定义 HINT,就可以将 SQL 下发到node_name对应的分库中执行。

  • 指定 SQL 在多个分库上执行:

    1. /*+TDDL:node('node_name'[,'node_name1','node_name2'])*/

    在参数中指定多个分片名,将 SQL 下发到多个分库上执行,分片名之间使用逗号分隔。

    • 使用该自定义 HINT 时,DRDS 会将 SQL 直接下发到分库上执行,所以在 SQL 语句中,表名必须是该分库中已经存在的表名。
    • NODE HINT支持 DML、DDL、DAL 语句。

示例

对于名为 drds_test 的 DRDS 数据库,SHOW NODE 的结果如下:

  1. mysql> SHOW NODE\G
  2. *************************** 1. row ******************
  3. ID: 0
  4. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0000_RDS
  5. MASTER_READ_COUNT: 212
  6. SLAVE_READ_COUNT: 0
  7. MASTER_READ_PERCENT: 100%
  8. SLAVE_READ_PERCENT: 0%
  9. *************************** 2. row ******************
  10. ID: 1
  11. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0001_RDS
  12. MASTER_READ_COUNT: 29
  13. SLAVE_READ_COUNT: 0
  14. MASTER_READ_PERCENT: 100%
  15. SLAVE_READ_PERCENT: 0%
  16. *************************** 3. row ******************
  17. ID: 2
  18. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0002_RDS
  19. MASTER_READ_COUNT: 29
  20. SLAVE_READ_COUNT: 0
  21. MASTER_READ_PERCENT: 100%
  22. SLAVE_READ_PERCENT: 0%
  23. *************************** 4. row ******************
  24. ID: 3
  25. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0003_RDS
  26. MASTER_READ_COUNT: 29
  27. SLAVE_READ_COUNT: 0
  28. MASTER_READ_PERCENT: 100%
  29. SLAVE_READ_PERCENT: 0%
  30. *************************** 5. row ******************
  31. ID: 4
  32. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0004_RDS
  33. MASTER_READ_COUNT: 29
  34. SLAVE_READ_COUNT: 0
  35. MASTER_READ_PERCENT: 100%
  36. SLAVE_READ_PERCENT: 0%
  37. *************************** 6. row ******************
  38. ID: 5
  39. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0005_RDS
  40. MASTER_READ_COUNT: 29
  41. SLAVE_READ_COUNT: 0
  42. MASTER_READ_PERCENT: 100%
  43. SLAVE_READ_PERCENT: 0%
  44. *************************** 7. row ******************
  45. ID: 6
  46. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0006_RDS
  47. MASTER_READ_COUNT: 29
  48. SLAVE_READ_COUNT: 0
  49. MASTER_READ_PERCENT: 100%
  50. SLAVE_READ_PERCENT: 0%
  51. *************************** 8. row ******************
  52. ID: 7
  53. NAME: DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0007_RDS
  54. MASTER_READ_COUNT: 29
  55. SLAVE_READ_COUNT: 0
  56. MASTER_READ_PERCENT: 100%
  57. SLAVE_READ_PERCENT: 0%
  58. 8 rows in set (0.02 sec)

可以看到每个分库都有 NAME 这个属性,这就是分库的分片名。每个分片名都唯一对应一个分库名,比如DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0003_RDS这个分片名对应的分库名是drds_test_vtla_0003。得到了分片名,就可以使用 DRDS 的自定义 HINT 指定分库执行 SQL 语句了。

  • 指定 SQL 在第 0 个分库上执行:

    1. SELECT /*TDDL:node('DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0000_RDS')*/ * FROM table_name;
  • 指定 SQL 在多个分库上执行:

    1. SELECT /*TDDL:node('DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0000_RDS','DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0006_RDS')*/ * FROM table_name;

    这条 SQL 语句将在DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0000_RDSDRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0006_RDS这两个分片上执行。

  • 查看 SQL 在第 0 个分库上物理执行计划:

    1. /*TDDL:node('DRDS_TEST_1473471355140LRPRDRDS_TEST_VTLA_0000_RDS')*/ EXPLAIN SELECT * FROM table_name;