hhdb数据库介绍(9-10)

计算节点特色功能

HHDB Server在基于关系集群数据库设计的基础上,提供了一些扩展的功能,方便进行使用和管理。

DNID

DNID是数据节点DATANODE_ID的缩写

在计算节点上可以使用DNID作为WHERE子句中的过滤条件,以及在SELECT语句中作为查询项;也可以在结果集中显示每行结果的DNID(数据节点)。

1.在SELECT、UPDATE、DELETE子句中,使用DNID字段

执行该SELECT语句,计算节点将会返回分片表customer在数据节点ID为1上的数据。

SELECT * FROM customer WHERE dnid=1;

执行该DELETE语句,计算节点将会删除分片表customer在数据节点ID为1,字段ID等于3的数据。

DELETE FROM customer WHERE dnid=1 AND id=3;

执行该DELETE语句,计算节点将会修改分片表customer在数据节点ID为1,字段name等于'a'的数据。

UPDATE customer SET id=4 WHERE dnid=1 AND name='a';

2.执行SELECT语句使用DNID作为查询项

执行该SELECT语句,计算节点将会在结果集里显示所有结果的dnid值/

SELECT *,dnid FROM tab_name;

3. 在结果集中显示DNID

登录到计算节点以后,执行SET SHOW_DNID=1语句,计算节点将会在SELECT语句中返回每一行结果的DNID(数据节点ID)。

mysql> set show_dnid=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from customer where id in (77,67,52,20);
+----+--------+-------------+------------+-----------+------+-------------+------+
| id | name   | telephone   | provinceid | province  | city | address     | DNID |
+----+--------+-------------+------------+-----------+------+-------------+------+
| 52 | 马深圳 | 13912340052 | 7          | Guangdong | 深圳 | 某某街某某号| 13   |
| 77 | 郝上海 | 13912340077 | 25         | Shanghai  | 上海 | 某某街某某号| 14   |
| 20 | 许重庆 | 13912340020 | 4          | Chongqing | 重庆 | 某某街某某号| 12   |
| 67 | 岑南昌 | 13912340067 | 17         | Jiangxi   | 南昌 | 某某街某某号| 15   |
+----+--------+-------------+------------+-----------+------+-------------+------+
4 rows in set (0.00 sec)

图中结果分别显示了数据节点ID为12,13,14,15的数据行。

执行SET SHOW_DNID=1语句,查询全局表时,计算节点将会在SELECT语句中返回每一行结果的DNID(GLOBAL)。

mysql> set show_dnid=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tb_quan;
+----+---+------+--------+
| id | a | b    | DNID   |
+----+---+------+--------+
| 1  | 1 | 1.10 | GLOBAL |
| 2  | 2 | 1.20 | GLOBAL |
| 3  | 3 | 1.30 | GLOBAL |
+----+---+------+--------+

SET SHOW_DNID=0,将取消在结果集中显示DNID列。

mysql> set show_dnid=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from customer where id in (77,67,52,20);
+----+--------+-------------+------------+-----------+------+-------------+
| id | name   | telephone   | provinceid | province  | city | address     |
+----+--------+-------------+------------+-----------+------+-------------+
| 52 | 马深圳 | 13912340052 | 7          | Guangdong | 深圳 | 某某街某某号|
| 77 | 郝上海 | 13912340077 | 25         | Shanghai  | 上海 | 某某街某某号|
| 20 | 许重庆 | 13912340020 | 4          | Chongqing | 重庆 | 某某街某某号|
| 67 | 岑南昌 | 13912340067 | 17         | Jiangxi   | 南昌 | 某某街某某号|
+----+--------+-------------+------------+-----------+------+-------------+
4 rows in set (0.00 sec)

4.DNID的限制

DNID字段为计算节点的保留字段,禁止在业务表中使用DNID字段,在SQL语句中使用DNID作为别名。

DNID只适用于SELECT,UPDATE,DELETE的简单单表语句;并且,DNID只能作为WHERE子句的过滤条件,不能在ORDER BY,GROUP BY,HAVING中使用DNID字段;同样,不支持在JOIN语句、UNION/UNION ALL、子查询中使用DNID;不支持在函数,表达式中使用DNID字段。

HINT

在计算节点使用HINT语法,可绕过HHDB Server解析器,直接在指定数据节点上执行任意SQL语句。计算节点支持两种方式的HINT语法:

5.在HINT中使用DNID(数据节点ID):

语法:

/*!hotdb:dnid = dnid_value*/ 要执行的SQL

注意
dnid_value的值为某个数据节点的ID号。用户可以替换dnid_value的值来指定具体的分片节点。

例如:

/*!hotdb:dnid = 1*/select * from customer where age > 20;

该语句将在数据库节点1上执行。用户可以通过关系集群数据库可视化管理平台中的"数据节点"页面,找到数据节点ID为1的存储节点名称,并在"存储节点"页面中搜索指定的存储节点名称,即可定位到实际的数据库。

若set show_dnid=1,同时在HINT中使用DNID,执行SQL语句得到的结果集中将增加一列虚拟列DN_INFO显示对应返回后的存储节点信息。

/*!hotdb:dnid = all*/select * from departments limit 1;
+---------------+-----------------+------------+-------------+-----------------------------------------------------------------------+
| DEPARTMENT_ID | DEPARTMENT_NAME | MANAGER_ID | LOCATION_ID | DN_INFO                                                               |
+---------------+-----------------+------------+-------------+-----------------------------------------------------------------------+
|            20 | Marketing       |        201 |        1800 | [id:1,nodeId:1 192.168.210.76:3307/db01_ora status:1,charset:utf8mb4] |
|            10 | Administration  |        200 |        1700 | [id:2,nodeId:2 192.168.210.76:3307/db02_ora status:1,charset:utf8mb4] |
+---------------+-----------------+------------+-------------+-----------------------------------------------------------------------+
2 rows in set (0.00 sec)

6.在HINT中使用DSID(存储节点ID):

HINT语句支持指定datasource_id跳过计算节点直接向存储节点发送语句。可利用服务端口命令查看存储节点datasource_id:

语法:

SHOW [full] HOTDB {datasources} [LIKE 'pattern' | WHERE expr]

示例:

hotdb> show hotdb datasources where datasource_id like '22';
+-------------+---------------+------------------------------+-----------------+-------------------+----------------+------+----------+--------+
| DATANODE_ID | DATASOURCE_ID | DATASOURCE_NAME              | DATASOURCE_TYPE | DATASOURCE_STATUS | HOST           | PORT | SCHEMA   | IDC_ID |
+-------------+---------------+------------------------------+-----------------+-------------------+----------------+------+----------+--------+
| 23          | 22            | 192.168.210.41_3308_hotdb157 | 1               | 1                 | 192.168.210.41 | 3308 | hotdb157 | 1      |
+-------------+---------------+------------------------------+-----------------+-------------------+----------------+------+----------+--------+

指定具体datasource_id且不写binlog:

/*!hotdb:dsid=nobinlog:datasource_id*/要执行的SQL

注意
datasource_id的值为某个存储节点的ID,可以指定多个节点用英文","隔开。此语法不会将执行的语句记入存储节点二进制日志文件binlog中,若使用不当,可能存在导致双主数据不一致、GTID位置错乱的情况,使用时需谨慎。

示例:

在datasource_id=22的存储节点上创建用户hpt,并且不写binlog

hotdb> /*!hotdb:dsid=nobinlog:22*/create user 'hpt'@'%' identified by '123456';

Query OK, 0 rows affected (0.00 sec)

在datasource_id=22的存储节点上设置参数

hotdb> /*!hotdb:dsid=nobinlog:22*/set wait_timeout=1200;

Query OK, 0 rows affected (0.01 sec)

hotdb> /*!hotdb:dsid=nobinlog:22*/show variables like 'wait_timeout';

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 1200  |
+---------------+-------+
1 row in set (0.01 sec)

指定所有datasource_id且不写binlog:

/*!hotdb:dsid=nobinlog:all*/要执行的SQL

注意
all为所有存储节点(包括容灾模式下容灾机房存储节点),此语法不会将执行的语句记入二进制日志文件binlog中。

示例:

在所有存储节点上更新table1表且不写binlog:

/*!hotdb:dsid=nobinlog:all*/update table1 set name='hotdb' where id=100;

在所有存储节点上设置参数。

hotdb> /*!hotdb:dsid=nobinlog:all*/set wait_timeout=1200;

Query OK, 0 rows affected (0.00 sec)

hotdb> /*!hotdb:dsid=nobinlog:all*/show variables like 'wait_timeout';

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
| wait_timeout  | 1200  |
+---------------+-------+
8 rows in set (0.00 sec)

指定具体datasource_id且写binlog的语法:

/*!hotdb:dsid=datasource_id*/要执行的SQL

注意
此语法会将执行的语句记入对应存储节点的二进制日志文件binlog中。同时操作具有复制关系的存储节点时需要谨慎处理,以免导致主从复制同步异常。

指定所有datasource_id且写binlog的语法:

/*!hotdb:dsid=all*/要执行的SQL

注意
若多个存储节点分布在同实例上,使用HINT中datasource_id也需单独指定存储节点执行。

7.在HINT中使用分片字段:

语法:

/!hotdb:table = table_name:column_value*/ 要执行的SQL

注意
table_name即某个分片表的表名;column_value即该表上分片字段某个值。用户可以替换table_name的值指定相应的拆分规则,通过替换column_value的值来指定使用该分片字段的值对应的分片节点。

例如:

/*!hotdb: table = customer:10001*/select * from customer where age > 20;

使用方法:

连接计算节点,选择设置的逻辑库(这里使用test逻辑库),然后使用上述方式执行指定的语句(这里举例说明,使用时可以按需编写SQL)。

在dn_id=2的分片节点上查找cutomer表

mysql> /*!hotdb: dnid=2*/ select count(*) from customer;
+----------+
| count(*) |
+----------+
| 50       |
+----------+
1 row in set (0.00 sec)

查找customer表上provinceid为1的分片节点的customer表

mysql> /*!hotdb: table=customer:1*/ select count(*) from customer;
+----------+
| count(*) |
+----------+
| 11       |
+----------+
1 row in set (0.00 sec)

注意事项:
业务层面不建议HINT直接操作存储节点,因为使用HINT之后,存储节点的数据和状态将不受计算节点控制。

连接绑定

为了防止连接池被污染,当使用HINT操作后,计算节点会绑定当前HINT查询使用的逻辑库关联的后端连接(即计算节点与存储节点的连接),所有涉及到后端的操作均在绑定的连接范围内被允许。故当HINT使用完毕后,建议重建新的前端连接以保证新的会话连接状态干净稳定。若不重建连接,当HINT使用后,有其他操作涉及到与原逻辑库绑定的后端连接之外的新的数据节点时,之前绑定的后端连接会失效,前端连接会被自动重建。

涉及到连接绑定的语句除了HINT,还包括如下语句:

set [session] foreign_key_checks=0;
START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
set [session] UNIQUE_CHECKS=0;

计算节点在这种连接被绑定的SQL执行后,会输出Warning及日志提醒:

如执行如下语句时会有warning提示:

mysql> use db_a

Database changed

mysql> /*!hotdb:dnid=all*/select * From tba;
+----+---+
| id | a |
+----+---+
| 1  | 1 |
| 2  | 2 |
| 3  | 3 |
| 4  | 4 |
| 5  | 5 |
+----+---+
5 rows in set, 1 warning (0.01 sec)
Warning (Code 10041): The current session has been bound to the backend connection associated with the current LogicDB. It is recommended to rebuild the session after use.

同时日志会有info信息:

2019-04-01 19:11:29.662 [INFO] [CONNECTION] [$NIOEecutor-3-1] ServerConnection(1565) -- 31 has been bound to the backend connection:[2,1]

当操作涉及到与原逻辑库绑定的后端连接之外的新的数据节点时,SHOW WARNINGS会有如下提示且连接会断开:

mysql> use db_b
Database changed

mysql> show warnings;
+-------+-------+----------------------------------------------------------------------------------------------------------------------+
| Level | Code  | Message                                                                                                              |
+-------+-------+----------------------------------------------------------------------------------------------------------------------+
| Note  | 10042 | The connection in current LogicDB was a binded connection, operations under current LogicDB may cause connect abort. |
+-------+-------+----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from tbb;
ERROR 2013 (HY000): Lost connection to MySQL server during query
ERROR 2016 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 63
Current database: db_b

在没有USE逻辑库的情况下,计算节点默认绑定所有后端存储节点连接,执行了连接绑定的语句后的其他SQL语句均直接下发执行,可能导致原存储节点的历史数据被修改或覆盖的问题。

例如:登录服务端口,未use逻辑库,执行连接绑定语句:

set [session] foreign_key_checks=0;

之后直接执行

DROP TABLE IF EXISTS table_test;

此时DROP语句会直接下发到所有存储节点执行,进而删除原本不相关的数据。

故使用连接绑定的语句时,需要额外注意:INSERT/REPLACE/UPDATE/DELETE/LOAD DATA/CREATE TABLE/ALTER TABLE/DROP TABLE/TRUNCATE TABLE/RENAME TABLE等会修改数据的操作需要提前use逻辑库。

在计算节点对该类场景做了进一步优化,支持对连接绑定中的内容进行解析。

连接绑定中,无论是否USE逻辑库,都不允许执行对存储节点存在破坏性的SQL(注意HINT本身对如下类型的SQL是不做限制的):

CREATE | ALTER | DROP DATABASE/SET SESSION SQL_LOG_BIN | GTID_NEXT/SET GLOBAL/RESET MASTER | SLAVE/CHANGE MASTER/START | STOP SLAVE | GROUP_REPLICATION/CREATE | ALTER | DROP | RENAME USER | ROLE/GRANT/REVOKE/SET PASSWORD/SET DEFAULT ROLE/CLONE等SQL类型。

例如:执行绑定连接语句,再执行DROP DATABASE操作:

mysql> set foreign_key_checks=0;

Query OK, 0 rows affected, 1 warning (0.02 sec)
Warning (Code 10195): The current session has been bound to the backend connection associated with the current LogicDB. It is recommended to rebuild the session after use.

mysql> drop database TEST_DB;

ERROR 1289 (HY000): Command '{CREATE | ALTER | DROP} {DATABASE | SCHEMA}' is forbidden

在没有USE逻辑库的情况下,执行绑定连接语句后,可以执行带逻辑库.且限定单一逻辑库的SQL:SELECT/INSERT/REPLACE/UPDATE/DELETE/LOAD/CREATE TABLE/ALTER TABLE/DROP TABLE/TRUNCATE TABLE/RENAME TABLE/PREPARE/EXECUTE/DEALLOCATE,也可执行:SET SESSION(不包括SQL_LOG_BIN|GTID_NEXT)、SHOW 、非XA模式下开启事务的语句、SAVEPOINT、提交事务、回滚事务等语句。

例如:执行绑定连接语句不USE逻辑库,再执行带逻辑库名的CREATE TABLE语句,将被允许;执行不带逻辑库名的CREATE TABLE语句,将被拒绝:

mysql> set foreign_key_checks=0;

Query OK, 0 rows affected, 1 warning (0.02 sec)
Warning (Code 10195): The current session has been bound to the backend connection associated with the current LogicDB. It is recommended to rebuild the session after use.

mysql> create table logic_db1.table_test (id int);

Query OK, 0 rows affected, 1 warning (0.18 sec)

mysql> create table table_test2 (id int);

ERROR 1289 (HY000): Command 'create table table_test2 (id int)' is forbidden when sql don't use database with table or use multi database, because he current session has been bound to the backend connection.
posted @   恒辉信达  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示