You need to enable JavaScript to run this app.
导航
Hint 语法使用
最近更新时间:2024.11.18 16:47:49首次发布时间:2024.04.17 10:14:15

本文介绍如何在 veDB MySQL 中使用 Hint 语法,以及相关的注意事项。

使用限制

仅读写终端(自动读写分离)地址支持 Hint 语法,只读终端地址和主节点终端地址不支持 Hint 语法,即使在 SQL 语句中添加了 Hint 语法,也不会生效。连接终端详情信息请参见关于连接终端

注意事项

  • Hint 的路由优先级别最高,不受事务导致的连接绑定、一致性级别和事务拆分等功能的约束,使用前请进行评估是否可用于业务。

  • MySQL 命令行默认会过滤 SQL 语句中的注释,因此使用 MySQL 命令行执行 Hint 语句时,需要在连接数据库时加上 -c 选项,例如 mysql -h<连接地址> -P<端口> -u<用户名> -p -c ,否则会因 Hint 被过滤导致 Hint 失效,详情请参见 MySQL官方文档

  • Hint 语句里不要有改变环境变量的语句,例如 /*FORCE_SLAVE*/ set names utf8; 等,这类语句可能导致后续的业务出错。也不要通过 Hint 设置用户变量,因为 Hint 指定后,只会对指定的节点设置变量,其它节点不会设置。如果使用不当,会导致同一前端连接的不同后端节点连接变量不一致。

使用说明

veDB MySQL 支持以下三种 Hint:

  • 在 SQL 语句中加上 /*FORCE_MASTER*/ 强制指定 SQL 在主节点执行。

    例如,select * from test; 正常情况下会被路由至只读节点,若在该语句中添加 Hint 语法,改为 /*FORCE_MASTER*/ select * from test,则该语句会被强制路由至主节点。

  • 在 SQL 语句中加上 /*FORCE_SLAVE*/ 强制指定 SQL 在只读节点执行。

    通过 /*FORCE_SLAVE*/ 指定时,若该读写终端下存在多个只读节点,则会按照负载均衡策略发送 SQL 至其中一个只读节点上执行。

  • 在 SQL 语句中加上 /*force_node=<节点ID>*/ 强制指定 SQL 在某节点执行。

    例如,/*force_node=vedbm-255rdo****-0*/ show processlist ,该 show processlist 命令只在 vedbm-255rdo****-0 节点上执行。如果该节点发生故障或指定的节点不存在,则返回报错 force hint server node is not found, please check

说明

  • Hint 语句不区分大小写,仅支持在 SQL 语句的句首使用 Hint。

  • 在一条 SQL 语句中同时使用若干个 Hint,则仅生效最后一个 Hint。例如 /*FORCE_MASTER*//*FORCE_SLAVE*//*force_node=vedbm-255rdo****-0*/,则生效 /*force_node=vedbm-255rdo****-0*/

  • 通过 /*FORCE_SLAVE*/ 或者 /*force_node=<节点ID>*/ 强制指定只读节点执行写操作或 DDL 操作,例如 insert、update、alter table 等,则会返回报错 The MySQL server is running with the --replica-mode option so it cannot execute this statement

示例

  • 如果使用了 Hint 指定节点执行 PREPARE ,则 EXECUTE 也只能在对应的节点上执行。

    MySQL [test]> /*FORCE_MASTER*/ PREPARE selecttest from 'select * from test where id=?';
    Query OK, 0 rows affected (0.00 sec)
    Statement prepared
    
    MySQL [test]> set @a=555;
    Query OK, 0 rows affected (0.01 sec)
    
    # 指定在主节点执行命令或不指定节点,成功。
    MySQL [test]> execute selecttest using @a;
    +------+------+
    | id   | code |
    +------+------+
    |  555 | 05   |
    +------+------+
    1 row in set (0.01 sec)
    MySQL [test]> /*FORCE_MASTER*/ execute selecttest using @a;
    +------+------+
    | id   | code |
    +------+------+
    |  555 | 05   |
    +------+------+
    1 row in set (0.00 sec)
    
    # 指定在只读节点执行命令,失败。
    MySQL [test]> /* force_node=vedbm-apdm3ztf****-2 */ execute selecttest using @a;
    ERROR 1243 (HY000): Unknown prepared statement handler (selecttest) given to EXECUTE
    
  • 通过 Hint 指定 set 在具体的节点上执行,则也只能在对应的节点上使用该变量。

    MySQL [test]> /* force_node=vedbm-apdm3ztf****-1 */ set @a=111;
    Query OK, 0 rows affected (0.01 sec)
    
    MySQL [test]> /* force_node=vedbm-apdm3ztf****-1 */ select @a;
    +------+
    | @a   |
    +------+
    |  111 |
    +------+
    1 row in set (0.00 sec)
    
    MySQL [test]> /*FORCE_MASTER*/ select @a;
    +------+
    | @a   |
    +------+
    | NULL |
    +------+
    1 row in set (0.00 sec)
    
  • 事务中 Hint 的优先级最高。

    MySQL [test]> begin;
    Query OK, 0 rows affected (0.01 sec)
    
    MySQL [test]> INSERT INTO `test` VALUES ('222', '02');
    Query OK, 1 row affected (0.01 sec)
    
    MySQL [test]> /*FORCE_SLAVE*/ select * from test;
    +------+------+
    | id   | code |
    +------+------+
    |  111 | 01   |
    +------+------+
    1 row in set (0.01 sec)
    
    MySQL [test]> /*FORCE_MASTER*/ select * from test;
    +------+------+
    | id   | code |
    +------+------+
    |  111 | 01   |
    |  222 | 02   |
    +------+------+
    2 rows in set (0.01 sec)
    
    MySQL [test]> INSERT INTO `test` VALUES ('333', '03');
    Query OK, 1 row affected (0.01 sec)
    
    MySQL [test]> /*FORCE_MASTER*/ select * from test;
    +------+------+
    | id   | code |
    +------+------+
    |  111 | 01   |
    |  222 | 02   |
    |  333 | 03   |
    +------+------+
    3 rows in set (0.01 sec)
    
    MySQL [test]> /*FORCE_SLAVE*/ select * from test;
    +------+------+
    | id   | code |
    +------+------+
    |  111 | 01   |
    +------+------+
    1 row in set (0.00 sec)
    
    MySQL [test]> commit;
    Query OK, 0 rows affected (0.01 sec)
    
    MySQL [test]> /*FORCE_SLAVE*/ select * from test;
    +------+------+
    | id   | code |
    +------+------+
    |  111 | 01   |
    |  222 | 02   |
    |  333 | 03   |
    +------+------+
    3 rows in set (0.01 sec)