From 80ef91daddebe824330e38f83946f4797acb7ee0 Mon Sep 17 00:00:00 2001 From: "chao.feng" Date: Mon, 21 Aug 2023 14:50:13 +0800 Subject: [PATCH 01/15] udpate alter stable test case to add ts-3841 scenario by charles --- tests/system-test/1-insert/alter_stable.py | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/system-test/1-insert/alter_stable.py b/tests/system-test/1-insert/alter_stable.py index 3e82b573b1..52f185a868 100644 --- a/tests/system-test/1-insert/alter_stable.py +++ b/tests/system-test/1-insert/alter_stable.py @@ -155,9 +155,37 @@ class TDTestCase: tdSql.error(f'alter stable {self.ntbname} modify column {key} {v}') for i in range(self.tbnum): tdSql.error(f'alter stable {self.stbname}_{i} modify column {key} {v}') - def run(self): + + def alter_stable_column_varchar_39001(self): + """Check alter stable column varchar 39001 from 39000(TS-3841) + """ + stbname = "st1" + column_dict = { + 'ts' : 'timestamp', + 'col1': 'varchar(39000)', + 'col2': 'tinyint', + 'col3': 'timestamp', + 'col4': 'tinyint', + 'col5': 'timestamp', + 'col6': 'varchar(18)', + 'col7': 'varchar(17)' + } + tag_dict = { + 'id': 'int' + } + tdSql.execute(self.setsql.set_create_stable_sql(stbname, column_dict, tag_dict)) + res = tdSql.getResult(f'desc {stbname}') + tdLog.info(res) + assert(res[1][2] == 39000) + tdSql.execute(f'alter stable {stbname} modify column col1 varchar(39001)') + res = tdSql.getResult(f'desc {stbname}') + tdLog.info(res) + assert(res[1][2] == 39001) + + def run(self): self.alter_stable_check() + self.alter_stable_column_varchar_39001() def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) From ce44b80208bc50be81f8bbd9bec6e8d91a5b50ea Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 19:31:58 +0800 Subject: [PATCH 02/15] doc: add enterprise functionalities --- docs/zh/12-taos-sql/25-grant.md | 257 +++-- .../{07-import.md => 04-import.md} | 0 .../{08-export.md => 05-export.md} | 0 .../{10-monitor.md => 06-monitor.md} | 0 docs/zh/17-operation/07-cluster.md | 78 ++ docs/zh/17-operation/08-web.md | 178 ++++ docs/zh/17-operation/09-storage.md | 52 + docs/zh/18-data-transfer/01-taosX.md | 972 ++++++++++++++++++ docs/zh/18-data-transfer/02-explorer.md | 128 +++ 9 files changed, 1587 insertions(+), 78 deletions(-) rename docs/zh/17-operation/{07-import.md => 04-import.md} (100%) rename docs/zh/17-operation/{08-export.md => 05-export.md} (100%) rename docs/zh/17-operation/{10-monitor.md => 06-monitor.md} (100%) create mode 100644 docs/zh/17-operation/07-cluster.md create mode 100644 docs/zh/17-operation/08-web.md create mode 100644 docs/zh/17-operation/09-storage.md create mode 100644 docs/zh/18-data-transfer/01-taosX.md create mode 100644 docs/zh/18-data-transfer/02-explorer.md diff --git a/docs/zh/12-taos-sql/25-grant.md b/docs/zh/12-taos-sql/25-grant.md index d53f951e67..42d740539f 100644 --- a/docs/zh/12-taos-sql/25-grant.md +++ b/docs/zh/12-taos-sql/25-grant.md @@ -4,87 +4,85 @@ title: 权限管理 description: 企业版中才具有的权限管理功能 --- -本节讲述如何在 TDengine 中进行权限管理的相关操作。权限管理是 TDengine 企业版的特有功能,本节只列举了一些基本的权限管理功能作为示例,更丰富的权限管理请联系 TDengine 销售或市场团队。 +本节讲述如何在 TDengine 中进行权限管理的相关操作。权限管理是 TDengine 企业版的特有功能,欲试用 TDengine 企业版请联系 TDengine 销售或市场团队。 -## 创建用户 +TDengine 中的权限管理分为用户管理、数据库授权管理以及消息订阅授权管理。 + +当 TDengine 安装并部署成功后,系统中内置有 "root" 用户。持有默认 "root" 用户密码的系统管理员应该第一时间修改 root 用户的密码,并根据业务需要创建普通用户并为这些用户授予适当的权限。在未授权的情况下,普通用户可以创建 DATABASE,并拥有自己创建的 DATABASE 的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他(即非该用户所创建的) DATABASE 的读写权限,使其可以在这些 DATABASE 上读写数据,但不能对其进行删除和修改数据库的操作。超级用户或者 topic 的创建者也可以给其它用户授予对某个 topic 的订阅权限。 + +## 用户管理 + +用户管理涉及用户的整个生命周期,从创建用户、对用户进行授权、撤销对用户的授权、查看用户信息、直到删除用户。 + +### 创建用户 + +创建用户的操作只能由 root 用户进行,语法如下 + +```sql +CREATE USER user_name PASS 'password' [SYSINFO {1\|0}]; +``` + +说明: + +- user_name 最长为 23 字节。 +- password 最长为 128 字节,合法字符包括"a-zA-Z0-9!?\$%\^&\*()_–+={[}]:;@\~\#\|\<,\>.?/",不可以出现单双引号、撇号、反斜杠和空格,且不可以为空。 +- SYSINFO 表示用户是否可以查看系统信息。1 表示可以查看,0 表示不可以查看。系统信息包括服务端配置信息、服务端各种节点信息(如 DNODE、QNODE等)、存储相关的信息等。默认为可以查看系统信息。 + +示例:创建密码为123456且可以查看系统信息的用户 test + +``` +SQL taos\> create user test pass '123456' sysinfo 1; Query OK, 0 of 0 rows affected (0.001254s) +``` + +### 查看用户 + +查看系统中的用户信息请使用 show users 命令,示例如下 + +```sql +show users; +``` + +也可以通过查询系统表 `INFORMATION_SCHEMA.INS_USERS` 获取系统中的用户信息,示例如下 + +```sql +select * from information_schema.ins_users; +``` + +### 删除用户 + +删除用户请使用 + +```sql +DROP USER user_name; +``` + +### 修改用户信息 + +修改用户信息的命令如下 + +```sql +ALTER USER user_name alter_user_clause alter_user_clause: { PASS 'literal' \| ENABLE value \| SYSINFO value } +``` + +说明: + +- PASS:修改用户密码。 +- ENABLE:修改用户是否启用。1 表示启用此用户,0 表示禁用此用户。 +- SYSINFO:修改用户是否可查看系统信息。1 表示可以查看系统信息,0 表示不可以查看系统信息。 + +示例:禁用 test 用户 + +```sql +alter user test enable 0; Query OK, 0 of 0 rows affected (0.001160s) +``` ```sql CREATE USER use_name PASS 'password' [SYSINFO {1|0}]; ``` -创建用户。 +## 访问控制 -use_name 最长为 23 字节。 - -password 最长为 31 字节,合法字符包括"a-zA-Z0-9!?$%^&*()_–+={[}]:;@~#|<,>.?/",不可以出现单双引号、撇号、反斜杠和空格,且不可以为空。 - -SYSINFO 表示用户是否可以查看系统信息。1 表示可以查看,0 表示不可以查看。系统信息包括服务端配置信息、服务端各种节点信息(如 DNODE、QNODE等)、存储相关的信息等。默认为可以查看系统信息。 - -例如,创建密码为123456且可以查看系统信息的用户test如下: - -```sql -taos> create user test pass '123456' sysinfo 1; -Query OK, 0 of 0 rows affected (0.001254s) -``` - -## 查看用户 - -```sql -SHOW USERS; -``` - -查看用户信息。 - -```sql -taos> show users; - name | super | enable | sysinfo | create_time | -================================================================================ - test | 0 | 1 | 1 | 2022-08-29 15:10:27.315 | - root | 1 | 1 | 1 | 2022-08-29 15:03:34.710 | -Query OK, 2 rows in database (0.001657s) -``` - -也可以通过查询INFORMATION_SCHEMA.INS_USERS系统表来查看用户信息,例如: - -```sql -taos> select * from information_schema.ins_users; - name | super | enable | sysinfo | create_time | -================================================================================ - test | 0 | 1 | 1 | 2022-08-29 15:10:27.315 | - root | 1 | 1 | 1 | 2022-08-29 15:03:34.710 | -Query OK, 2 rows in database (0.001953s) -``` - -## 删除用户 - -```sql -DROP USER user_name; -``` - -## 修改用户信息 - -```sql -ALTER USER user_name alter_user_clause - -alter_user_clause: { - PASS 'literal' - | ENABLE value - | SYSINFO value -} -``` - -- PASS:修改用户密码。 -- ENABLE:修改用户是否启用。1 表示启用此用户,0 表示禁用此用户。 -- SYSINFO:修改用户是否可查看系统信息。1 表示可以查看系统信息,0 表示不可以查看系统信息。 - -例如,禁用 test 用户: - -```sql -taos> alter user test enable 0; -Query OK, 0 of 0 rows affected (0.001160s) -``` - -## 授权 +在 TDengine 企业版中,系统管理员可以根据业务和数据安全的需要控制任意一个用户对每一个数据库、订阅甚至表级别的访问。 ```sql GRANT privileges ON priv_level TO user_name @@ -105,14 +103,106 @@ priv_level : { } ``` -对用户授权。授权功能只包含在企业版中。 +### 数据库权限 -授权级别支持到DATABASE,权限有READ和WRITE两种。 -TDengine 有超级用户和普通用户两类用户。超级用户缺省创建为root,拥有所有权限。使用超级用户创建出来的用户为普通用户。在未授权的情况下,普通用户可以创建DATABASE,并拥有自己创建的DATABASE的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他DATABASE的读写权限,使其可以在此DATABASE上读写数据,但不能对其进行删除和修改数据库的操作。 +TDengine 有超级用户和普通用户两类用户。超级用户缺省创建为root,拥有所有权限。使用超级用户创建出来的用户为普通用户。在未授权的情况下,普通用户可以创建 DATABASE,并拥有自己创建的 DATABASE 的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他 DATABASE 的读写权限,使其可以在此 DATABASE 上读写数据,但不能对其进行删除和修改数据库的操作。 对于非DATABASE的对象,如USER、DNODE、UDF、QNODE等,普通用户只有读权限(一般为SHOW命令),不能创建和修改。 +对数据库的访问权限包含读和写两种权限,它们可以被分别授予,也可以被同时授予。 + +补充说明 + +- priv_level 格式中 "." 之前为数据库名称, "." 之后为表名称 +- "dbname.\*" 意思是名为 "dbname" 的数据库中的所有表 +- "\*.\*" 意思是所有数据库名中的所有表 + +**下表中总结了数据库权限的各种组合** + +对 root 用户和普通用户的权限的说明如下表 + +| 用户 | 描述 | 权限说明 | +|----------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 超级用户 | 只有 root 是超级用户 | DB 外部 所有操作权限,例如user、dnode、udf、qnode等的CRUD DB 权限,包括 创建 删除 更新,例如修改 Option,移动 Vgruop等 读 写 Enable/Disable 用户 | +| 普通用户 | 除 root 以外的其它用户均为普通用户 | 在可读的 DB 中,普通用户可以进行读操作 select describe show subscribe 在可写 DB 的内部,用户可以进行写操作: 创建、删除、修改 超级表 创建、删除、修改 子表 创建、删除、修改 topic 写入数据 被限制系统信息时,不可进行如下操作 show dnode、mnode、vgroups、qnode、snode 修改用户包括自身密码 show db时只能看到自己的db,并且不能看到vgroups、副本、cache等信息 无论是否被限制系统信息,都可以 管理 udf 可以创建 DB 自己创建的 DB 具备所有权限 非自己创建的 DB ,参照读、写列表中的权限 | + +### 消息订阅授权 + +任意用户都可以在自己拥有读权限的数据库上创建 topic。超级用户 root 可以在任意数据库上创建 topic。每个 topic 的订阅权限都可以被独立授权给任何用户,不管该用户是否拥有该数据库的访问权限。删除 topic 只能由 root 用户或者该 topic 的创建者进行。topic 只能由超级用户、topic的创建者或者被显式授予 subscribe 权限的用户订阅。 + +授予订阅权限的语法如下: + +```sql +GRANT privileges ON priv_level TO user_name privileges : { ALL | priv_type [, priv_type] ... } priv_type : { SUBSCRIBE } priv_level : { topic_name } +``` + +### 基于标签的授权(表级授权) + +从 TDengine 3.0.5.0 开始,我们支持按标签授权某个超级表中部分特定的子表。具体的 SQL 语法如下。 + +```sql +GRANT privileges ON priv_level [WITH tag_condition] TO user_name + +privileges : { + ALL + | SUBSCRIBE + | priv_type [, priv_type] ... +} + +priv_type : { + READ + | WRITE +} + +priv_level : { + dbname.tbname + | dbname.* + | *.* + | topic_name +} + +REVOKE privileges ON priv_level [WITH tag_condition] FROM user_name + +privileges : { + ALL + | priv_type [, priv_type] ... +} + +priv_type : { + READ + | WRITE +} + +priv_level : { + dbname.tbname + | dbname.* + | *.* +} +``` + +上面 SQL 的语义为: + +- 用户可以通过 dbname.tbname 来为指定的表(包括超级表和普通表)授予或回收其读写权限,不支持直接对子表授予或回收权限。 +- 用户可以通过 dbname.tbname 和 WITH 子句来为符合条件的所有子表授予或回收其读写权限。使用 WITH 子句时,权限级别必须为超级表。 + +**表级权限和数据库权限的关系** + +下表列出了在不同的数据库授权和表级授权的组合下产生的实际权限。 + +| |**表无授权** | **表读授权** | **表读授权有标签条件** | **表写授权** | **表写授权有标签条件** | +| -------------- | ---------------- | -------- | ---------- | ------ | ----------- | +| **数据库无授权** | 无授权 | 对此表有读权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表无权限 | 对此表有写权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有写权限,对数据库下的其他表无权限 | +| **数据库读授权** | 对所有表有读权限 | 对所有表有读权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表有读权限 | 对此表有写权限,对所有表有读权限 | 对此表符合标签权限的子表有写权限,所有表有读权限 | +| **数据库写授权** | 对所有表有写权限 | 对此表有读权限,对所有表有写权限 | 对此表符合标签权限的子表有读权限,对所有表有写权限 | 对所有表有写权限 | 对此表符合标签权限的子表有写权限,数据库下的其他表有写权限 | + +### 查看用户授权 + +使用下面的命令可以显示一个用户所拥有的授权: + +```sql +show user privileges +``` ## 撤销授权 ```sql @@ -135,4 +225,15 @@ priv_level : { ``` -收回对用户的授权。授权功能只包含在企业版中。 +### 撤销授权 + +1. 撤销数据库访问的授权 + +```sql +REVOKE privileges ON priv_level FROM user_name privileges : { ALL \| priv_type [, priv_type] ... } priv_type : { READ \| WRITE } priv_level : { dbname.\* \| \*.\* } +``` + +2. 撤销数据订阅的授权 + +```sql +REVOKE privileges ON priv_level FROM user_name privileges : { ALL \| priv_type [, priv_type] ... } priv_type : { SUBSCRIBE } priv_level : { topi_name } diff --git a/docs/zh/17-operation/07-import.md b/docs/zh/17-operation/04-import.md similarity index 100% rename from docs/zh/17-operation/07-import.md rename to docs/zh/17-operation/04-import.md diff --git a/docs/zh/17-operation/08-export.md b/docs/zh/17-operation/05-export.md similarity index 100% rename from docs/zh/17-operation/08-export.md rename to docs/zh/17-operation/05-export.md diff --git a/docs/zh/17-operation/10-monitor.md b/docs/zh/17-operation/06-monitor.md similarity index 100% rename from docs/zh/17-operation/10-monitor.md rename to docs/zh/17-operation/06-monitor.md diff --git a/docs/zh/17-operation/07-cluster.md b/docs/zh/17-operation/07-cluster.md new file mode 100644 index 0000000000..0b7fb7e53d --- /dev/null +++ b/docs/zh/17-operation/07-cluster.md @@ -0,0 +1,78 @@ +--- +title: 集群运维 +description: TDengine 提供了多种集群运维手段以使集群运行更健康更高效 +--- + +为了使集群运行更健康更高效,TDengine 企业版提供了一些运维手段来帮助系统管理员更好地运维集群。 + +## 数据重整 + +TDengine 面向多种写入场景,在有些写入场景下,TDengine 的存储会导致数据存储的放大或数据文件的空洞等。这一方面影响数据的存储效率,另一方面也会影响查询效率。为了解决上述问题,TDengine 企业版提供了对数据的重整功能,即 DATA COMPACT 功能,将存储的数据文件重新整理,删除文件空洞和无效数据,提高数据的组织度,从而提高存储和查询的效率。 + +**语法** + +```sql +COMPACT DATABASE db_name [start with 'XXXX'] [end with 'YYYY']; +``` + +**效果** + +- 扫描并压缩指定的 DB 中所有 VGROUP 中 VNODE 的所有数据文件 +- COMPCAT 会删除被删除数据以及被删除的表的数据 +- COMPACT 会合并多个 STT 文件 +- 可通过 start with 关键字指定 COMPACT 数据的起始时间 +- 可通过 end with 关键字指定 COMPACT 数据的终止时间 + +**补充说明** + +- COMPACT 为异步,执行 COMPACT 命令后不会等 COMPACT 结束就会返回。如果上一个 COMPACT 没有完成则再发起一个 COMPACT 任务,则会等上一个任务完成后再返回。 +- COMPACT 可能阻塞写入,但不阻塞查询 +- COMPACT 的进度不可观测 + +## 集群负载再平衡 + +当多副本集群中的一个或多个节点因为升级或其它原因而重启后,有可能出现集群中各个 dnode 负载不均衡的现象,极端情况下会出现所有 vgroup 的 leader 都位于同一个 dnode 的情况。为了解决这个问题,可以使用下面的命令 + +```sql +balance vgroup leader; +``` + +**功能** + +让所有的 vgroup 的 leade r在各自的replica节点上均匀分布。这个命令会让 vgroup 强制重新选举,通过重新选举,在选举的过程中,变换 vgroup 的leader,通过这个方式,最终让leader均匀分布。 + +**注意** + +Raft选举本身带有随机性,所以通过选举的重新分布产生的均匀分布也是带有一定的概率,不会完全的均匀。**该命令的副作用是影响查询和写入**,在vgroup重新选举时,从开始选举到选举出新的 leader 这段时间,这 个vgroup 无法写入和查询。选举过程一般在秒级完成。所有的vgroup会依次逐个重新选举。 + +## 恢复数据节点 + +当集群中的某个数据节点(dnode)的数据全部丢失或被破坏,比如磁盘损坏或者目录被误删除,可以通过 `restore dnode` 命令来恢复该数据节点上的部分或全部逻辑节点,该功能依赖多副本中的其它副本进行数据复制,所以只在集群中 dnode 数量大于等于 3 且副本数为 3 的情况下能够工作。 + + +```sql +restore dnode ;# 恢复dnode上的mnode,所有vnode和qnode +restore mnode on dnode ;# 恢复dnode上的mnode +restore vnode on dnode ;# 恢复dnode上的所有vnode +restore qnode on dnode ;# 恢复dnode上的qnode +``` + +**限制** +- 该功能是基于已有的复制功能的恢复,不是灾难恢复或者备份恢复,所以对于要恢复的 mnode 和 vnode来说,使用该命令的前提是还存在该 mnode 或 vnode 的其它两个副本仍然能够正常工作。 +- 该命令不能修复数据目录中的个别文件的损坏或者丢失。例如,如果某个 mnode 或者 vnode 中的个别文件或数据损坏,无法单独恢复损坏的某个文件或者某块数据。此时,可以选择将该 mnode/vnode 的数据全部清空再进行恢复。 + + +## 虚拟组分裂 (Scale Out) + +当一个 vgroup 因为子表数过多而导致 CPU 或 Disk 资源使用量负载过高时,增加 dnode 节点后,可通过 `split vgroup` 命令把该 vgroup 分裂为两个虚拟组。分裂完成后,新产生的两个 vgroup 承担原来由一个 vgroup 提供的读写服务。这也是 TDengine 为企业版用户提供的 scale out 集群的能力。 + +```sql +split vgroup +``` + +**注意** +- 单副本库虚拟组,在分裂完成后,历史时序数据总磁盘空间使用量,可能会翻倍。所以,在执行该操作之前,通过增加 dnode 节点方式,确保集群中有足够的 CPU 和磁盘资源,避免资源不足现象发生。 +- 该命令为 DB 级事务;执行过程,当前DB的其它管理事务将会被拒绝。集群中,其它DB不受影响。 +- 分裂任务执行过程中,可持续提供读写服务;期间,可能存在可感知的短暂的读写业务中断。 +- 在分裂过程中,不支持流和订阅。分裂结束后,历史 WAL 会清空。 +- 分裂过程中,可支持节点宕机重启容错;但不支持节点磁盘故障容错。 \ No newline at end of file diff --git a/docs/zh/17-operation/08-web.md b/docs/zh/17-operation/08-web.md new file mode 100644 index 0000000000..9923c9912e --- /dev/null +++ b/docs/zh/17-operation/08-web.md @@ -0,0 +1,178 @@ +--- +title: 基于 Web 的系统管理工具 +description: 本节描述 TDengine 的图形化管理工具, taos-explorer, 的基本功能 +--- + +## 简介 + +为了易于企业版用户更容易使用和管理数据库,TDengine 3.0 企业版提供了一个全新的可视化组件 taosExplorer。用户能够在其中方便地管理数据库管理系统中中各元素(数据库、超级表、子表)的生命周期,执行查询,监控系统状态,管理用户和授权,完成数据备份和恢复,与其它集群之间进行数据同步,导出数据,管理主题和流计算。 + +**欲体验基于 Web 的 TDengine 系统管理能力,请联系 TDengine 市场或销售团队** + +## 部署服务 + +### 准备工作 + +1. taosExplorer 没有独立的安装包,请使用 taosX 安装包进行安装。 +2. 在启动 taosExplorer 之前,请先确认 TDengine 集群已经正确设置并运行(即 taosd 服务),taosAdapter 也已经正确设置和运行并与 TDengine 集群保持连接状态。如果想要使用数据备份和恢复或者数据同步功能,请确保 taosX 服务和 Agent 服务也已经正确设置和运行。 + +### 配置 + +在启动 taosExplorer 之前,请确保配置文件中的内容正确。 + +```TOML +listen = "0.0.0.0:6060" +log_level = "info" +cluster = "http://localhost:6041" +x_api = "http://localhost:6050" +``` + +说明: + +- listen - taosExplorer 对外提供服务的地址 +- log_level - 日志级别,可选值为 "debug", "info", "warn", "error", "fatal" +- cluster - TDengine集群的 taosadapter 地址 +- x_api - taosX 的服务地址 + +### 启动 + +然后启动 taosExplorer,可以直接在命令行执行 taos-explorer 或者使用下面的 systemctl 脚本用 systemctl 来启动 taosExplorer 服务 + +```shell +[Unit] +Description=Explorer for TDengine +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/usr/bin/taos-explorer +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +### 问题排查 + +1. 当通过浏览器打开taosExplorer站点遇到“无法访问此网站”的错误信息时,请通过命令行登录taosExplorer所在机器,并使用命令systemctl status taos-explorer.service检查服务的状态,如果返回的状态是inactive,请使用命令systemctl start taos-explorer.service启动服务。 +2. 如果需要获取taosExplorer的详细日志,可通过命令journalctl -u taos-explorer + +## 登录 + +在 TDengine 管理系统的登录页面,输入正确的用户名和密码后,点击登录按钮,即可登录。 + +说明: +- 这里的用户,需要在所连接的 TDengine 中创建,TDengine 默认的用户名和密码为`root/taosdata`; +- 在 TDengine 中创建用户时,默认会设置用户的 SYSINFO 属性值为1, 表示该用户可以查看系统信息,只有 SYSINFO 属性为 1 的用户才能正常登录 TDengine 管理系统。 + +## 面板 + +taosExplorer 内置了一个简单的仪表盘展示以下集群信息,点击左侧功能列表中的 "面板" 可以启用此功能。 + +- 默认的仪表盘会返回对应 Grafana 的安装配置向导 +- 配置过 Grafana 的仪表盘在点击' 面板' 时会跳转到对应的配置地址(该地址来源于 /profile 接口的返回值) + + +## 数据浏览器 + +点击功能列表的“数据浏览器”入口,在“数据浏览器”中可以创建和删除数据库、创建和删除超级表和子表,执行SQL语句,查看SQL语句的执行结果。此外,超级管理员还有对数据库的管理权限,其他用户不提供该功能。 + +具体权限有: + +1.查看(提供数据库/超级表/普通表的基本信息) + +2.编辑 (编辑数据库/超级表/普通表的信息) + +3.数据库管理权限 (仅限超级管理员,该操作可以给指定用户配置数据库管理权限) + +4.删除 (删除数据库/超级表/普通表) + +5.追加 (选择对应的数据库/超级表/普通表名称直接追加到右侧sql输入区域,避免了手工输入) + + +## 系统管理 + +点击功能列表中的“系统管理”入口,可以创建用户、对用户进行访问授权、以及删除用户。还能够对当前所管理的集群中的数据进行备份和恢复。也可以配置一个远程 TDengine 的地址进行数据同步。同时也提供了集群信息和许可证的信息以及代理信息以供查看。系统管理 菜单只有 root 用户才有权限看到 + +### 用户管理 + +点击“系统管理”后,默认会进入“用户”标签页。 +在用户列表,可以查看系统中已存在的用户及其创建时间,并可以对用户进行启用、禁用,编辑(包括修改密码,数据库的读写权限等),删除等操作。 +点击用户列表右上方的“+新增”按钮,即可打开“新增用户”对话框: +1. 输入新增用户的用户名称,必填 +2. 输入新增用户的登录密码,必填,密码长度要求为8-16个字符,且至少要满足以下4个条件中的3个:大写字母,小写字母,数字,特殊字符 +3. 选择新增用户对系统中已存在的数据库的读写权限,非必填,默认情况下,新增用户对所有已存在的数据库无读写权限 +4. 提写完成后,点击确定按钮,即可新增用户。 + +### 系统信息 + +点击“集群”标签后,可以查看DNodes, MNodes和QNodes的状态、创建时间等信息,并可以对以上节点进行新增和删除操作。 + +### 许可证管理 + +点击“许可证”标签后,可以查看系统和系统和各连接器的许可证信息。 +点击位于“许可证”标签页右上角的“激活许可证”按钮,输入“激活码”和“连接器激活码”后,点击“确定”按钮,即可激活,激活码请联系 TDengine 客户成功团队获取。 + +## 数据订阅 + +本章节,将介绍如何在 TDengine 集群中,创建主题,并将其分享给其他用户,以及如何查看一个主题的消费者信息。 + +通过 Explorer, 您可以轻松地完成对数据订阅的管理,从而更好地利用 TDengine 提供的数据订阅能力。 +点击左侧导航栏中的“数据订阅”,即可跳转至数据订阅配置管理页面。 +您可以通过以下两种方式创建主题:使用向导和自定义 SQL 语句。通过自定义 SQL 创建主题时,您需要了解 TDengine 提供的数据订阅 SQL 语句的语法,并保证其正确性。 + +注: 对于数据订阅的详细说明,可参考官方文档中关于“数据订阅”章节,创建数据订阅之前需要先准备源数据库(或源数据库包含相应的超级表或者表),其中源数据库需配置wal_retention_period > 0 。 + +包括主题,消费者,共享主题和示例代码 + +### 创建主题 + +1. 在“主题”标签页,点击“新增新主题”按钮以后,选择向导窗格,然后输入“主题名称”; +2. 在“数据库”下拉列表中,选择相应的数据库; +3. 在“类型”标签下,选择“数据库” 或 “超级表” 或 “子查询”,这里以默认值“数据库”为例; +4. 然后点击“创建” 按钮,即可创建对应的主题。 + +### 分享主题 + +1. 在“共享主题”标签页,在“主题“下拉列表中,选择将要分享的主题; +2. 点击“添加可消费该主题的用户”按钮,然后在“用户名”下拉列表中选择相应的用户,然后点击“新增”,即可将该主题分享给此用户。 + + +### 查看消费者信息 + +1. 通过执行下一节“示例代码”所述的“完整实例”,即可消费共享主题 +2. 在“消费者”标签页,可查看到消费者的有关信息 + +### 示例代码 + +1. 在“示例代码”标签页,在“主题“下拉列表中,选择相应的主题; +2. 选择您熟悉的语言,然后您可以阅读以及使用这部分示例代码用来”创建消费“,”订阅主题“,通过执行 “完整实例”中的程序即可消费共享主题 + +## 流计算 + +通过 Explorer, 您可以轻松地完成对流的管理,从而更好地利用 TDengine 提供的流计算能力。 +点击左侧导航栏中的“流计算”,即可跳转至流计算配置管理页面。 +您可以通过以下两种方式创建流:流计算向导和自定义 SQL 语句。当前,通过流计算向导创建流时,暂不支持分组功能。通过自定义 SQL 创建流时,您需要了解 TDengine 提供的流计算 SQL 语句的语法,并保证其正确性。 + +注: 对于流计算的详细说明,可参考官方文档中关于“流式计算”章节,创建流计算之前需要先准备源数据库以及相应的超级表或表、输出的数据库。 + +### 流计算向导 + +1. 点击“创建流计算”按钮以后,选择流计算向导窗格,然后输入“流名称”; +2. 在“输出”部分,输入相应的“数据库”,“超级表”以及“子表前缀”; +3. 在“源”部分,选择相应的“数据库”,然后根据具体情况,选择使用“超级表”或“表”: + 1. 如果使用“超级表“,请从“超级表”下拉列表中选择相应的超级表, 并在“字段设置”区域,选择相应的字段 + 2. 如果使用“表“,请从“表”下拉列表中选择相应的表, 并在“字段设置”区域,选择相应的字段 +4. 对于窗口设置,根据需要选择”SESSION“, "STATE"或"INTERVAL", 并配置相应的值; +5. 对于”执行“部分,选择相应的”触发器“类型,并设置“Watermark”, "Ignore Expired", "DELETE_MARK", "FILL_HISTORY", "IGNORE UPDATE"; +6. 然后点击“创建” 按钮,即可创建对应的流计算。 + +### 使用 SQL 语句建流 + +1. 点击“创建流计算”按钮以后,选择流计算SQL窗格,然后输入类似如下的SQL语句(反引号内为源数据库以及相应的超级表或表、输出的数据库,请按您的环境更新反引号内的内容) + +```shell +CREATE STREAM `test_stream` TRIGGER WINDOW_CLOSE IGNORE EXPIRED 1 INTO `db_name`.`stable1` SUBTABLE(CONCAT('table1',tbname)) AS SELECT count(*) FROM `test_db`.`stable_name` PARTITION BY tbname INTERVAL(1m) +``` +2. 点击“创建”按钮,即可创建对应的流计算。 \ No newline at end of file diff --git a/docs/zh/17-operation/09-storage.md b/docs/zh/17-operation/09-storage.md new file mode 100644 index 0000000000..f6cdb347b4 --- /dev/null +++ b/docs/zh/17-operation/09-storage.md @@ -0,0 +1,52 @@ +--- +title: 多级存储 +--- + +## 多级存储 + +说明:多级存储功能仅企业版支持。 + +在默认配置下,TDengine 会将所有数据保存在 /var/lib/taos 目录下,而且每个 vnode 的数据文件保存在该目录下的不同目录。为扩大存储空间,尽量减少文件读取的瓶颈,提高数据吞吐率 TDengine 可通过配置系统参数 dataDir 让多个挂载的硬盘被系统同时使用。 + +除此之外,TDengine 也提供了数据分级存储的功能,将不同时间段的数据存储在挂载的不同介质上的目录里,从而实现不同“热度”的数据存储在不同的存储介质上,充分利用存储,节约成本。比如,最新采集的数据需要经常访问,对硬盘的读取性能要求高,那么用户可以配置将这些数据存储在 SSD 盘上。超过一定期限的数据,查询需求量没有那么高,那么可以存储在相对便宜的 HDD 盘上。 + +多级存储支持 3 级,每级最多可配置 16 个挂载点。 + +TDengine 多级存储配置方式如下(在配置文件/etc/taos/taos.cfg 中): + +``` +dataDir [path] +``` + +- path: 挂载点的文件夹路径 +- level: 介质存储等级,取值为 0,1,2。 + 0 级存储最新的数据,1 级存储次新的数据,2 级存储最老的数据,省略默认为 0。 + 各级存储之间的数据流向:0 级存储 -> 1 级存储 -> 2 级存储。 + 同一存储等级可挂载多个硬盘,同一存储等级上的数据文件分布在该存储等级的所有硬盘上。 + 需要说明的是,数据在不同级别的存储介质上的移动,是由系统自动完成的,用户无需干预。 +- primary: 是否为主挂载点,0(否)或 1(是),省略默认为 1。 + +在配置中,只允许一个主挂载点的存在(level=0,primary=1),例如采用如下的配置方式: + +``` +dataDir /mnt/data1 0 1 +dataDir /mnt/data2 0 0 +dataDir /mnt/data3 1 0 +dataDir /mnt/data4 1 0 +dataDir /mnt/data5 2 0 +dataDir /mnt/data6 2 0 +``` + +:::note + +1. 多级存储不允许跨级配置,合法的配置方案有:仅 0 级,仅 0 级+ 1 级,以及 0 级+ 1 级+ 2 级。而不允许只配置 level=0 和 level=2,而不配置 level=1。 +2. 禁止手动移除使用中的挂载盘,挂载盘目前不支持非本地的网络盘。 +3. 多级存储目前不支持删除已经挂载的硬盘的功能。 + +::: + +## 0 级负载均衡 + +在多级存储中,有且只有一个主挂载点,主挂载点承担了系统中最重要的元数据在座,同时各个 vnode 的主目录均存在于当前 dnode 主挂载点上,从而导致该 dnode 的写入性能受限于单个磁盘的 IO 吞吐能力。 + +从 TDengine 3.1.0.0 开始,如果一个 dnode 配置了多个 0 级挂载点,我们将该 dnode 上所有 vnode 的主目录均衡分布在所有的 0 级挂载点上,由这些 0 级挂载点共同承担写入负荷。在网络 I/O 及其它处理资源不成为瓶颈的情况下,通过优化集群配置,测试结果证明整个系统的写入能力和 0 级挂载点的数量呈现线性关系,即随着 0 级挂载点数量的增加,整个系统的写入能力也成倍增加。 diff --git a/docs/zh/18-data-transfer/01-taosX.md b/docs/zh/18-data-transfer/01-taosX.md new file mode 100644 index 0000000000..72d2cb2211 --- /dev/null +++ b/docs/zh/18-data-transfer/01-taosX.md @@ -0,0 +1,972 @@ +--- +title: 数据接入、同步和备份 +--- + +## 简介 + +为了能够方便地将各种数据源中的数据导入 TDengine 3.0,TDengine 3.0 企业版提供了一个全新的工具 taosX 用于帮助用户快速将其它数据源中的数据传输到 TDengine 中。 taosX 定义了自己的集成框架,方便扩展新的数据源。目前支持的数据源有 TDengine 自身(即从一个 TDengine 集群到另一个 TDengine 集群),Pi, OPC UA。除了数据接入外,taosX 还支持数据备份、数据同步、数据迁移以及数据导出功能。 + +**欲体验 taosX 的各种数据接入能力,请联系 TDengine 市场或销售团队。** + +## 使用前提 + +使用 taosX 需要已经部署好 TDengine 中的 taosd 和 taosAdapter,具体细节请参考 [系统部署](../../deployment/deploy) + +**使用限制**:taosX 只能用于企业版数据库服务端。 + +## 安装与配置 + +安装 taosX 需要使用独立的 taosX 安装包,其中除了 taosX 之外,还包含 Pi 连接器(限 Windows), OPC 连接器, InfluxDB 连接器, MQTT 连接器,以及必要的 Agent 组件,taosX + Agent + 某个连接器可以用于将相应数据源的数据同步到 TDengine。taosX 安装包中还包含了 taos-explorer 这个可视化管理组件 + +### Linux 安装 + +下载需要的 taosX 安装包,下文以安装包 `taosx-1.0.0-linux-x64.tar.gz` 为例展示如何安装: + +``` bash +# 在任意目录下解压文件 +tar -zxf taosx-1.0.0-linux-x64.tar.gz +cd taosx-1.0.0-linux-x64 + +# 安装 +sudo ./install.sh + +# 验证 +taosx -V +# taosx 1.0.0-494d280c (built linux-x86_64 2023-06-21 11:06:00 +08:00) +taosx-agent -V +# taosx-agent 1.0.0-494d280c (built linux-x86_64 2023-06-21 11:06:01 +08:00) + +# 卸载 +cd /usr/local/taosx +sudo ./uninstall.sh +``` + +**常见问题:** + +1. 安装后系统中增加了哪些文件? + * /usr/bin: taosx, taosx-agent, taos-explorer + * /usr/local/taosx/plugins: influxdb, mqtt, opc + * /etc/systemd/system:taosx.service, taosx-agent.service, taos-explorer.service + * /usr/local/taosx: uninstall.sh + * /etc/taox: agent.toml, explorer.toml + +2. taosx -V 提示 "Command not found" 应该如何解决? + * 检验问题1,保证所有的文件都被复制到对应的目录 + ``` bash + ls /usr/bin | grep taosx + ``` + +### Windows 安装 + +- 下载需要的 taosX 安装包,例如 taosx-1.0.0-Windows-x64-installer.exe,执行安装 +- 可使用 uninstall_taosx.exe 进行卸载 +- 命令行执行 ```sc start/stop taosx``` 启动/停止 taosx 服务 +- 命令行执行 ```sc start/stop taosx-agent``` 启动/停止 taosx-agent 服务 +- 命令行执行 ```sc start/stop taos-explorer``` 启动/停止 taosx-agent 服务 +- windows 默认安装在```C:\Program Files\taosX```,目录结构如下: +~~~ +├── bin +│   ├── taosx.exe +│   ├── taosx-srv.exe +│   ├── taosx-srv.xml +│   ├── taosx-agent.exe +│   ├── taosx-agent-srv.exe +│   ├── taosx-agent-srv.xml +│   ├── taos-explorer.exe +│   ├── taos-explorer-srv.exe +│   └── taos-explorer-srv.xml +├── plugins +│   ├── influxdb +│   │   └── taosx-inflxdb.jar +│   ├── mqtt +│   │   └── taosx-mqtt.exe +│   ├── opc +│   | └── taosx-opc.exe +│   ├── pi +│   | └── taosx-pi.exe +│   | └── taosx-pi-backfill.exe +│   | └── ... +└── config +│   ├── agent.toml +│   ├── explorer.toml +├── uninstall_taosx.exe +├── uninstall_taosx.dat +~~~ + +**运行模式** + +taosX 是进行数据同步与复制的核心组件,以下运行模式指 taosX 的运行模式,其它组件的运行模式在 taosX 的不同运行模式下与之适配。 + +## 命令行模式 + +可以直接在命令行上添加必要的参数直接启动 taosX 即为命令行模式运行。当命令行参数所指定的任务完成后 taosX 会自动停止。taosX 在运行中如果出现错误也会自动停止。也可以在任意时刻使用 ctrl+c 停止 taosX 的运行。本节介绍如何使用 taosX 的各种使用场景下的命令行。 + +### 命令行参数说明 + +**注意:部分参数暂无法通过 explorer设置【见:其他参数说明】,之后会逐步开放) ** + +命令行执行示例: + +```shell +taosx -f -t <其他参数> +``` + +以下参数说明及示例中若无特殊说明 `` 的格式均为占位符,使用时需要使用实际参数进行替换。 + +### DSN (Data Source Name) + +taosX 命令行模式使用 DSN 来表示一个数据源(来源或目的源),典型的 DSN 如下: + +```bash +# url-like +[+]://[[:@]:][/][?=[&=]] +|------|------------|---|-----------|-----------|------|------|----------|-----------------------| +|driver| protocol | | username | password | host | port | object | params | + +// url 示例 +tmq+ws://root:taosdata@localhost:6030/db1?timeout=never +``` +[] 中的数据都为可选参数。 + +1. 不同的驱动 (driver) 拥有不同的参数。driver 包含如下选项: + +- taos:使用查询接口从 TDengine 获取数据 +- tmq:启用数据订阅从 TDengine 获取数据 +- local:数据备份或恢复 +- pi: 启用 pi-connector从 pi 数据库中获取数据 +- opc:启用 opc-connector 从 opc-server 中获取数据 +- mqtt: 启用 mqtt-connector 获取 mqtt-broker 中的数据 +- kafka: 启用 Kafka 连接器从 Kafka Topics 中订阅消息写入 +- influxdb: 启用 influxdb 连接器从 InfluxDB 获取数据 +- csv:从 CSV 文件解析数据 + +2. +protocol 包含如下选项: +- +ws: 当 driver 取值为 taos 或 tmq 时使用,表示使用 rest 获取数据。不使用 +ws 则表示使用原生连接获取数据,此时需要 taosx 所在的服务器安装 taosc。 +- +ua: 当 driver 取值为 opc 时使用,表示采集的数据的 opc-server 为 opc-ua +- +da: 当 driver 取值为 opc 时使用,表示采集的数据的 opc-server 为 opc-da + +3. host:port 表示数据源的地址和端口。 +4. object 表示具体的数据源,可以是TDengine的数据库、超级表、表,也可以是本地备份文件的路径,也可以是对应数据源服务器中的数据库。 +5. username 和 password 表示该数据源的用户名和密码。 +6. params 代表了 dsn 的参数。 + +### 其它参数说明 + +1. parser 通过 --parser 或 -p 设置,设置 transform 的 parser 生效。可以通过 Explorer 在如 CSV,MQTT,KAFKA 数据源的任务配置进行设置。 + + 配置示例: + + ```shell + --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"key\":{\"as\":\"binary\",\"alias\":\"k\"},\"value\":{\"as\":\"binary\",\"alias\":\"v\"}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"k\",\"v\"]}]}" + + ``` + +2. transform 通过 --transform 或 -T 设置,配置数据同步(仅支持 2.6 到 3.0 以及 3.0 之间同步)过程中对于表名及表字段的一些操作。暂无法通过 Explorer 进行设置。配置说明如下: + + ```shell + 1.AddTag,为表添加 TAG。设置示例:-T add-tag:=。 + 2.表重命名: + 2.1 重命名表限定 + 2.1.1 RenameTable:对所有符合条件的表进行重命名。 + 2.1.2 RenameChildTable:对所有符合条件的子表进行重命名。 + 2.1.3 RenameSuperTable:对所有符合条件的超级表进行重命名。 + 2.2 重命名方式 + 2.2.1 Prefix:添加前缀。 + 2.2.2 Suffix:添加后缀。 + 2.2.3 Template:模板方式。 + 2.2.4 ReplaceWithRegex:正则替换。taosx 1.1.0 新增。 + 重命名配置方式: + <表限定>:<重命名方式>:<重命名值> + 使用示例: + 1.为所有表添加前缀 + --transform rename-table:prefix: + 2.为符合条件的表替换前缀:prefix1 替换为 prefix2,以下示例中的 <> 为正则表达式的不再是占位符。 + -T rename-child-table:replace_with_regex:^prefix1(?)::prefix2_$old + + 示例说明:^prefix1(?) 为正则表达式,该表达式会匹配表名中包含以 prefix1 开始的表名并将后缀部分记录为 old,prefix2$old 则会使用 prefix2 与 old 进行替换。注意:两部分使用关键字符 :: 进行分隔,所以需要保证正则表达式中不能包含该字符。 + 若有更复杂的替换需求请参考:https://docs.rs/regex/latest/regex/#example-replacement-with-named-capture-groups 或咨询 taosx 开发人员。 + ``` + +3. jobs 指定任务并发数,仅支持 tmq 任务。暂无法通过 Explorer 进行设置。通过 --jobs `` 或 -j `` 进行设置。 +4. -v 用于指定 taosx 的日志级别,-v 表示启用 info 级别日志,-vv 对应 debug,-vvv 对应 trace。 + + +### 从 TDengine 到 TDengine 的数据同步 + +#### TDengine 3.0 -> TDengine 3.0 + +在两个相同版本 (都是 3.0.x.y)的 TDengine 集群之间将源集群中的存量及增量数据同步到目标集群中。 + +命令行模式下支持的参数如下: + +| 参数名称 | 说明 | 默认值 | +|-----------|------------------------------------------------------------------|----------------------------| +| group.id | 订阅使用的分组ID | 若为空则使用 hash 生成一个 | +| client.id | 订阅使用的客户端ID | taosx | +| timeout | 监听数据的超时时间,当设置为 never 表示 taosx 不会停止持续监听。 | 500ms | +| offset | 从指定的 offset 开始订阅,格式为 `:`,若有多个 vgroup 则用半角逗号隔开 | 若为空则从 0 开始订阅 | +| token | 目标源参数。 认证使用参数。 | 无 | + +示例: +```shell +taosx run \ + -f 'tmq://root:taosdata@localhost:6030/db1?group.id=taosx1&client.id=taosx&timeout=never&offset=2:10' \ + -t 'taos://root:taosdata@another.com:6030/db2' +``` + + + +#### TDengine 2.6 -> TDengine 3.0 + +将 2.6 版本 TDengine 集群中的数据迁移到 3.0 版本 TDengine 集群。 + +#### 命令行参数 + +| 参数名称 | 说明 | 默认值 | +|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------| +| libraryPath | 在 option 模式下指定 taos 库路径 | 无 | +| configDir | 指定 taos.cfg 配置文件路径 | 无 | +| mode | 数据源参数。 history 表示历史数据。 realtime 表示实时同步。 all 表示以上两种。 | history | +| restro | 数据源参数。 在同步实时数据前回溯指定时间长度的数据进行同步。 restro=10m 表示回溯最近 10 分钟的数据以后,启动实时同步。 | 无 | +| interval | 数据源参数。 轮询间隔 ,mode=realtime&interval=5s 指定轮询间隔为 5s | 无 | +| excursion | 数据源参数。 允许一段时间的乱序数据 | 500ms | +| stables | 数据源参数。 仅同步指定超级表的数据,多个超级表名用英文逗号 ,分隔 | 无 | +| tables | 数据源参数。 仅同步指定子表的数据,表名格式为 {stable}.{table} 或 {table},多个表名用英文逗号 , 分隔,支持 @filepath 的方式输入一个文件,每行视为一个表名,如 tables=@./tables.txt 表示从 ./tables.txt 中按行读取每个表名,空行将被忽略。 | 无 | +| select-from-stable | 数据源参数。 从超级表获取 select {columns} from stable where tbname in ({tbnames}) ,这种情况 tables 使用 {stable}.{table} 数据格式,如 meters.d0 表示 meters 超级表下面的 d0 子表。 | 默认使用 select \* from table 获取数据 | +| assert | 目标源参数。 taos:///db1?assert 将检测数据库是否存在,如不存在,将自动创建目标数据库。 | 默认不自动创建库。 | +| force-stmt | 目标源参数。 当 TDengine 版本大于 3.0 时,仍然使用 STMT 方式写入。 | 默认为 raw block 写入方式 | +| batch-size | 目标源参数。 设置 STMT 写入模式下的最大批次插入条数。 | | +| interval | 目标源参数。 每批次写入后的休眠时间。 | 无 | +| max-sql-length | 目标源参数。 用于建表的 SQL 最大长度,单位为 bytes。 | 默认 800_000 字节。 | +| failes-to | 目标源参数。 添加此参数,值为文件路径,将写入错误的表及其错误原因写入该文件,正常执行其他表的同步任务。 | 默认写入错误立即退出。 | +| timeout-per-table | 目标源参数。 为子表或普通表同步任务添加超时。 | 无 | +| update-tags | 目标源参数。 检查子表存在与否,不存在时正常建表,存在时检查标签值是否一致,不一致则更新。 | 无 | + +#### 示例 + +1.使用原生连接同步数据 + +```shell +taosx run \ + -f 'taos://td1:6030/db1?libraryPath=./libtaos.so.2.6.0.30&mode=all' \ + -t 'taos://td2:6030/db2?libraryPath=./libtaos.so.3.0.1.8&assert \ + -v +``` + +2.使用 WebSocket 同步数据超级表 stable1 和 stable2 的数据 + +```shell +taosx run \ + -f 'taos+ws://:@td1:6041/db1?stables=stable1,stable2' \ + -t 'taos+wss://td2:6041/db2?assert&token= \ + -v +``` + +### 从 TDengine 备份数据文件到本地 + +示例: +```shell +taosx run -f 'tmq://root:taosdata@td1:6030/db1' -t 'local:/path_directory/' + +``` +以上示例执行的结果及参数说明: + +将集群 td1 中的数据库 db1 的所有数据,备份到 taosx 所在设备的 /path_directory 路径下。 + +数据源(-f 参数的 DSN)的 object 支持配置为 数据库级(dbname)、超级表级(dbname.stablename)、子表/普通表级(dbname.tablename),对应备份数据的级别数据库级、超级表级、子表/普通表级 + + +### 从本地数据文件恢复到 TDengine + +#### 示例 +```shell +taosx run -f 'local:/path_directory/' -t 'taos://root:taosdata@td2:6030/db1?assert' +``` + +以上示例执行的结果: + +将 taosx 所在设备 /path_directory 路径下已备份的数据文件,恢复到集群 td2 的数据库 db1 中,如果 db1 不存在,则自动建库。 + +目标源(-t 参数的 DSN)中的 object 支持配置为数据库(dbname)、超级表(dbname.stablename)、子表/普通表(dbname.tablename),对应备份数据的级别数据库级、超级表级、子表/普通表级,前提是备份的数据文件也是对应的数据库级、超级表级、子表/普通表级数据。 + + +#### 常见错误排查 + +(1) 如果使用原生连接,任务启动失败并报以下错误: + +```text +Error: tmq to td task exec error + +Caused by: + [0x000B] Unable to establish connection +``` +产生原因是与数据源的端口链接异常,需检查数据源 FQDN 是否联通及端口 6030 是否可正常访问。 + +(2) 如果使用 WebSocket 连接,任务启动失败并报以下错误: + +```text +Error: tmq to td task exec error + +Caused by: + 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution + 1: IO error: failed to lookup address information: Temporary failure in name resolution + 2: failed to lookup address information: Temporary failure in name resolution +``` + +使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: + +- "Temporary failure in name resolution": DNS 解析错误,检查 IP 或 FQDN 是否能够正常访问。 +- "IO error: Connection refused (os error 111)": 端口访问失败,检查端口是否配置正确或是否已开启和可访问。 +- "IO error: received corrupt message": 消息解析失败,可能是使用了 wss 方式启用了 SSL,但源端口不支持。 +- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 +- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 + +(3) 如果任务启动失败并报以下错误: + +```text +Error: tmq to td task exec error + +Caused by: + [0x038C] WAL retention period is zero +``` + +是由于源端数据库 WAL 配置错误,无法订阅。 + +解决方式: +修改数据 WAL 配置: + +```sql +alter database test wal_retention_period 3600; +``` + +### 从 OPC-UA 同步数据到 TDengine + +#### 配置参数 + +| 参数名称 | 类型 | 描述 | +|-----------------|--------|-----------------------------------------------------------------------------| +| interval | int | 采集间隔(单位:秒),默认为1秒 | +| concurrent | int | 采集器并发数,默认为1 | +| batch_size | int | 采集器上报的批次点位数,默认为100 | +| batch_timeout | int | 采集器上报的超时时间(单位:秒),默认为20秒 | +| connect_timeout | int | 连接的超时时间(单位:秒),默认为10秒 | +| request_timeout | int | 请求的超时时间(单位:秒),默认为10秒 | +| security_policy | string | OPC-UA连接安全策略(可配置为None/Basic128Rsa15/Basic256/Basic256Sha256) | +| security_mode | string | OPC-UA连接模式(可配置为None/Sign/SignAndEncrypt) | +| certificate | string | cert.pem的路径。当安全模式或策略不是”无”时生效 | +| private_key | string | key.pem的路径。 当安全模式或策略不是”无”时生效 | +| csv_config_file | string | 包含 OPC UA 的点位配置和表配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效| +| ua.nodes | string | OPC-UA 测点的 NodeID。和 opc_table_config 配置结合使用,两者需要同时配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效。配置格式为 ::,code 用于建子表。| +| opc_table_config | string | OPCUA 单列模式表配置。需要与 ua.nodes 配合使用。| +| debug | bool | 启用 OPC 连接器的 debug 日志。默认为 false。| +| enable | bool | 原始数据存储。默认为 false| +| path | string | 原始数据存储路径。enable 为 true 时必须配置。| +| keep | int | 原始数据保存天数。enable 为 true 时必须配置。| + +补充: +1. opc_table_config 说明: + +```json +{ + "stable_prefix": "meters", // 超级表前缀 + "column_configs": + [ + { + "column_name": "received_time", // 存储接收时间 + "column_type": "timestamp", + "column_alias": "ts", // 接收时间建表列用列名为 ts + "is_primary_key": true // 接收时间时间戳作为主键 + }, + { + "column_name": "original_time", + "column_type": "timestamp", + "column_alias": "ts_2", + "is_primary_key": false + }, + { + "column_name": "value", // 数据列 + "column_alias": "valueaa", // 数据列别名 + "is_primary_key": false + }, + { + "column_name": "quality", // 质量位列 + "column_type": "int", + "column_alias": "quality11", // 质量位列别名 + "is_primary_key": false + } + ] +} +``` + +#### 示例 + +1. 使用 ua.nodes 和 opc_table_config 的配置示例: +采集 nodeid 为 ns=2;i=2 和 ns=2;i=3 的点位,将其写入到集群 tdengine 的 opc 库中超级表前缀为 meters,如果 ns=2;i=2 的点位类型为 float 则会创建 meters_float 的超级表,超级表使用 opc 接收的数据作为时间戳索引列,并且保留原始时间戳列,原始时间戳列名为 ts_2,数据列存储为 valueaa,同时存储质量数据到 quality11 列。 + +```shell +taosx run \ + -f "opcua://uauser:uapass@localhost:4840?ua.nodes=ns=2;i=2::DSF1312,ns=2;i=3::DSF1313&opc_table_config={\"stable_prefix\": \"meters\", \"column_configs\": [{\"column_name\": \"received_time\", \"column_type\": \"timestamp\", \"column_alias\": \"ts\", \"is_primary_key\": true }, {\"column_name\": \"original_time\", \"column_type\": \"timestamp\", \"column_alias\": \"ts_2\", \"is_primary_key\": false }, {\"column_name\": \"value\", \"column_alias\": \"valueaa\", \"is_primary_key\": false }, {\"column_name\": \"quality\", \"column_type\": \"int\", \"column_alias\": \"quality11\", \"is_primary_key\": false } ] }" \ + -t "taos://tdengine:6030/opc" + + + +``` + +2. 使用 CSV 配置文件 + +```shell +taosx run -f "opcua://?csv_config_file=@" -t "taos+ws://tdengine:6041/opc" +``` + +#### CSV 配置文件模板 + + +### 从 OPC-DA 同步数据到 TDengine (Windows) + +#### 配置参数 + +| 参数名称 | 类型 | 描述 | +|-----------------|--------|-----------------------------------------------------------------------------| +| interval | int | 采集间隔(单位:秒),默认为1秒 | +| concurrent | int | 采集器并发数,默认为1 | +| batch_size | int | 采集器上报的批次点位数,默认为100 | +| batch_timeout | int | 采集器上报的超时时间(单位:秒),默认为20秒 | +| connect_timeout | int | 连接的超时时间(单位:秒),默认为10秒 | +| request_timeout | int | 请求的超时时间(单位:秒),默认为10秒 | +| csv_config_file | string | 包含 OPC UA 的点位配置和表配置。与 ua.nodes 两者之间需要配置一个。CSV 的配置模版参考:OPC 需求汇总及完成现状 | +| da.tags | string | OPC-UA 测点的 NodeID。和 opc_table_config 配置结合使用,两者需要同时配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效。| +| opc_table_config | string | OPCUA 单列模式表配置。需要与 da.tags 配合使用| +| debug | bool | 启用 OPC 连接器的 debug 日志。默认为 false。| +| enable | bool | 原始数据存储。默认为 false| +| path | string | 原始数据存储路径。enable 为 true 时必须配置。| +| keep | int | 原始数据保存天数。enable 为 true 时必须配置。| + +#### 应用示例 + +```shell +taosx run \ + -f "opc+da://Matrikon.OPC.Simulation.1?nodes=localhost&da.tags=Random.Real8::tb3::c1::int" + -t "taos://tdengine:6030/opc" +``` + +以上示例的执行结果: + +采集 Matrikon.OPC.Simulation.1 服务器上 OPC DA 中 da.tags 为 Random.Real8的数据,数据类型为int,对应在 TDengine 中以表名为 tb3 ,列名为c1,列类型为 int 型 schema 来创建表(如果对应表已存在,则直接采集数据并写入)。 + +#### 常见错误排查 + +(1) 如果使用原生连接,任务启动失败并打印如下错误: +```text +Error: tmq to td task exec error + +Caused by: + 0: Error occurred while creating a new object: [0x000B] Unable to establish connection +``` +解决方式: + +检查目标端 TDengine 的 FQDN 是否联通及端口 6030 是否可正常访问。 + +(2) 如果使用 WebSocket 连接任务启动失败并打印如下错误:: + +```text +Error: tmq to td task exec error + +Caused by: + 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution + 1: IO error: failed to lookup address information: Temporary failure in name resolution + 2: failed to lookup address information: Temporary failure in name resolution +``` + +使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: + +- "Temporary failure in name resolution": DNS 解析错误,检查目标端 TDengine的 IP 或 FQDN 是否能够正常访问。 +- "IO error: Connection refused (os error 111)": 端口访问失败,检查目标端口是否配置正确或是否已开启和可访问(通常为6041端口)。 +- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 +- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 + +### 从 PI 同步数据到 TDengine (Windows) + +#### PI DSN 配置 + +PI DSN 的完整配置如下: + +```shell +pi://[:@]PIServerName/AFDatabaseName?[TemplateForPIPoint][&TemplateForAFElement][&PointList][&][&][&UpdateInterval] +``` + +在 taosX CLI 运行时支持的参数如下,其中 TemplateForPIPoint、TemplateForAFElement、PointList 三个参数至少配置一项: +- PISystemName:选填,连接配置 PI 系统服务名,默认值与 PIServerName 一致 +- MaxWaitLen:选填,数据最大缓冲条数,默认值为 1000 ,有效取值范围为 [1,10000] +- UpdateInterval:选填,PI System 取数据频率,默认值为 10000(毫秒:ms),有效取值范围为 [10,600000] +- TemplateForPIPoint:选填,使用 PI Point 模式将模板按照 element 的每个 Arrtribution 作为子表导入到 TDengine +- TemplateForAFElement:选填,使用 AF Point 模式将模板按照 element 的 Attribution 集合作为一个子表导入到 TDengine +- PointList:选填,使用 PointList 模式将指定csv文件中描述的点位信息在 PI 数据库中的数据导入到 TDengine + + +#### 应用示例 + +将位于服务器 WIN-2OA23UM12TN 中的 PI 数据库 Met1,模板 template1、template2配置为 TemplateForPIPoint模式,模板 template3、template4 配置为 TemplateForAFElement 模式,服务器 /home/ 路径下的点位文件 points.csv 配置为 PointList 模式,连接配置 PI 系统服务名为 PI,数据最大缓冲条数为1000,PI System 取数据频率为10000ms,将该库中的数据同步到 服务器 tdengine 的 pi 库中。完整的示例如下: + +```shell +taosx run \ + -f "pi://WIN-2OA23UM12TN/Met1?TemplateForPIPoint=template1,template2&TemplateForAFElement=template3,template4" \ + -t "taos://tdengine:6030/pi" +``` + + +#### 常见错误排查 + +(1) 如果使用原生连接,任务启动失败并打印如下错误: +```text +Error: tmq to td task exec error + +Caused by: + 0: Error occurred while creating a new object: [0x000B] Unable to establish connection +``` +解决方式: + +检查目标端 TDengine 的 FQDN 是否联通及端口 6030 是否可正常访问。 + +(2) 如果使用 WebSocket 连接任务启动失败并打印如下错误:: + +```text +Error: tmq to td task exec error + +Caused by: + 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution + 1: IO error: failed to lookup address information: Temporary failure in name resolution + 2: failed to lookup address information: Temporary failure in name resolution +``` + +使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: + +- "Temporary failure in name resolution": DNS 解析错误,检查目标端 TDengine的 IP 或 FQDN 是否能够正常访问。 +- "IO error: Connection refused (os error 111)": 端口访问失败,检查目标端口是否配置正确或是否已开启和可访问(通常为6041端口)。 +- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 +- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 + + +### 从 InfluxDB 同步数据到 TDengine + +#### 命令行参数 + +将数据从 InfluxDB 同步至 TDengine 的命令,如下所示: + +```bash +taosx run --from "" --to "" +``` + +其中,InfluxDB DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: +- version: 必填,InfluxDB 的版本,主要用于区分 1.x 与 2.x 两个版本,二者使用不同的认证参数; +- version = 1.x + - username: 必填,InfluxDB 用户,该用户至少在该组织中拥有读取权限; + - password: 必填,InfluxDB 用户的登陆密码; +- version = 2.x + - orgId: 必填,InfluxDB 中的 Orgnization ID; + - token: 必填,InfluxDB 中生成的 API token, 这个 token 至少要拥有以上 Bucket 的 Read 权限; +- bucket: 必填,InfluxDB 中的 Bucket 名称,一次只能同步一个 Bucket; +- measurements: 非必填,可以指定需要同步的多个 Measurements(英文逗号分割),未指定则同步全部; +- beginTime: 必填,格式为:YYYY-MM-DD'T'HH:MM:SS'Z', 时区采用 UTC 时区,例如:2023-06-01T00:00:00+0800, 即北京时间2023-06-01 00:00:00(东八区时间); +- endTime: 非必填,可以不指定该字段或值为空,格式与beginTime相同;如果未指定,提交任务后,将持续进行数据同步; +- readWindow: 非必填,可以不指定该字段或值为空,可选项为D、H、M(天、时、分);如果未指定,则默认按 M 拆分读取窗口。 + +#### 示例 + +将位于 192.168.1.10 的 InfluxDB 中, Bucket 名称为 test_bucket, 从UTC时间2023年06月01日00时00分00秒开始的数据,通过运行在 192.168.1.20 上的 taoskeeper, 同步至 TDengine 的 test_db 数据库中,完整的命令如下所示: +```bash +# version = 1.x +taosx run \ + --from "influxdb+http://192.168.1.10:8086/?version=1.7&username=test&password=123456&bucket=test_bucket&measurements=&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ + --to "taos+http://192.168.1.20:6041/test_db" \ + -vv + +# version = 2.x +taosx run \ + --from "influxdb+http://192.168.1.10:8086/?version=2.7&orgId=3233855dc7e37d8d&token=OZ2sB6Ie6qcKcYAmcHnL-i3STfLVg_IRPQjPIzjsAQ4aUxCWzYhDesNape1tp8IsX9AH0ld41C-clTgo08CGYA==&bucket=test_bucket&measurements=&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ + --to "taos+http://192.168.1.20:6041/test_db" \ + -vv +``` + +在这个命令中,未指定endTime, 所以任务会长期运行,持续同步最新的数据。 + + +### 从 OpenTSDB 同步数据到 TDengine + +#### 命令行参数 + +将数据从 OpenTSDB 同步至 TDengine 的命令,如下所示: + +```bash +taosx run --from "" --to "" +``` + +其中,OpenTSDB DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: +- metrics: 非必填,可以指定需要同步的多个 Metrics(英文逗号分割),未指定则同步全部; +- beginTime: 必填,格式为:YYYY-MM-DD'T'HH:MM:SS'Z', 时区采用 UTC 时区,例如:2023-06-01T00:00:00+0800, 即北京时间2023-06-01 00:00:00(东八区时间); +- endTime: 非必填,可以不指定该字段或值为空,格式与beginTime相同;如果未指定,提交任务后,将持续进行数据同步; +- readWindow: 非必填,可以不指定该字段或值为空,可选项为D、H、M(天、时、分);如果未指定,则默认按分钟拆分读取窗口。 + +#### 示例 + +将位于 192.168.1.10 的 OpenTSDB 中, Metric 名称为 test_metric1 与 test_metric2 的两个数据源, 从UTC时间2023年06月01日00时00分00秒开始的数据,通过运行在 192.168.1.20 上的 taoskeeper, 同步至 TDengine 的 test_db 数据库中,完整的命令如下所示: + +```bash +taosx run \ + --from "opentsdb+http://192.168.1.10:4242/?metrics=test_metric1,test_metric2&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ + --to "taos+http://192.168.1.20:6041/test_db" \ + -vv +``` + +在这个命令中,未指定endTime, 所以任务会长期运行,持续同步最新的数据。 + + +### 从 MQTT 同步数据到 TDengine + +目前,MQTT 连接器仅支持从 MQTT 服务端消费 JSON 格式的消息,并将其同步至 TDengine. 命令如下所示: + +```bash +taosx run --from "" --to "" --parser "@" +``` + +其中: +- `--from` 用于指定 MQTT 数据源的 DSN +- `--to` 用于指定 TDengine 的 DSN +- `--parser` 用于指定一个 JSON 格式的配置文件,该文件决定了如何解析 JSON 格式的 MQTT 消息,以及写入 TDengine 时的超级表名、子表名、字段名称和类型,以及标签名称和类型等。 + +#### MQTT DSN 配置 + +MQTT DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: +- topics: 必填,用于配置监听的 MQTT 主题名称和连接器支持的最大 QoS, 采用 `::` 的形式;支持配置多个主题,使用逗号分隔;配置主题时,还可以使用 MQTT 协议的支持的通配符#和+; +- version: 非必填,用于配置 MQTT 协议的版本,支持的版本包括:3.1/3.1.1/5.0, 默认值为3.1; +- clean_session: 非必填,用于配置连接器作为 MQTT 客户端连接至 MQTT 服务端时,服务端是否保存该会话信息,其默认值为 true, 即不保存会话信息; +- client_id: 必填,用于配置连接器作为 MQTT 客户端连接至 MQTT 服务端时的客户端 id; +- keep_alive: 非必填,用于配置连接器作为 MQTT 客户端,向 MQTT 服务端发出 PINGREG 消息后的等待时间,如果连接器在该时间内,未收到来自 MQTT 服务端的 PINGREQ, 连接器则主动断开连接;该配置的单位为秒,默认值为 60; +- ca: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的 CA 证书,其值为在证书文件的绝对路径前添加@, 例如:@/home/admin/certs/ca.crt; +- cert: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的客户端证书,其值为在证书文件的绝对路径前添加@, 例如:@/home/admin/certs/client.crt; +- cert_key: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的客户端私钥,其值为在私钥文件的绝对路径前添加@, 例如:@/home/admin/certs/client.key; +- log_level: 非必填,用于配置连接器的日志级别,连接器支持 error/warn/info/debug/trace 5种日志级别,默认值为 info. + +一个完整的 MQTT DSN 示例如下: +```bash +mqtt://:@:8883?topics=testtopic/1::2&version=3.1&clean_session=true&log_level=info&client_id=taosdata_1234&keep_alive=60&ca=@/home/admin/certs/ca.crt&cert=@/home/admin/certs/client.crt&cert_key=@/home/admin/certs/client.key +``` + +#### MQTT 连接器的解释器配置 + +连接器的解释器配置文件,即`--parser`配置项的参数,它的值为一个 JSON 文件,其配置可分为`parse`和`model`两部分,模板如下所示: + +```json +{ + "parse": { + "payload": { + "json": [ + { + "name": "ts", + "alias": "ts", + "cast": "TIMESTAMP" + }, + ... + ] + } + }, + "model": { + "using": "", + "name": "{alias}", + "columns": [ ... ], + "tags": [ ... ] + } +} +``` + +各字段的说明如下: +- parse 部分目前仅支持 json 一种 payload, json 字段的值是一个由 JSON Object 构成的 JSON Array: + - 每个 JSON Ojbect 包括 name, alias, cast 三个字段; + - name 字段用于指定如何从 MQTT 消息中提取字段,如果 MQTT 消息是一个简单的 JSON Object, 这里可以直接设置其字段名;如果 MQTT 消息是一个复杂的 JSON Object, 这里可以使用 JSON Path 提取字段,例如:`$.data.city`; + - alias 字段用于命名 MQTT 消息中的字段同步至 TDengine 后使用的名称; + - cast 字段用于指定 MQTT 消息中的字段同步至 TDengine 后使用的类型。 +- model 部分用于设置 TDengine 超级表、子表、列和标签等信息: + - using 字段用于指定超级表名称; + - name 字段用于指定子表名称,它的值可以分为前缀和变量两部分,变量为 parse 部分设置的 alias 的值,需要使用{}, 例如:d{id}; + - columns 字段用于设置 MQTT 消息中的哪些字段作为 TDengine 超级表中的列,取值为 parse 部分设置的 alias 的值;需要注意的是,这里的顺序会决定 TDengine 超级表中列的顺序,因此第一列必须为 TIMESTAMP 类型; + - tags 字段用于设置 MQTT 消息中的哪些字段作为 TDengine 超级表中的标签,取值为 parse 部分设置的 alias 的值。 + +#### 举例说明 + +在 192.168.1.10 的 1883 端口运行着一个 MQTT broker, 用户名、口令分别为admin, 123456; 现欲将其中的消息,通过运行在 192.168.1.20 的 taosadapter 同步至 TDengine 的 test 数据库中。MQTT 消息格式为: + +```json +{ + "id": 1, + "current": 10.77, + "voltage": 222, + "phase": 0.77, + "groupid": 7, + "location": "California.SanDiego" +} +``` + +MQTT 消息同步至 TDengine 时, 如果采用 meters 作为超级表名,前缀“d”拼接id字段的值作为子表名,ts, id, current, voltage, phase作为超级表的列,groupid, location作为超级表的标签,其解释器的配置如下: +```json +{ + "parse": { + "payload": { + "json": [ + { + "name": "ts", + "alias": "ts", + "cast": "TIMESTAMP" + }, + { + "name": "id", + "alias": "id", + "cast": "INT" + }, + { + "name": "voltage", + "alias": "voltage", + "cast": "INT" + }, + { + "name": "phase", + "alias": "phase", + "cast": "FLOAT" + }, + { + "name": "current", + "alias": "current", + "cast": "FLOAT" + }, + { + "name": "groupid", + "alias": "groupid", + "cast": "INT" + }, + { + "name": "location", + "alias": "location", + "cast": "VARCHAR(20)" + } + ] + } + }, + "model": { + "name": "d{id}", + "using": "meters", + "columns": [ + "ts", + "id", + "current", + "voltage", + "phase" + ], + "tags": [ + "groupid", + "location" + ] + } +} +``` + +如果以上parser配置位于`/home/admin/parser.json`中,那么完整的命令如下所示: + +```bash +taosx run \ + -f "mqtt://admin:123456@192.168.1.10:1883?topics=testtopic/1::2&version=3.1&clean_session=true&log_level=info&client_id=1234&keep_alive=60" \ + -t "taos+ws://192.168.1.20:6041/test" + --parser "@/home/admin/parser.json" + --verbose +``` + +### 从 Kafka 同步数据到 TDengine + +#### 命令行参数 + +taosx 支持从 Kafka 消费数据,写入 TDengine。命令如下所示: +```sehll +taosx run -f "" -t "" +``` +或 +```shell +taosx run -f "" -t "" --parser "@" +``` +其中: +- -f或--from: Kafka 的 DSN +- -t或--to :TDengine 的 DSN +- --parser :一个 JSON 格式的配置文件,或JSON格式的字符串。 + +#### Kafka DSN 配置的配置 + +| 参数 | 说明 | 必填? | 缺省值 | 适用于 | 示例 | +|-----|---------------|----------|---------|---------|----------| +| group| 消费者的group。允许组为空字符串,在这种情况下,生成的消费者将是无组的 | 否 | "" | 源端 | | +| topics | 指定要使用的主题。指定主题的所有可用分区都将被使用,除非在指定 topic_partitions 时被覆盖。| 该参数或topic_partitions必须至少指定一个,以便将主题分配给消费者。| None | 源端 | topics=tp1,tp2 | +| topic_partitions | 显式指定要使用的主题分区。只使用已标识主题的指定分区。 | 该参数或topics必须至少指定一个,以便将主题分配给消费者。 | None | 源端 | topic_partitions=tp1:0..2,tp2:1 | +| fallback_offset | topic偏移量时可能的值:- Earliest:接收最早的可用偏移量; - Latest:接收最近的偏移量; - ByTime(i64):用于请求在某一特定时间(ms)之前的所有消息;Unix时间戳(毫秒) | 否 | Earliest | 源端 | fallback_offset=Earliest | +| offset_storage | 定义在获取或提交组偏移量时,要使用的可用存储:- Zookeeper:基于Zookeeper的存储(从kafka 0.8.1开始可用);- Kafka:基于Kafka的存储(从Kafka 0.8.2开始可用)。这是组存储其偏移量的首选方法。 | 否 | Kafka | 源端 | offset_storage=Kafka | +| timeout | 从kafka订阅数据时,如果超时后没有获取到有效数据,退出 | 否 | 500 | 源端 | timeout=never | +| use_ssl | 是否使用SSL认证 | 否 | | 源端 | | +| cert | SSL证书的文件路径 | 否 | | | 源端 | | +| cert_key | SSL证书key的文件路径 | 否 | | 源端 || + + +#### 示例一 + +从192.168.1.92服务器的Kafka实例中消费数据,同步到192.168.1.92上的TDengine,不使用parser。 + +1. kafka + +```shell +#!/bin/bash +KAFKA_HOME=/root/zyyang/kafka_2.13-3.1.0 +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --delete +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --delete +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --partitions 5 --replication-factor 1 --create +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --partitions 1 --replication-factor 1 --create +$KAFKA_HOME/bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 << EOF +{"id": 1, "message": "hello"} +{"id": 2, "message": "hello"} +{"id": 3, "message": "hello"} +{"id": 4, "message": "hello"} +{"id": 5, "message": "hello"} +EOF +$KAFKA_HOME/bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 << EOF +{"id": 1, "message": "aaa"} +{"id": 2, "message": "aaa"} +{"id": 3, "message": "aaa"} +{"id": 4, "message": "aaa"} +{"id": 5, "message": "aaa"} +EOF +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --describe +$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --describe +``` + +2. TDengine + +```shell +drop database if exists kafka_to_taos; +create database if not exists kafka_to_taos precision 'ms'; +use kafka_to_taos; +``` + +3. taosx + +```shell +taosx run -f "kafka://192.168.1.92:9092/?topics=tp1,tp2&timeout=5000" -t "taos://192.168.1.92:6030/kafka_to_taos" --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"key\":{\"as\":\"binary\",\"alias\":\"k\"},\"value\":{\"as\":\"binary\",\"alias\":\"v\"}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"k\",\"v\"]}]}" +``` + +#### 示例2 + +从192.168.1.92服务器的Kafka实例中消费数据,同步到192.168.1.92上的TDengine,使用parser解析value中的JSON数据。 + +1. kafka,同“示例1” +2. TDengine,同“示例1” +3. Taosx + +```shell +taosx run -f "kafka://192.168.1.92:9092/?topics=tp1,tp2&timeout=5000" -t "taos://192.168.0.201:6030/kafka_to_taos" --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"value\":{\"json\":[\"id::int\",\"message::binary\"]}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"id\",\"message\"]}]}" +``` + +## 服务模式 + +在服务模式下, 一共需要三个组件协同完成数据迁移。 taosX,Agent 以及 taosExplorer 均已服务态运行,各种操作通过 taosExplorer 的图形界面进行。taos-Explorer 组件除了数据迁移之外,还提供了使用 TDengine 的图形化界面。 + +### 部署 taosX + +#### 配置 + +taosX 仅支持通过命令行参数进行配置。服务模式下,taosX 支持的命令行参数可以通过以下方式查看: + +``` +taosx serve --help +``` + +建议通过 Systemd 的方式,启动 taosX 的服务模式,其 Systemd 的配置文件位于:`/etc/systemd/system/taosx.service`. 如需修改 taosX 的启动参数,可以编辑该文件中的以下行: + +``` +ExecStart=/usr/bin/taosx serve -v +``` + +修改后,需执行以下命令重启 taosX 服务,使配置生效: + +``` +systemctl daemon-reload +systemctl restart taosx +``` + +#### 启动 + +Linux 系统上以 Systemd 的方式启动 taosX 的命令如下: + +```shell +systemctl start taosx +``` + +Windows 系统上,请在 "Services" 系统管理工具中找到 "taosX" 服务,然后点击 "启动这个服务"。 + +#### 问题排查 + +1. 如何修改 taosX 的日志级别? + +taosX 的日志级别是通过命令行参数指定的,默认的日志级别为 Info, 具体参数如下: +- INFO: `taosx serve -v` +- DEBUG: `taosx serve -vv` +- TRACE: `taosx serve -vvv` + +Systemd 方式启动时,如何修改命令行参数,请参考“配置”章节。 + +2. 如何查看 taosX 的日志? + +以 Systemd 方式启动时,可通过 journalctl 命令查看日志。以滚动方式,实时查看最新日志的命令如下: + +``` +journalctl -u taosx -f +``` + +### 部署 Agent + +#### 配置 + +Agent 默认的配置文件位于`/etc/taos/agent.toml`, 包含以下配置项: +- endpoint: 必填,taosX 的 GRPC endpoint +- token: 必填,在 taosExplorer 上创建 agent 时,产生的token +- debug_level: 非必填,默认为 info, 还支持 debug, trace 等级别 + +如下所示: + +```TOML +endpoint = "grpc://:6055" +token = "" +log_level = "debug" +``` + +日志保存时间设置 +日志保存的天数可以通过环境变量进行设置 TAOSX_LOGS_KEEP_DAYS, 默认为 30 天。 + +```shell +export TAOSX_LOGS_KEEP_DAYS=7 +``` + +#### 启动 + +Linux 系统上 Agent 可以通过 Systemd 命令启动: + +``` +systemctl start taosx-agent +``` + +Windows 系统上通过系统管理工具 "Services" 找到 taosx-agent 服务,然后启动它。 + +#### 问题排查 + +可以通过 journalctl 查看 Agent 的日志 + +``` +journalctl -u taosx-agent -f +``` + +### 部署 taosExplorer + + +### 数据同步功能 + +请参考 taosExplorer \ No newline at end of file diff --git a/docs/zh/18-data-transfer/02-explorer.md b/docs/zh/18-data-transfer/02-explorer.md new file mode 100644 index 0000000000..6d410c4997 --- /dev/null +++ b/docs/zh/18-data-transfer/02-explorer.md @@ -0,0 +1,128 @@ +--- +title: 基于可视化界面的数据迁移 +--- + +本节讲述使用 taos Explorer 的可视化界面进行数据迁移,使用此功能需要依赖 taosd, taosAdapter, taosX, taos-explorer 等几个服务组件。关于 taosd 和 taosAdapter 的部署请参考 [系统部署](../../deployment/deploy),[taosX](../taosX),以及 [部署 taos-explorer](../../operation/explorer) + +## 功能入口 + +点击 explorer 左侧功能列表中的 "数据写入",可以配置不同类型的数据源,包括 TDengine Subscription, PI, OPC-UA, OPC-DA, InfluxDB, MQTT,Kafka, CSV 等,将它们的数据写入到当前正在被管理的 TDengine 集群中。 + +## TDengine 订阅 + +进入TDengine订阅任务配置页面: +1. 在连接协议栏中,配置连接协议,默认为原生连接,可配置为WS、WSS; +2. 在服务器栏中配置服务器的 IP 或域名; +3. 在端口栏中配置连接的端口号,默认值为6030; +4. 在主题栏中,配置可以配置订阅一个或多个数据库,或超级表或普通表,也可以是一个已创建的 Topic; +5. 在认证栏,可以配置访问 TDengine 的用户名密码,用户名默认值为 root,密码默认值为 taosdata;如果数据源为云服务实例,则可以选择令牌认证方式并配置实例 token; +6. 在订阅初始位置栏,可配置从最早数据(earliest)或最晚(latest)数据开始订阅,默认为 earliest; +7. 在超时栏配置超时时间,可配置为 never: 表示无超时时间,持续进行订阅,也可指定超时时间:5s, 1m 等,支持单位 ms(毫秒),s(秒),m(分钟),h(小时),d(天),M(月),y(年)。 +8. 在目标数据库栏中,选择本地 TDengine 的库作为目标库,点击 submit,即可启动一个 TDengine 订阅任务。 + +## Pi + +1. 在 PI 数据接入页面,设置 PI 服务器的名称、AF 数据库名称。 +2. 在监测点集栏,可以配置选择 Point 模式监测点集合、Point 模式监测的 AF 模板、AF 模式监测的 AF 模板。 +3. 在 PI 系统设置栏,可以配置 PI 系统名,默认为 PI 服务器名。 +4. 在 Data Queue 栏,可以配置 PI 连接器运行参数:MaxWaitLen(数据最大缓冲条数),默认值为 1000 ,有效取值范围为 [1,10000];UpdateInterval(PI System 取数据频率),默认值为 10000(毫秒:ms),有效取值范围为 [10,600000];重启补偿时间(Max Backfill Range,单位:天),每次重启服务时向前补偿该天数的数据,默认为1天。 +5. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit ,即可启动一个 PI 数据接入任务。 + +## OPC-UA + +1. 在 OPC-UA页面,配置 OPC-server 的地址,输入格式为 127.0.0.1:6666/OPCUA/ServerPath。 +2. 在认证栏,选择访问方式。可以选择匿名访问、用户名密码访问、证书访问。使用证书访问时,需配置证书文件信息、私钥文件信息、OPC-UA 安全协议和 OPC-UA 安全策略 +3. 在 Data Sets 栏,配置点位信息。(可通过“选择”按钮选择正则表达式过滤点位,每次最多能过滤出10条点位);点位配置有两种方式:1.手动输入点位信息 2.上传csv文件配置点位信息 +4. 在连接配置栏,配置连接超时间隔和采集超时间隔(单位:秒),默认值为10秒。 +5. 在采集配置栏,配置采集间隔(单位:秒)、点位数量、采集模式。采集模式可选择observe(轮询模式)和subscribe(订阅模式),默认值为observe。 +6. 在库表配置栏,配置目标 TDengine 中存储数据的超级表、子表结构信息。 +7. 在其他配置栏,配置并行度、单次采集上报批次(默认值100)、上报超时时间(单位:秒,默认值10)、是否开启debug级别日志。 +8. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit,即可启动一个 OPC-UA 数据接入任务。 + +## OPC-DA + +1. 在 OPC-DA页面,配置 OPC-server 的地址,输入格式为 127.0.0.1<,localhost>/Matrikon.OPC.Simulation.1。 +2. 在数据点栏,配置 OPC-DA 采集点信息。(可通过“选择”按钮选择正则表达式过滤点位,每次最多能过滤出10条点位)。点位配置有两种方式:1.手动输入点位信息 2.上传csv文件配置点位信息 +3. 在连接栏,配置连接超时时间(单位:秒,默认值为10秒)、采集超时时间(单位:秒,默认值为10秒)。 +4. 在库表配置栏,配置目标 TDengine 中存储数据的超级表、子表结构信息。 +5. 在其他配置栏,配置并行度、单次采集上报批次(默认值100)、上报超时时间(单位:秒,默认值10)、是否开启debug级别日志。 +6. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit,即可启动一个 OPC-DA 数据接入任务。 + +## InfluxDB + +进入 InfluxDB 数据源同步任务的编辑页面后: +1. 在服务器地址输入框, 输入 InfluxDB 服务器的地址,可以输入 IP 地址或域名,此项为必填字段; +2. 在端口输入框, 输入 InfluxDB 服务器端口,默认情况下,InfluxDB 监听8086端口的 HTTP 请求和8088端口的 HTTPS 请求,此项为必填字段; +3. 在组织 ID 输入框,输入将要同步的组织 ID,此项为必填字段; +4. 在令牌 Token 输入框,输入一个至少拥有读取这个组织 ID 下的指定 Bucket 权限的 Token, 此项为必填字段; +5. 在同步设置的起始时间项下,通过点选选择一个同步数据的起始时间,起始时间使用 UTC 时间, 此项为必填字段; +6. 在同步设置的结束时间项下,当不指定结束时间时,将持续进行最新数据的同步;当指定结束时间时,将只同步到这个结束时间为止; 结束时间使用 UTC 时间,此项为可选字段; +7. 在桶 Bucket 输入框,输入一个需要同步的 Bucket,目前只支持同步一个 Bucket 至 TDengine 数据库,此项为必填字段; +8. 在目标数据库下拉列表,选择一个将要写入的 TDengine 目标数据库 (注意:目前只支持同步到精度为纳秒的 TDengine 目标数据库),此项为必填字段; +9. 填写完成以上信息后,点击提交按钮,即可直接启动从 InfluxDB 到 TDengine 的数据同步。 + +## MQTT + +进入 MQTT 数据源同步任务的编辑页面后: +1. 在 MQTT 地址卡片,输入 MQTT 地址,必填字段,包括 IP 和 端口号,例如:192.168.1.10:1883; +2. 在认证卡片,输入 MQTT 连接器访问 MQTT 服务器时的用户名和密码,这两个字段为选填字段,如果未输入,即采用匿名认证的方式; +3. 在 SSL 证书卡片,可以选择是否打开 SSL/TLS 开关,如果打开此开关,MQTT 连接器和 MQTT 服务器之间的通信将采用 SSL/TLS 的方式进行加密;打开这个开关后,会出现 CA, 客户端证书和客户端私钥三个必填配置项,可以在这里输入证书和私钥文件的内容; +4. 在连接卡片,可以配置以下信息: + - MQTT 协议:支持3.1/3.1.1/5.0三个版本; + - Client ID: MQTT 连接器连接 MQTT 服务器时所使用的客户端 ID, 用于标识客户端的身份; + - Keep Alive: 用于配置 MQTT 连接器与 MQTT 服务器之间的Keep Alive时间,默认值为60秒; + - Clean Session: 用于配置 MQTT 连接器是否以Clean Session的方式连接至 MQTT 服务器,默认值为True; + - 订阅主题及 QoS 配置:这里用来配置监听的 MQTT 主题,以及该主题支持的最大QoS, 主题和 QoS 的配置之间用::分隔,多个主题之间用,分隔,主题的配置可以支持 MQTT 协议的通配符#和+; +5. 在其他卡片,可以配置 MQTT 连接器的日志级别,支持 error, warn, info, debug, trace 5个级别,默认值为 info; +6. MQTT Payload 解析卡片,用于配置如何解析 MQTT 消息: + - 配置表的第一行为 ts 字段,该字段为 TIMESTAMP 类型,它的值为 MQTT 连接器收到 MQTT 消息的时间; + - 配置表的第二行为 topic 字段,为该消息的主题名称,可以选择将该字段作为列或者标签同步至 TDengine; + - 配置表的第三行为 qos 字段,为该消息的 QoS 属性,可以选择将该字段作为列或者标签同步至 TDengine; + - 剩余的配置项皆为自定义字段,每个字段都需要配置:字段(来源),列(目标),列类型(目标)。字段(来源)是指该 MQTT 消息中的字段名称,当前仅支持 JSON 类型的 MQTT 消息同步,可以使用 JSON Path 语法从 MQTT 消息中提取字段,例如:$.data.id; 列(目标)是指同步至 TDengine 后的字段名称;列类型(目标)是指同步至 TDengine 后的字段类型,可以从下拉列表中选择;当且仅当以上3个配置都填写后,才能新增下一个字段; + - 如果 MQTT 消息中包含时间戳,可以选择新增一个自定义字段,将其作为同步至 TDengine 时的主键;需要注意的是,MQTT 消息中时间戳的仅支持 Unix Timestamp格式,且该字段的列类型(目标)的选择,需要与创建 TDengine 数据库时的配置一致; + - 子表命名规则:用于配置子表名称,采用“前缀+{列类型(目标)}”的格式,例如:d{id}; + - 超级表名:用于配置同步至 TDengine 时,采用的超级表名; +7. 在目标数据库卡片,可以选择同步至 TDengine 的数据库名称,支持直接从下拉列表中选择。 +8. 填写完成以上信息后,点击提交按钮,即可直接启动从 MQTT 到 TDengine 的数据同步。 + +## Kafka + +1. 在Kafka页面,配置Kafka选项,必填字段,包括:bootstrap_server,例如192.168.1.92:9092; +2. 如果使用SSL认证,在SSL认证卡中,选择cert和cert_key的文件路径; +3. 配置其他参数,topics、topic_partitions这2个参数至少填写一个,其他参数有默认值; +4. 如果消费的Kafka数据是JSON格式,可以配置parser卡片,对数据进行解析转换; +5. 在目标数据库卡片中,选择同步到TDengine的数据库名称,支持从下拉列表中选择; +6. 填写完以上信息后,点击提交按钮,即可启动从Kafka到TDengine的数据同步。 + +## CSV + +1. 在CSV页面,配置CSV选项,可设置忽略前N行,可输入具体的数字 +2. CSV的写入配置,设置批次写入量,默认是1000 +3. CSV文件解析,用于获取CSV对应的列信息: + - 上传CSV文件或者输入CSV文件的地址 + - 选择是否包包含Header + - 包含Header情况下直接执行下一步,查询出对应CSV的列信息,获取CSV的配置信息 + - 不包含Header情况,需要输入自定列信息,并以逗号分隔,然后下一步,获取CSV的配置信息 + - CSV的配置项,每个字段都需要配置:CSV列,DB列,列类型(目标),主键(整个配置只能有一个主键,且主键必须是TIMESTAMP类型),作为列,作为Tag。CSV列是指该 CSV文件中的列或者自定义的列;DB列是对应的数据表的列 + - 子表命名规则:用于配置子表名称,采用“前缀+{列类型(目标)}”的格式,例如:d{id}; + - 超级表名:用于配置同步至 TDengine 时,采用的超级表名; +4. 在目标数据库卡片,可以选择同步至 TDengine 的数据库名称,支持直接从下拉列表中选择。 +5. 填写完成以上信息后,点击提交按钮,即可直接启动从 CSV到 TDengine 的数据同步。 + + +## 备份和恢复 + +您可以将当前连接的 TDengine 集群中的数据备份至一个或多个本地文件中,稍后可以通过这些文件进行数据恢复。本章节将介绍数据备份和恢复的具体步骤。 + +### 备份数据到本地文件 + +1. 进入系统管理页面,点击【备份】进入数据备份页面,点击右上角【新增备份】。 +2. 在数据备份配置页面中可以配置三个参数: + - 备份周期:必填项,配置每次执行数据备份的时间间隔,可通过下拉框选择每天、每 7 天、每 30 天执行一次数据备份,配置后,会在对应的备份周期的0:00时启动一次数据备份任务; + - 数据库:必填项,配置需要备份的数据库名(数据库的 wal_retention_period 参数需大于0); + - 目录:必填项,配置将数据备份到 taosX 所在运行环境中指定的路径下,如 /root/data_backup; +3. 点击【确定】,可创建数据备份任务。 + +### 从本地文件恢复 + +1. 完成数据备份任务创建后,在页面中对应的数据备份任务右侧点击【数据恢复】,可将已经备份到指定路径下的数据恢复到当前 TDengine 中。 \ No newline at end of file From 1aa20c96e105d696902a1ea888cc90985e9af556 Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 19:58:03 +0800 Subject: [PATCH 03/15] doc: fix broken links --- docs/zh/17-operation/09-storage.md | 4 ++++ docs/zh/18-data-transfer/02-explorer.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/zh/17-operation/09-storage.md b/docs/zh/17-operation/09-storage.md index f6cdb347b4..ca3f3af49b 100644 --- a/docs/zh/17-operation/09-storage.md +++ b/docs/zh/17-operation/09-storage.md @@ -50,3 +50,7 @@ dataDir /mnt/data6 2 0 在多级存储中,有且只有一个主挂载点,主挂载点承担了系统中最重要的元数据在座,同时各个 vnode 的主目录均存在于当前 dnode 主挂载点上,从而导致该 dnode 的写入性能受限于单个磁盘的 IO 吞吐能力。 从 TDengine 3.1.0.0 开始,如果一个 dnode 配置了多个 0 级挂载点,我们将该 dnode 上所有 vnode 的主目录均衡分布在所有的 0 级挂载点上,由这些 0 级挂载点共同承担写入负荷。在网络 I/O 及其它处理资源不成为瓶颈的情况下,通过优化集群配置,测试结果证明整个系统的写入能力和 0 级挂载点的数量呈现线性关系,即随着 0 级挂载点数量的增加,整个系统的写入能力也成倍增加。 + +## 同级挂载点选择策略 + +一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 `minimalDataDirGB` \ No newline at end of file diff --git a/docs/zh/18-data-transfer/02-explorer.md b/docs/zh/18-data-transfer/02-explorer.md index 6d410c4997..0bc0a0f559 100644 --- a/docs/zh/18-data-transfer/02-explorer.md +++ b/docs/zh/18-data-transfer/02-explorer.md @@ -2,7 +2,7 @@ title: 基于可视化界面的数据迁移 --- -本节讲述使用 taos Explorer 的可视化界面进行数据迁移,使用此功能需要依赖 taosd, taosAdapter, taosX, taos-explorer 等几个服务组件。关于 taosd 和 taosAdapter 的部署请参考 [系统部署](../../deployment/deploy),[taosX](../taosX),以及 [部署 taos-explorer](../../operation/explorer) +本节讲述使用 taos Explorer 的可视化界面进行数据迁移,使用此功能需要依赖 taosd, taosAdapter, taosX, taos-explorer 等几个服务组件。关于 taosd 和 taosAdapter 的部署请参考 [系统部署](../../deployment/deploy),[taosX](../taosX),以及 [部署 taos-explorer](../../operation/web) ## 功能入口 From 9dc7fe051d94e54ef9cbfe970f2d097ca972b48e Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 20:19:15 +0800 Subject: [PATCH 04/15] doc: refine enterprise --- docs/zh/17-operation/08-web.md | 4 ++-- docs/zh/17-operation/09-storage.md | 2 +- docs/zh/18-data-transfer/index.md | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 docs/zh/18-data-transfer/index.md diff --git a/docs/zh/17-operation/08-web.md b/docs/zh/17-operation/08-web.md index 9923c9912e..6560bb979f 100644 --- a/docs/zh/17-operation/08-web.md +++ b/docs/zh/17-operation/08-web.md @@ -1,6 +1,6 @@ --- -title: 基于 Web 的系统管理工具 -description: 本节描述 TDengine 的图形化管理工具, taos-explorer, 的基本功能 +title: Web 管理工具 +description: 基于 Web 的系统管理工具 --- ## 简介 diff --git a/docs/zh/17-operation/09-storage.md b/docs/zh/17-operation/09-storage.md index ca3f3af49b..018525861b 100644 --- a/docs/zh/17-operation/09-storage.md +++ b/docs/zh/17-operation/09-storage.md @@ -53,4 +53,4 @@ dataDir /mnt/data6 2 0 ## 同级挂载点选择策略 -一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 `minimalDataDirGB` \ No newline at end of file +一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 2GB,即会跳过可用空间小于 2GB 的挂载点。 \ No newline at end of file diff --git a/docs/zh/18-data-transfer/index.md b/docs/zh/18-data-transfer/index.md new file mode 100644 index 0000000000..749ad16308 --- /dev/null +++ b/docs/zh/18-data-transfer/index.md @@ -0,0 +1,3 @@ +--- +title: 数据集成 +--- \ No newline at end of file From 4f52ae097fe14e1f36236446ae51522ff9f6293a Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 20:47:32 +0800 Subject: [PATCH 05/15] doc: refine enterprise --- docs/zh/17-operation/07-cluster.md | 4 +++- docs/zh/18-data-transfer/02-explorer.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/zh/17-operation/07-cluster.md b/docs/zh/17-operation/07-cluster.md index 0b7fb7e53d..cf4bfafd53 100644 --- a/docs/zh/17-operation/07-cluster.md +++ b/docs/zh/17-operation/07-cluster.md @@ -47,7 +47,9 @@ Raft选举本身带有随机性,所以通过选举的重新分布产生的均 ## 恢复数据节点 -当集群中的某个数据节点(dnode)的数据全部丢失或被破坏,比如磁盘损坏或者目录被误删除,可以通过 `restore dnode` 命令来恢复该数据节点上的部分或全部逻辑节点,该功能依赖多副本中的其它副本进行数据复制,所以只在集群中 dnode 数量大于等于 3 且副本数为 3 的情况下能够工作。 +在多节点三副本的集群环境中,如果某个 dnode 的磁盘损坏,该 dnode 会自动退出,但集群中其它的 dnode 仍然能够继续提供写入和查询服务。 + +在更换了损坏的磁盘后,如果想要让曾经主动退出的 dnode 重新加入集群提供服务,可以通过 `restore dnode` 命令来恢复该数据节点上的部分或全部逻辑节点,该功能依赖多副本中的其它副本进行数据复制,所以只在集群中 dnode 数量大于等于 3 且副本数为 3 的情况下能够工作。 ```sql diff --git a/docs/zh/18-data-transfer/02-explorer.md b/docs/zh/18-data-transfer/02-explorer.md index 0bc0a0f559..fd374cc734 100644 --- a/docs/zh/18-data-transfer/02-explorer.md +++ b/docs/zh/18-data-transfer/02-explorer.md @@ -1,5 +1,5 @@ --- -title: 基于可视化界面的数据迁移 +title: 基于可视化界面的数据接入和数据迁移 --- 本节讲述使用 taos Explorer 的可视化界面进行数据迁移,使用此功能需要依赖 taosd, taosAdapter, taosX, taos-explorer 等几个服务组件。关于 taosd 和 taosAdapter 的部署请参考 [系统部署](../../deployment/deploy),[taosX](../taosX),以及 [部署 taos-explorer](../../operation/web) From cf417eb31dd42f696b7d12bee91ecc1fb3502544 Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 21:00:03 +0800 Subject: [PATCH 06/15] doc: add product description and links --- docs/zh/02-intro.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/zh/02-intro.md b/docs/zh/02-intro.md index 888f779966..68a2541717 100644 --- a/docs/zh/02-intro.md +++ b/docs/zh/02-intro.md @@ -6,7 +6,14 @@ toc_max_heading_level: 2 TDengine 是一款开源、高性能、云原生的[时序数据库](https://tdengine.com/tsdb/),且针对物联网、车联网、工业互联网、金融、IT 运维等场景进行了优化。TDengine 的代码,包括集群功能,都在 GNU AGPL v3.0 下开源。除核心的时序数据库功能外,TDengine 还提供[缓存](../develop/cache/)、[数据订阅](../develop/tmq)、[流式计算](../develop/stream)等其它功能以降低系统复杂度及研发和运维成本。 -本章节介绍 TDengine 的主要功能、竞争优势、适用场景、与其他数据库的对比测试等等,让大家对 TDengine 有个整体的了解。 +本章节介绍 TDengine 的主要产品和功能、竞争优势、适用场景、与其他数据库的对比测试等等,让大家对 TDengine 有个整体的了解。 + +## 主要产品 + +TDengine 有三个主要产品:TDengine Pro (即 TDengine 企业版),TDengine Cloud,和 TDengine OSS,关于它们的具体定义请参考 +- [TDengine 企业版](https://www.taosdata.com/tdengine-pro) +- [TDengine 云服务](https://cloud.taosdata.com/?utm_source=menu&utm_medium=webcn) +- [TDengine 开源版](https://www.taosdata.com/tdengine-oss) ## 主要功能 From ca67d8d2f05b116eea086fb715d6bc2aca0627c5 Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 23:28:02 +0800 Subject: [PATCH 07/15] doc: remove taosx and explorer from website --- docs/zh/17-operation/08-web.md | 178 ----- docs/zh/18-data-transfer/01-taosX.md | 972 ------------------------ docs/zh/18-data-transfer/02-explorer.md | 128 ---- docs/zh/18-data-transfer/index.md | 3 - 4 files changed, 1281 deletions(-) delete mode 100644 docs/zh/17-operation/08-web.md delete mode 100644 docs/zh/18-data-transfer/01-taosX.md delete mode 100644 docs/zh/18-data-transfer/02-explorer.md delete mode 100644 docs/zh/18-data-transfer/index.md diff --git a/docs/zh/17-operation/08-web.md b/docs/zh/17-operation/08-web.md deleted file mode 100644 index 6560bb979f..0000000000 --- a/docs/zh/17-operation/08-web.md +++ /dev/null @@ -1,178 +0,0 @@ ---- -title: Web 管理工具 -description: 基于 Web 的系统管理工具 ---- - -## 简介 - -为了易于企业版用户更容易使用和管理数据库,TDengine 3.0 企业版提供了一个全新的可视化组件 taosExplorer。用户能够在其中方便地管理数据库管理系统中中各元素(数据库、超级表、子表)的生命周期,执行查询,监控系统状态,管理用户和授权,完成数据备份和恢复,与其它集群之间进行数据同步,导出数据,管理主题和流计算。 - -**欲体验基于 Web 的 TDengine 系统管理能力,请联系 TDengine 市场或销售团队** - -## 部署服务 - -### 准备工作 - -1. taosExplorer 没有独立的安装包,请使用 taosX 安装包进行安装。 -2. 在启动 taosExplorer 之前,请先确认 TDengine 集群已经正确设置并运行(即 taosd 服务),taosAdapter 也已经正确设置和运行并与 TDengine 集群保持连接状态。如果想要使用数据备份和恢复或者数据同步功能,请确保 taosX 服务和 Agent 服务也已经正确设置和运行。 - -### 配置 - -在启动 taosExplorer 之前,请确保配置文件中的内容正确。 - -```TOML -listen = "0.0.0.0:6060" -log_level = "info" -cluster = "http://localhost:6041" -x_api = "http://localhost:6050" -``` - -说明: - -- listen - taosExplorer 对外提供服务的地址 -- log_level - 日志级别,可选值为 "debug", "info", "warn", "error", "fatal" -- cluster - TDengine集群的 taosadapter 地址 -- x_api - taosX 的服务地址 - -### 启动 - -然后启动 taosExplorer,可以直接在命令行执行 taos-explorer 或者使用下面的 systemctl 脚本用 systemctl 来启动 taosExplorer 服务 - -```shell -[Unit] -Description=Explorer for TDengine -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -ExecStart=/usr/bin/taos-explorer -Restart=always - -[Install] -WantedBy=multi-user.target -``` - -### 问题排查 - -1. 当通过浏览器打开taosExplorer站点遇到“无法访问此网站”的错误信息时,请通过命令行登录taosExplorer所在机器,并使用命令systemctl status taos-explorer.service检查服务的状态,如果返回的状态是inactive,请使用命令systemctl start taos-explorer.service启动服务。 -2. 如果需要获取taosExplorer的详细日志,可通过命令journalctl -u taos-explorer - -## 登录 - -在 TDengine 管理系统的登录页面,输入正确的用户名和密码后,点击登录按钮,即可登录。 - -说明: -- 这里的用户,需要在所连接的 TDengine 中创建,TDengine 默认的用户名和密码为`root/taosdata`; -- 在 TDengine 中创建用户时,默认会设置用户的 SYSINFO 属性值为1, 表示该用户可以查看系统信息,只有 SYSINFO 属性为 1 的用户才能正常登录 TDengine 管理系统。 - -## 面板 - -taosExplorer 内置了一个简单的仪表盘展示以下集群信息,点击左侧功能列表中的 "面板" 可以启用此功能。 - -- 默认的仪表盘会返回对应 Grafana 的安装配置向导 -- 配置过 Grafana 的仪表盘在点击' 面板' 时会跳转到对应的配置地址(该地址来源于 /profile 接口的返回值) - - -## 数据浏览器 - -点击功能列表的“数据浏览器”入口,在“数据浏览器”中可以创建和删除数据库、创建和删除超级表和子表,执行SQL语句,查看SQL语句的执行结果。此外,超级管理员还有对数据库的管理权限,其他用户不提供该功能。 - -具体权限有: - -1.查看(提供数据库/超级表/普通表的基本信息) - -2.编辑 (编辑数据库/超级表/普通表的信息) - -3.数据库管理权限 (仅限超级管理员,该操作可以给指定用户配置数据库管理权限) - -4.删除 (删除数据库/超级表/普通表) - -5.追加 (选择对应的数据库/超级表/普通表名称直接追加到右侧sql输入区域,避免了手工输入) - - -## 系统管理 - -点击功能列表中的“系统管理”入口,可以创建用户、对用户进行访问授权、以及删除用户。还能够对当前所管理的集群中的数据进行备份和恢复。也可以配置一个远程 TDengine 的地址进行数据同步。同时也提供了集群信息和许可证的信息以及代理信息以供查看。系统管理 菜单只有 root 用户才有权限看到 - -### 用户管理 - -点击“系统管理”后,默认会进入“用户”标签页。 -在用户列表,可以查看系统中已存在的用户及其创建时间,并可以对用户进行启用、禁用,编辑(包括修改密码,数据库的读写权限等),删除等操作。 -点击用户列表右上方的“+新增”按钮,即可打开“新增用户”对话框: -1. 输入新增用户的用户名称,必填 -2. 输入新增用户的登录密码,必填,密码长度要求为8-16个字符,且至少要满足以下4个条件中的3个:大写字母,小写字母,数字,特殊字符 -3. 选择新增用户对系统中已存在的数据库的读写权限,非必填,默认情况下,新增用户对所有已存在的数据库无读写权限 -4. 提写完成后,点击确定按钮,即可新增用户。 - -### 系统信息 - -点击“集群”标签后,可以查看DNodes, MNodes和QNodes的状态、创建时间等信息,并可以对以上节点进行新增和删除操作。 - -### 许可证管理 - -点击“许可证”标签后,可以查看系统和系统和各连接器的许可证信息。 -点击位于“许可证”标签页右上角的“激活许可证”按钮,输入“激活码”和“连接器激活码”后,点击“确定”按钮,即可激活,激活码请联系 TDengine 客户成功团队获取。 - -## 数据订阅 - -本章节,将介绍如何在 TDengine 集群中,创建主题,并将其分享给其他用户,以及如何查看一个主题的消费者信息。 - -通过 Explorer, 您可以轻松地完成对数据订阅的管理,从而更好地利用 TDengine 提供的数据订阅能力。 -点击左侧导航栏中的“数据订阅”,即可跳转至数据订阅配置管理页面。 -您可以通过以下两种方式创建主题:使用向导和自定义 SQL 语句。通过自定义 SQL 创建主题时,您需要了解 TDengine 提供的数据订阅 SQL 语句的语法,并保证其正确性。 - -注: 对于数据订阅的详细说明,可参考官方文档中关于“数据订阅”章节,创建数据订阅之前需要先准备源数据库(或源数据库包含相应的超级表或者表),其中源数据库需配置wal_retention_period > 0 。 - -包括主题,消费者,共享主题和示例代码 - -### 创建主题 - -1. 在“主题”标签页,点击“新增新主题”按钮以后,选择向导窗格,然后输入“主题名称”; -2. 在“数据库”下拉列表中,选择相应的数据库; -3. 在“类型”标签下,选择“数据库” 或 “超级表” 或 “子查询”,这里以默认值“数据库”为例; -4. 然后点击“创建” 按钮,即可创建对应的主题。 - -### 分享主题 - -1. 在“共享主题”标签页,在“主题“下拉列表中,选择将要分享的主题; -2. 点击“添加可消费该主题的用户”按钮,然后在“用户名”下拉列表中选择相应的用户,然后点击“新增”,即可将该主题分享给此用户。 - - -### 查看消费者信息 - -1. 通过执行下一节“示例代码”所述的“完整实例”,即可消费共享主题 -2. 在“消费者”标签页,可查看到消费者的有关信息 - -### 示例代码 - -1. 在“示例代码”标签页,在“主题“下拉列表中,选择相应的主题; -2. 选择您熟悉的语言,然后您可以阅读以及使用这部分示例代码用来”创建消费“,”订阅主题“,通过执行 “完整实例”中的程序即可消费共享主题 - -## 流计算 - -通过 Explorer, 您可以轻松地完成对流的管理,从而更好地利用 TDengine 提供的流计算能力。 -点击左侧导航栏中的“流计算”,即可跳转至流计算配置管理页面。 -您可以通过以下两种方式创建流:流计算向导和自定义 SQL 语句。当前,通过流计算向导创建流时,暂不支持分组功能。通过自定义 SQL 创建流时,您需要了解 TDengine 提供的流计算 SQL 语句的语法,并保证其正确性。 - -注: 对于流计算的详细说明,可参考官方文档中关于“流式计算”章节,创建流计算之前需要先准备源数据库以及相应的超级表或表、输出的数据库。 - -### 流计算向导 - -1. 点击“创建流计算”按钮以后,选择流计算向导窗格,然后输入“流名称”; -2. 在“输出”部分,输入相应的“数据库”,“超级表”以及“子表前缀”; -3. 在“源”部分,选择相应的“数据库”,然后根据具体情况,选择使用“超级表”或“表”: - 1. 如果使用“超级表“,请从“超级表”下拉列表中选择相应的超级表, 并在“字段设置”区域,选择相应的字段 - 2. 如果使用“表“,请从“表”下拉列表中选择相应的表, 并在“字段设置”区域,选择相应的字段 -4. 对于窗口设置,根据需要选择”SESSION“, "STATE"或"INTERVAL", 并配置相应的值; -5. 对于”执行“部分,选择相应的”触发器“类型,并设置“Watermark”, "Ignore Expired", "DELETE_MARK", "FILL_HISTORY", "IGNORE UPDATE"; -6. 然后点击“创建” 按钮,即可创建对应的流计算。 - -### 使用 SQL 语句建流 - -1. 点击“创建流计算”按钮以后,选择流计算SQL窗格,然后输入类似如下的SQL语句(反引号内为源数据库以及相应的超级表或表、输出的数据库,请按您的环境更新反引号内的内容) - -```shell -CREATE STREAM `test_stream` TRIGGER WINDOW_CLOSE IGNORE EXPIRED 1 INTO `db_name`.`stable1` SUBTABLE(CONCAT('table1',tbname)) AS SELECT count(*) FROM `test_db`.`stable_name` PARTITION BY tbname INTERVAL(1m) -``` -2. 点击“创建”按钮,即可创建对应的流计算。 \ No newline at end of file diff --git a/docs/zh/18-data-transfer/01-taosX.md b/docs/zh/18-data-transfer/01-taosX.md deleted file mode 100644 index 72d2cb2211..0000000000 --- a/docs/zh/18-data-transfer/01-taosX.md +++ /dev/null @@ -1,972 +0,0 @@ ---- -title: 数据接入、同步和备份 ---- - -## 简介 - -为了能够方便地将各种数据源中的数据导入 TDengine 3.0,TDengine 3.0 企业版提供了一个全新的工具 taosX 用于帮助用户快速将其它数据源中的数据传输到 TDengine 中。 taosX 定义了自己的集成框架,方便扩展新的数据源。目前支持的数据源有 TDengine 自身(即从一个 TDengine 集群到另一个 TDengine 集群),Pi, OPC UA。除了数据接入外,taosX 还支持数据备份、数据同步、数据迁移以及数据导出功能。 - -**欲体验 taosX 的各种数据接入能力,请联系 TDengine 市场或销售团队。** - -## 使用前提 - -使用 taosX 需要已经部署好 TDengine 中的 taosd 和 taosAdapter,具体细节请参考 [系统部署](../../deployment/deploy) - -**使用限制**:taosX 只能用于企业版数据库服务端。 - -## 安装与配置 - -安装 taosX 需要使用独立的 taosX 安装包,其中除了 taosX 之外,还包含 Pi 连接器(限 Windows), OPC 连接器, InfluxDB 连接器, MQTT 连接器,以及必要的 Agent 组件,taosX + Agent + 某个连接器可以用于将相应数据源的数据同步到 TDengine。taosX 安装包中还包含了 taos-explorer 这个可视化管理组件 - -### Linux 安装 - -下载需要的 taosX 安装包,下文以安装包 `taosx-1.0.0-linux-x64.tar.gz` 为例展示如何安装: - -``` bash -# 在任意目录下解压文件 -tar -zxf taosx-1.0.0-linux-x64.tar.gz -cd taosx-1.0.0-linux-x64 - -# 安装 -sudo ./install.sh - -# 验证 -taosx -V -# taosx 1.0.0-494d280c (built linux-x86_64 2023-06-21 11:06:00 +08:00) -taosx-agent -V -# taosx-agent 1.0.0-494d280c (built linux-x86_64 2023-06-21 11:06:01 +08:00) - -# 卸载 -cd /usr/local/taosx -sudo ./uninstall.sh -``` - -**常见问题:** - -1. 安装后系统中增加了哪些文件? - * /usr/bin: taosx, taosx-agent, taos-explorer - * /usr/local/taosx/plugins: influxdb, mqtt, opc - * /etc/systemd/system:taosx.service, taosx-agent.service, taos-explorer.service - * /usr/local/taosx: uninstall.sh - * /etc/taox: agent.toml, explorer.toml - -2. taosx -V 提示 "Command not found" 应该如何解决? - * 检验问题1,保证所有的文件都被复制到对应的目录 - ``` bash - ls /usr/bin | grep taosx - ``` - -### Windows 安装 - -- 下载需要的 taosX 安装包,例如 taosx-1.0.0-Windows-x64-installer.exe,执行安装 -- 可使用 uninstall_taosx.exe 进行卸载 -- 命令行执行 ```sc start/stop taosx``` 启动/停止 taosx 服务 -- 命令行执行 ```sc start/stop taosx-agent``` 启动/停止 taosx-agent 服务 -- 命令行执行 ```sc start/stop taos-explorer``` 启动/停止 taosx-agent 服务 -- windows 默认安装在```C:\Program Files\taosX```,目录结构如下: -~~~ -├── bin -│   ├── taosx.exe -│   ├── taosx-srv.exe -│   ├── taosx-srv.xml -│   ├── taosx-agent.exe -│   ├── taosx-agent-srv.exe -│   ├── taosx-agent-srv.xml -│   ├── taos-explorer.exe -│   ├── taos-explorer-srv.exe -│   └── taos-explorer-srv.xml -├── plugins -│   ├── influxdb -│   │   └── taosx-inflxdb.jar -│   ├── mqtt -│   │   └── taosx-mqtt.exe -│   ├── opc -│   | └── taosx-opc.exe -│   ├── pi -│   | └── taosx-pi.exe -│   | └── taosx-pi-backfill.exe -│   | └── ... -└── config -│   ├── agent.toml -│   ├── explorer.toml -├── uninstall_taosx.exe -├── uninstall_taosx.dat -~~~ - -**运行模式** - -taosX 是进行数据同步与复制的核心组件,以下运行模式指 taosX 的运行模式,其它组件的运行模式在 taosX 的不同运行模式下与之适配。 - -## 命令行模式 - -可以直接在命令行上添加必要的参数直接启动 taosX 即为命令行模式运行。当命令行参数所指定的任务完成后 taosX 会自动停止。taosX 在运行中如果出现错误也会自动停止。也可以在任意时刻使用 ctrl+c 停止 taosX 的运行。本节介绍如何使用 taosX 的各种使用场景下的命令行。 - -### 命令行参数说明 - -**注意:部分参数暂无法通过 explorer设置【见:其他参数说明】,之后会逐步开放) ** - -命令行执行示例: - -```shell -taosx -f -t <其他参数> -``` - -以下参数说明及示例中若无特殊说明 `` 的格式均为占位符,使用时需要使用实际参数进行替换。 - -### DSN (Data Source Name) - -taosX 命令行模式使用 DSN 来表示一个数据源(来源或目的源),典型的 DSN 如下: - -```bash -# url-like -[+]://[[:@]:][/][?=[&=]] -|------|------------|---|-----------|-----------|------|------|----------|-----------------------| -|driver| protocol | | username | password | host | port | object | params | - -// url 示例 -tmq+ws://root:taosdata@localhost:6030/db1?timeout=never -``` -[] 中的数据都为可选参数。 - -1. 不同的驱动 (driver) 拥有不同的参数。driver 包含如下选项: - -- taos:使用查询接口从 TDengine 获取数据 -- tmq:启用数据订阅从 TDengine 获取数据 -- local:数据备份或恢复 -- pi: 启用 pi-connector从 pi 数据库中获取数据 -- opc:启用 opc-connector 从 opc-server 中获取数据 -- mqtt: 启用 mqtt-connector 获取 mqtt-broker 中的数据 -- kafka: 启用 Kafka 连接器从 Kafka Topics 中订阅消息写入 -- influxdb: 启用 influxdb 连接器从 InfluxDB 获取数据 -- csv:从 CSV 文件解析数据 - -2. +protocol 包含如下选项: -- +ws: 当 driver 取值为 taos 或 tmq 时使用,表示使用 rest 获取数据。不使用 +ws 则表示使用原生连接获取数据,此时需要 taosx 所在的服务器安装 taosc。 -- +ua: 当 driver 取值为 opc 时使用,表示采集的数据的 opc-server 为 opc-ua -- +da: 当 driver 取值为 opc 时使用,表示采集的数据的 opc-server 为 opc-da - -3. host:port 表示数据源的地址和端口。 -4. object 表示具体的数据源,可以是TDengine的数据库、超级表、表,也可以是本地备份文件的路径,也可以是对应数据源服务器中的数据库。 -5. username 和 password 表示该数据源的用户名和密码。 -6. params 代表了 dsn 的参数。 - -### 其它参数说明 - -1. parser 通过 --parser 或 -p 设置,设置 transform 的 parser 生效。可以通过 Explorer 在如 CSV,MQTT,KAFKA 数据源的任务配置进行设置。 - - 配置示例: - - ```shell - --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"key\":{\"as\":\"binary\",\"alias\":\"k\"},\"value\":{\"as\":\"binary\",\"alias\":\"v\"}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"k\",\"v\"]}]}" - - ``` - -2. transform 通过 --transform 或 -T 设置,配置数据同步(仅支持 2.6 到 3.0 以及 3.0 之间同步)过程中对于表名及表字段的一些操作。暂无法通过 Explorer 进行设置。配置说明如下: - - ```shell - 1.AddTag,为表添加 TAG。设置示例:-T add-tag:=。 - 2.表重命名: - 2.1 重命名表限定 - 2.1.1 RenameTable:对所有符合条件的表进行重命名。 - 2.1.2 RenameChildTable:对所有符合条件的子表进行重命名。 - 2.1.3 RenameSuperTable:对所有符合条件的超级表进行重命名。 - 2.2 重命名方式 - 2.2.1 Prefix:添加前缀。 - 2.2.2 Suffix:添加后缀。 - 2.2.3 Template:模板方式。 - 2.2.4 ReplaceWithRegex:正则替换。taosx 1.1.0 新增。 - 重命名配置方式: - <表限定>:<重命名方式>:<重命名值> - 使用示例: - 1.为所有表添加前缀 - --transform rename-table:prefix: - 2.为符合条件的表替换前缀:prefix1 替换为 prefix2,以下示例中的 <> 为正则表达式的不再是占位符。 - -T rename-child-table:replace_with_regex:^prefix1(?)::prefix2_$old - - 示例说明:^prefix1(?) 为正则表达式,该表达式会匹配表名中包含以 prefix1 开始的表名并将后缀部分记录为 old,prefix2$old 则会使用 prefix2 与 old 进行替换。注意:两部分使用关键字符 :: 进行分隔,所以需要保证正则表达式中不能包含该字符。 - 若有更复杂的替换需求请参考:https://docs.rs/regex/latest/regex/#example-replacement-with-named-capture-groups 或咨询 taosx 开发人员。 - ``` - -3. jobs 指定任务并发数,仅支持 tmq 任务。暂无法通过 Explorer 进行设置。通过 --jobs `` 或 -j `` 进行设置。 -4. -v 用于指定 taosx 的日志级别,-v 表示启用 info 级别日志,-vv 对应 debug,-vvv 对应 trace。 - - -### 从 TDengine 到 TDengine 的数据同步 - -#### TDengine 3.0 -> TDengine 3.0 - -在两个相同版本 (都是 3.0.x.y)的 TDengine 集群之间将源集群中的存量及增量数据同步到目标集群中。 - -命令行模式下支持的参数如下: - -| 参数名称 | 说明 | 默认值 | -|-----------|------------------------------------------------------------------|----------------------------| -| group.id | 订阅使用的分组ID | 若为空则使用 hash 生成一个 | -| client.id | 订阅使用的客户端ID | taosx | -| timeout | 监听数据的超时时间,当设置为 never 表示 taosx 不会停止持续监听。 | 500ms | -| offset | 从指定的 offset 开始订阅,格式为 `:`,若有多个 vgroup 则用半角逗号隔开 | 若为空则从 0 开始订阅 | -| token | 目标源参数。 认证使用参数。 | 无 | - -示例: -```shell -taosx run \ - -f 'tmq://root:taosdata@localhost:6030/db1?group.id=taosx1&client.id=taosx&timeout=never&offset=2:10' \ - -t 'taos://root:taosdata@another.com:6030/db2' -``` - - - -#### TDengine 2.6 -> TDengine 3.0 - -将 2.6 版本 TDengine 集群中的数据迁移到 3.0 版本 TDengine 集群。 - -#### 命令行参数 - -| 参数名称 | 说明 | 默认值 | -|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------| -| libraryPath | 在 option 模式下指定 taos 库路径 | 无 | -| configDir | 指定 taos.cfg 配置文件路径 | 无 | -| mode | 数据源参数。 history 表示历史数据。 realtime 表示实时同步。 all 表示以上两种。 | history | -| restro | 数据源参数。 在同步实时数据前回溯指定时间长度的数据进行同步。 restro=10m 表示回溯最近 10 分钟的数据以后,启动实时同步。 | 无 | -| interval | 数据源参数。 轮询间隔 ,mode=realtime&interval=5s 指定轮询间隔为 5s | 无 | -| excursion | 数据源参数。 允许一段时间的乱序数据 | 500ms | -| stables | 数据源参数。 仅同步指定超级表的数据,多个超级表名用英文逗号 ,分隔 | 无 | -| tables | 数据源参数。 仅同步指定子表的数据,表名格式为 {stable}.{table} 或 {table},多个表名用英文逗号 , 分隔,支持 @filepath 的方式输入一个文件,每行视为一个表名,如 tables=@./tables.txt 表示从 ./tables.txt 中按行读取每个表名,空行将被忽略。 | 无 | -| select-from-stable | 数据源参数。 从超级表获取 select {columns} from stable where tbname in ({tbnames}) ,这种情况 tables 使用 {stable}.{table} 数据格式,如 meters.d0 表示 meters 超级表下面的 d0 子表。 | 默认使用 select \* from table 获取数据 | -| assert | 目标源参数。 taos:///db1?assert 将检测数据库是否存在,如不存在,将自动创建目标数据库。 | 默认不自动创建库。 | -| force-stmt | 目标源参数。 当 TDengine 版本大于 3.0 时,仍然使用 STMT 方式写入。 | 默认为 raw block 写入方式 | -| batch-size | 目标源参数。 设置 STMT 写入模式下的最大批次插入条数。 | | -| interval | 目标源参数。 每批次写入后的休眠时间。 | 无 | -| max-sql-length | 目标源参数。 用于建表的 SQL 最大长度,单位为 bytes。 | 默认 800_000 字节。 | -| failes-to | 目标源参数。 添加此参数,值为文件路径,将写入错误的表及其错误原因写入该文件,正常执行其他表的同步任务。 | 默认写入错误立即退出。 | -| timeout-per-table | 目标源参数。 为子表或普通表同步任务添加超时。 | 无 | -| update-tags | 目标源参数。 检查子表存在与否,不存在时正常建表,存在时检查标签值是否一致,不一致则更新。 | 无 | - -#### 示例 - -1.使用原生连接同步数据 - -```shell -taosx run \ - -f 'taos://td1:6030/db1?libraryPath=./libtaos.so.2.6.0.30&mode=all' \ - -t 'taos://td2:6030/db2?libraryPath=./libtaos.so.3.0.1.8&assert \ - -v -``` - -2.使用 WebSocket 同步数据超级表 stable1 和 stable2 的数据 - -```shell -taosx run \ - -f 'taos+ws://:@td1:6041/db1?stables=stable1,stable2' \ - -t 'taos+wss://td2:6041/db2?assert&token= \ - -v -``` - -### 从 TDengine 备份数据文件到本地 - -示例: -```shell -taosx run -f 'tmq://root:taosdata@td1:6030/db1' -t 'local:/path_directory/' - -``` -以上示例执行的结果及参数说明: - -将集群 td1 中的数据库 db1 的所有数据,备份到 taosx 所在设备的 /path_directory 路径下。 - -数据源(-f 参数的 DSN)的 object 支持配置为 数据库级(dbname)、超级表级(dbname.stablename)、子表/普通表级(dbname.tablename),对应备份数据的级别数据库级、超级表级、子表/普通表级 - - -### 从本地数据文件恢复到 TDengine - -#### 示例 -```shell -taosx run -f 'local:/path_directory/' -t 'taos://root:taosdata@td2:6030/db1?assert' -``` - -以上示例执行的结果: - -将 taosx 所在设备 /path_directory 路径下已备份的数据文件,恢复到集群 td2 的数据库 db1 中,如果 db1 不存在,则自动建库。 - -目标源(-t 参数的 DSN)中的 object 支持配置为数据库(dbname)、超级表(dbname.stablename)、子表/普通表(dbname.tablename),对应备份数据的级别数据库级、超级表级、子表/普通表级,前提是备份的数据文件也是对应的数据库级、超级表级、子表/普通表级数据。 - - -#### 常见错误排查 - -(1) 如果使用原生连接,任务启动失败并报以下错误: - -```text -Error: tmq to td task exec error - -Caused by: - [0x000B] Unable to establish connection -``` -产生原因是与数据源的端口链接异常,需检查数据源 FQDN 是否联通及端口 6030 是否可正常访问。 - -(2) 如果使用 WebSocket 连接,任务启动失败并报以下错误: - -```text -Error: tmq to td task exec error - -Caused by: - 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution - 1: IO error: failed to lookup address information: Temporary failure in name resolution - 2: failed to lookup address information: Temporary failure in name resolution -``` - -使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: - -- "Temporary failure in name resolution": DNS 解析错误,检查 IP 或 FQDN 是否能够正常访问。 -- "IO error: Connection refused (os error 111)": 端口访问失败,检查端口是否配置正确或是否已开启和可访问。 -- "IO error: received corrupt message": 消息解析失败,可能是使用了 wss 方式启用了 SSL,但源端口不支持。 -- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 -- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 - -(3) 如果任务启动失败并报以下错误: - -```text -Error: tmq to td task exec error - -Caused by: - [0x038C] WAL retention period is zero -``` - -是由于源端数据库 WAL 配置错误,无法订阅。 - -解决方式: -修改数据 WAL 配置: - -```sql -alter database test wal_retention_period 3600; -``` - -### 从 OPC-UA 同步数据到 TDengine - -#### 配置参数 - -| 参数名称 | 类型 | 描述 | -|-----------------|--------|-----------------------------------------------------------------------------| -| interval | int | 采集间隔(单位:秒),默认为1秒 | -| concurrent | int | 采集器并发数,默认为1 | -| batch_size | int | 采集器上报的批次点位数,默认为100 | -| batch_timeout | int | 采集器上报的超时时间(单位:秒),默认为20秒 | -| connect_timeout | int | 连接的超时时间(单位:秒),默认为10秒 | -| request_timeout | int | 请求的超时时间(单位:秒),默认为10秒 | -| security_policy | string | OPC-UA连接安全策略(可配置为None/Basic128Rsa15/Basic256/Basic256Sha256) | -| security_mode | string | OPC-UA连接模式(可配置为None/Sign/SignAndEncrypt) | -| certificate | string | cert.pem的路径。当安全模式或策略不是”无”时生效 | -| private_key | string | key.pem的路径。 当安全模式或策略不是”无”时生效 | -| csv_config_file | string | 包含 OPC UA 的点位配置和表配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效| -| ua.nodes | string | OPC-UA 测点的 NodeID。和 opc_table_config 配置结合使用,两者需要同时配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效。配置格式为 ::,code 用于建子表。| -| opc_table_config | string | OPCUA 单列模式表配置。需要与 ua.nodes 配合使用。| -| debug | bool | 启用 OPC 连接器的 debug 日志。默认为 false。| -| enable | bool | 原始数据存储。默认为 false| -| path | string | 原始数据存储路径。enable 为 true 时必须配置。| -| keep | int | 原始数据保存天数。enable 为 true 时必须配置。| - -补充: -1. opc_table_config 说明: - -```json -{ - "stable_prefix": "meters", // 超级表前缀 - "column_configs": - [ - { - "column_name": "received_time", // 存储接收时间 - "column_type": "timestamp", - "column_alias": "ts", // 接收时间建表列用列名为 ts - "is_primary_key": true // 接收时间时间戳作为主键 - }, - { - "column_name": "original_time", - "column_type": "timestamp", - "column_alias": "ts_2", - "is_primary_key": false - }, - { - "column_name": "value", // 数据列 - "column_alias": "valueaa", // 数据列别名 - "is_primary_key": false - }, - { - "column_name": "quality", // 质量位列 - "column_type": "int", - "column_alias": "quality11", // 质量位列别名 - "is_primary_key": false - } - ] -} -``` - -#### 示例 - -1. 使用 ua.nodes 和 opc_table_config 的配置示例: -采集 nodeid 为 ns=2;i=2 和 ns=2;i=3 的点位,将其写入到集群 tdengine 的 opc 库中超级表前缀为 meters,如果 ns=2;i=2 的点位类型为 float 则会创建 meters_float 的超级表,超级表使用 opc 接收的数据作为时间戳索引列,并且保留原始时间戳列,原始时间戳列名为 ts_2,数据列存储为 valueaa,同时存储质量数据到 quality11 列。 - -```shell -taosx run \ - -f "opcua://uauser:uapass@localhost:4840?ua.nodes=ns=2;i=2::DSF1312,ns=2;i=3::DSF1313&opc_table_config={\"stable_prefix\": \"meters\", \"column_configs\": [{\"column_name\": \"received_time\", \"column_type\": \"timestamp\", \"column_alias\": \"ts\", \"is_primary_key\": true }, {\"column_name\": \"original_time\", \"column_type\": \"timestamp\", \"column_alias\": \"ts_2\", \"is_primary_key\": false }, {\"column_name\": \"value\", \"column_alias\": \"valueaa\", \"is_primary_key\": false }, {\"column_name\": \"quality\", \"column_type\": \"int\", \"column_alias\": \"quality11\", \"is_primary_key\": false } ] }" \ - -t "taos://tdengine:6030/opc" - - - -``` - -2. 使用 CSV 配置文件 - -```shell -taosx run -f "opcua://?csv_config_file=@" -t "taos+ws://tdengine:6041/opc" -``` - -#### CSV 配置文件模板 - - -### 从 OPC-DA 同步数据到 TDengine (Windows) - -#### 配置参数 - -| 参数名称 | 类型 | 描述 | -|-----------------|--------|-----------------------------------------------------------------------------| -| interval | int | 采集间隔(单位:秒),默认为1秒 | -| concurrent | int | 采集器并发数,默认为1 | -| batch_size | int | 采集器上报的批次点位数,默认为100 | -| batch_timeout | int | 采集器上报的超时时间(单位:秒),默认为20秒 | -| connect_timeout | int | 连接的超时时间(单位:秒),默认为10秒 | -| request_timeout | int | 请求的超时时间(单位:秒),默认为10秒 | -| csv_config_file | string | 包含 OPC UA 的点位配置和表配置。与 ua.nodes 两者之间需要配置一个。CSV 的配置模版参考:OPC 需求汇总及完成现状 | -| da.tags | string | OPC-UA 测点的 NodeID。和 opc_table_config 配置结合使用,两者需要同时配置。与配置 csv_config_file 配置互斥,csv_config_file 优先生效。| -| opc_table_config | string | OPCUA 单列模式表配置。需要与 da.tags 配合使用| -| debug | bool | 启用 OPC 连接器的 debug 日志。默认为 false。| -| enable | bool | 原始数据存储。默认为 false| -| path | string | 原始数据存储路径。enable 为 true 时必须配置。| -| keep | int | 原始数据保存天数。enable 为 true 时必须配置。| - -#### 应用示例 - -```shell -taosx run \ - -f "opc+da://Matrikon.OPC.Simulation.1?nodes=localhost&da.tags=Random.Real8::tb3::c1::int" - -t "taos://tdengine:6030/opc" -``` - -以上示例的执行结果: - -采集 Matrikon.OPC.Simulation.1 服务器上 OPC DA 中 da.tags 为 Random.Real8的数据,数据类型为int,对应在 TDengine 中以表名为 tb3 ,列名为c1,列类型为 int 型 schema 来创建表(如果对应表已存在,则直接采集数据并写入)。 - -#### 常见错误排查 - -(1) 如果使用原生连接,任务启动失败并打印如下错误: -```text -Error: tmq to td task exec error - -Caused by: - 0: Error occurred while creating a new object: [0x000B] Unable to establish connection -``` -解决方式: - -检查目标端 TDengine 的 FQDN 是否联通及端口 6030 是否可正常访问。 - -(2) 如果使用 WebSocket 连接任务启动失败并打印如下错误:: - -```text -Error: tmq to td task exec error - -Caused by: - 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution - 1: IO error: failed to lookup address information: Temporary failure in name resolution - 2: failed to lookup address information: Temporary failure in name resolution -``` - -使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: - -- "Temporary failure in name resolution": DNS 解析错误,检查目标端 TDengine的 IP 或 FQDN 是否能够正常访问。 -- "IO error: Connection refused (os error 111)": 端口访问失败,检查目标端口是否配置正确或是否已开启和可访问(通常为6041端口)。 -- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 -- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 - -### 从 PI 同步数据到 TDengine (Windows) - -#### PI DSN 配置 - -PI DSN 的完整配置如下: - -```shell -pi://[:@]PIServerName/AFDatabaseName?[TemplateForPIPoint][&TemplateForAFElement][&PointList][&][&][&UpdateInterval] -``` - -在 taosX CLI 运行时支持的参数如下,其中 TemplateForPIPoint、TemplateForAFElement、PointList 三个参数至少配置一项: -- PISystemName:选填,连接配置 PI 系统服务名,默认值与 PIServerName 一致 -- MaxWaitLen:选填,数据最大缓冲条数,默认值为 1000 ,有效取值范围为 [1,10000] -- UpdateInterval:选填,PI System 取数据频率,默认值为 10000(毫秒:ms),有效取值范围为 [10,600000] -- TemplateForPIPoint:选填,使用 PI Point 模式将模板按照 element 的每个 Arrtribution 作为子表导入到 TDengine -- TemplateForAFElement:选填,使用 AF Point 模式将模板按照 element 的 Attribution 集合作为一个子表导入到 TDengine -- PointList:选填,使用 PointList 模式将指定csv文件中描述的点位信息在 PI 数据库中的数据导入到 TDengine - - -#### 应用示例 - -将位于服务器 WIN-2OA23UM12TN 中的 PI 数据库 Met1,模板 template1、template2配置为 TemplateForPIPoint模式,模板 template3、template4 配置为 TemplateForAFElement 模式,服务器 /home/ 路径下的点位文件 points.csv 配置为 PointList 模式,连接配置 PI 系统服务名为 PI,数据最大缓冲条数为1000,PI System 取数据频率为10000ms,将该库中的数据同步到 服务器 tdengine 的 pi 库中。完整的示例如下: - -```shell -taosx run \ - -f "pi://WIN-2OA23UM12TN/Met1?TemplateForPIPoint=template1,template2&TemplateForAFElement=template3,template4" \ - -t "taos://tdengine:6030/pi" -``` - - -#### 常见错误排查 - -(1) 如果使用原生连接,任务启动失败并打印如下错误: -```text -Error: tmq to td task exec error - -Caused by: - 0: Error occurred while creating a new object: [0x000B] Unable to establish connection -``` -解决方式: - -检查目标端 TDengine 的 FQDN 是否联通及端口 6030 是否可正常访问。 - -(2) 如果使用 WebSocket 连接任务启动失败并打印如下错误:: - -```text -Error: tmq to td task exec error - -Caused by: - 0: WebSocket internal error: IO error: failed to lookup address information: Temporary failure in name resolution - 1: IO error: failed to lookup address information: Temporary failure in name resolution - 2: failed to lookup address information: Temporary failure in name resolution -``` - -使用 WebSocket 连接时可能遇到多种错误类型,错误信息可以在 ”Caused by“ 后查看,以下是几种可能的错误: - -- "Temporary failure in name resolution": DNS 解析错误,检查目标端 TDengine的 IP 或 FQDN 是否能够正常访问。 -- "IO error: Connection refused (os error 111)": 端口访问失败,检查目标端口是否配置正确或是否已开启和可访问(通常为6041端口)。 -- "HTTP error: *": 可能连接到错误的 taosAdapter 端口或 LSB/Nginx/Proxy 配置错误。 -- "WebSocket protocol error: Handshake not finished": WebSocket 连接错误,通常是因为配置的端口不正确。 - - -### 从 InfluxDB 同步数据到 TDengine - -#### 命令行参数 - -将数据从 InfluxDB 同步至 TDengine 的命令,如下所示: - -```bash -taosx run --from "" --to "" -``` - -其中,InfluxDB DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: -- version: 必填,InfluxDB 的版本,主要用于区分 1.x 与 2.x 两个版本,二者使用不同的认证参数; -- version = 1.x - - username: 必填,InfluxDB 用户,该用户至少在该组织中拥有读取权限; - - password: 必填,InfluxDB 用户的登陆密码; -- version = 2.x - - orgId: 必填,InfluxDB 中的 Orgnization ID; - - token: 必填,InfluxDB 中生成的 API token, 这个 token 至少要拥有以上 Bucket 的 Read 权限; -- bucket: 必填,InfluxDB 中的 Bucket 名称,一次只能同步一个 Bucket; -- measurements: 非必填,可以指定需要同步的多个 Measurements(英文逗号分割),未指定则同步全部; -- beginTime: 必填,格式为:YYYY-MM-DD'T'HH:MM:SS'Z', 时区采用 UTC 时区,例如:2023-06-01T00:00:00+0800, 即北京时间2023-06-01 00:00:00(东八区时间); -- endTime: 非必填,可以不指定该字段或值为空,格式与beginTime相同;如果未指定,提交任务后,将持续进行数据同步; -- readWindow: 非必填,可以不指定该字段或值为空,可选项为D、H、M(天、时、分);如果未指定,则默认按 M 拆分读取窗口。 - -#### 示例 - -将位于 192.168.1.10 的 InfluxDB 中, Bucket 名称为 test_bucket, 从UTC时间2023年06月01日00时00分00秒开始的数据,通过运行在 192.168.1.20 上的 taoskeeper, 同步至 TDengine 的 test_db 数据库中,完整的命令如下所示: -```bash -# version = 1.x -taosx run \ - --from "influxdb+http://192.168.1.10:8086/?version=1.7&username=test&password=123456&bucket=test_bucket&measurements=&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ - --to "taos+http://192.168.1.20:6041/test_db" \ - -vv - -# version = 2.x -taosx run \ - --from "influxdb+http://192.168.1.10:8086/?version=2.7&orgId=3233855dc7e37d8d&token=OZ2sB6Ie6qcKcYAmcHnL-i3STfLVg_IRPQjPIzjsAQ4aUxCWzYhDesNape1tp8IsX9AH0ld41C-clTgo08CGYA==&bucket=test_bucket&measurements=&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ - --to "taos+http://192.168.1.20:6041/test_db" \ - -vv -``` - -在这个命令中,未指定endTime, 所以任务会长期运行,持续同步最新的数据。 - - -### 从 OpenTSDB 同步数据到 TDengine - -#### 命令行参数 - -将数据从 OpenTSDB 同步至 TDengine 的命令,如下所示: - -```bash -taosx run --from "" --to "" -``` - -其中,OpenTSDB DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: -- metrics: 非必填,可以指定需要同步的多个 Metrics(英文逗号分割),未指定则同步全部; -- beginTime: 必填,格式为:YYYY-MM-DD'T'HH:MM:SS'Z', 时区采用 UTC 时区,例如:2023-06-01T00:00:00+0800, 即北京时间2023-06-01 00:00:00(东八区时间); -- endTime: 非必填,可以不指定该字段或值为空,格式与beginTime相同;如果未指定,提交任务后,将持续进行数据同步; -- readWindow: 非必填,可以不指定该字段或值为空,可选项为D、H、M(天、时、分);如果未指定,则默认按分钟拆分读取窗口。 - -#### 示例 - -将位于 192.168.1.10 的 OpenTSDB 中, Metric 名称为 test_metric1 与 test_metric2 的两个数据源, 从UTC时间2023年06月01日00时00分00秒开始的数据,通过运行在 192.168.1.20 上的 taoskeeper, 同步至 TDengine 的 test_db 数据库中,完整的命令如下所示: - -```bash -taosx run \ - --from "opentsdb+http://192.168.1.10:4242/?metrics=test_metric1,test_metric2&beginTime=2023-06-01T00:00:00+0800&readWindow=M" \ - --to "taos+http://192.168.1.20:6041/test_db" \ - -vv -``` - -在这个命令中,未指定endTime, 所以任务会长期运行,持续同步最新的数据。 - - -### 从 MQTT 同步数据到 TDengine - -目前,MQTT 连接器仅支持从 MQTT 服务端消费 JSON 格式的消息,并将其同步至 TDengine. 命令如下所示: - -```bash -taosx run --from "" --to "" --parser "@" -``` - -其中: -- `--from` 用于指定 MQTT 数据源的 DSN -- `--to` 用于指定 TDengine 的 DSN -- `--parser` 用于指定一个 JSON 格式的配置文件,该文件决定了如何解析 JSON 格式的 MQTT 消息,以及写入 TDengine 时的超级表名、子表名、字段名称和类型,以及标签名称和类型等。 - -#### MQTT DSN 配置 - -MQTT DSN 符合 DSN 的通用规则,这里仅对其特有的参数进行说明: -- topics: 必填,用于配置监听的 MQTT 主题名称和连接器支持的最大 QoS, 采用 `::` 的形式;支持配置多个主题,使用逗号分隔;配置主题时,还可以使用 MQTT 协议的支持的通配符#和+; -- version: 非必填,用于配置 MQTT 协议的版本,支持的版本包括:3.1/3.1.1/5.0, 默认值为3.1; -- clean_session: 非必填,用于配置连接器作为 MQTT 客户端连接至 MQTT 服务端时,服务端是否保存该会话信息,其默认值为 true, 即不保存会话信息; -- client_id: 必填,用于配置连接器作为 MQTT 客户端连接至 MQTT 服务端时的客户端 id; -- keep_alive: 非必填,用于配置连接器作为 MQTT 客户端,向 MQTT 服务端发出 PINGREG 消息后的等待时间,如果连接器在该时间内,未收到来自 MQTT 服务端的 PINGREQ, 连接器则主动断开连接;该配置的单位为秒,默认值为 60; -- ca: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的 CA 证书,其值为在证书文件的绝对路径前添加@, 例如:@/home/admin/certs/ca.crt; -- cert: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的客户端证书,其值为在证书文件的绝对路径前添加@, 例如:@/home/admin/certs/client.crt; -- cert_key: 非必填,用于指定连接器与 MQTT 服务端建立 SSL/TLS 连接时,使用的客户端私钥,其值为在私钥文件的绝对路径前添加@, 例如:@/home/admin/certs/client.key; -- log_level: 非必填,用于配置连接器的日志级别,连接器支持 error/warn/info/debug/trace 5种日志级别,默认值为 info. - -一个完整的 MQTT DSN 示例如下: -```bash -mqtt://:@:8883?topics=testtopic/1::2&version=3.1&clean_session=true&log_level=info&client_id=taosdata_1234&keep_alive=60&ca=@/home/admin/certs/ca.crt&cert=@/home/admin/certs/client.crt&cert_key=@/home/admin/certs/client.key -``` - -#### MQTT 连接器的解释器配置 - -连接器的解释器配置文件,即`--parser`配置项的参数,它的值为一个 JSON 文件,其配置可分为`parse`和`model`两部分,模板如下所示: - -```json -{ - "parse": { - "payload": { - "json": [ - { - "name": "ts", - "alias": "ts", - "cast": "TIMESTAMP" - }, - ... - ] - } - }, - "model": { - "using": "", - "name": "{alias}", - "columns": [ ... ], - "tags": [ ... ] - } -} -``` - -各字段的说明如下: -- parse 部分目前仅支持 json 一种 payload, json 字段的值是一个由 JSON Object 构成的 JSON Array: - - 每个 JSON Ojbect 包括 name, alias, cast 三个字段; - - name 字段用于指定如何从 MQTT 消息中提取字段,如果 MQTT 消息是一个简单的 JSON Object, 这里可以直接设置其字段名;如果 MQTT 消息是一个复杂的 JSON Object, 这里可以使用 JSON Path 提取字段,例如:`$.data.city`; - - alias 字段用于命名 MQTT 消息中的字段同步至 TDengine 后使用的名称; - - cast 字段用于指定 MQTT 消息中的字段同步至 TDengine 后使用的类型。 -- model 部分用于设置 TDengine 超级表、子表、列和标签等信息: - - using 字段用于指定超级表名称; - - name 字段用于指定子表名称,它的值可以分为前缀和变量两部分,变量为 parse 部分设置的 alias 的值,需要使用{}, 例如:d{id}; - - columns 字段用于设置 MQTT 消息中的哪些字段作为 TDengine 超级表中的列,取值为 parse 部分设置的 alias 的值;需要注意的是,这里的顺序会决定 TDengine 超级表中列的顺序,因此第一列必须为 TIMESTAMP 类型; - - tags 字段用于设置 MQTT 消息中的哪些字段作为 TDengine 超级表中的标签,取值为 parse 部分设置的 alias 的值。 - -#### 举例说明 - -在 192.168.1.10 的 1883 端口运行着一个 MQTT broker, 用户名、口令分别为admin, 123456; 现欲将其中的消息,通过运行在 192.168.1.20 的 taosadapter 同步至 TDengine 的 test 数据库中。MQTT 消息格式为: - -```json -{ - "id": 1, - "current": 10.77, - "voltage": 222, - "phase": 0.77, - "groupid": 7, - "location": "California.SanDiego" -} -``` - -MQTT 消息同步至 TDengine 时, 如果采用 meters 作为超级表名,前缀“d”拼接id字段的值作为子表名,ts, id, current, voltage, phase作为超级表的列,groupid, location作为超级表的标签,其解释器的配置如下: -```json -{ - "parse": { - "payload": { - "json": [ - { - "name": "ts", - "alias": "ts", - "cast": "TIMESTAMP" - }, - { - "name": "id", - "alias": "id", - "cast": "INT" - }, - { - "name": "voltage", - "alias": "voltage", - "cast": "INT" - }, - { - "name": "phase", - "alias": "phase", - "cast": "FLOAT" - }, - { - "name": "current", - "alias": "current", - "cast": "FLOAT" - }, - { - "name": "groupid", - "alias": "groupid", - "cast": "INT" - }, - { - "name": "location", - "alias": "location", - "cast": "VARCHAR(20)" - } - ] - } - }, - "model": { - "name": "d{id}", - "using": "meters", - "columns": [ - "ts", - "id", - "current", - "voltage", - "phase" - ], - "tags": [ - "groupid", - "location" - ] - } -} -``` - -如果以上parser配置位于`/home/admin/parser.json`中,那么完整的命令如下所示: - -```bash -taosx run \ - -f "mqtt://admin:123456@192.168.1.10:1883?topics=testtopic/1::2&version=3.1&clean_session=true&log_level=info&client_id=1234&keep_alive=60" \ - -t "taos+ws://192.168.1.20:6041/test" - --parser "@/home/admin/parser.json" - --verbose -``` - -### 从 Kafka 同步数据到 TDengine - -#### 命令行参数 - -taosx 支持从 Kafka 消费数据,写入 TDengine。命令如下所示: -```sehll -taosx run -f "" -t "" -``` -或 -```shell -taosx run -f "" -t "" --parser "@" -``` -其中: -- -f或--from: Kafka 的 DSN -- -t或--to :TDengine 的 DSN -- --parser :一个 JSON 格式的配置文件,或JSON格式的字符串。 - -#### Kafka DSN 配置的配置 - -| 参数 | 说明 | 必填? | 缺省值 | 适用于 | 示例 | -|-----|---------------|----------|---------|---------|----------| -| group| 消费者的group。允许组为空字符串,在这种情况下,生成的消费者将是无组的 | 否 | "" | 源端 | | -| topics | 指定要使用的主题。指定主题的所有可用分区都将被使用,除非在指定 topic_partitions 时被覆盖。| 该参数或topic_partitions必须至少指定一个,以便将主题分配给消费者。| None | 源端 | topics=tp1,tp2 | -| topic_partitions | 显式指定要使用的主题分区。只使用已标识主题的指定分区。 | 该参数或topics必须至少指定一个,以便将主题分配给消费者。 | None | 源端 | topic_partitions=tp1:0..2,tp2:1 | -| fallback_offset | topic偏移量时可能的值:- Earliest:接收最早的可用偏移量; - Latest:接收最近的偏移量; - ByTime(i64):用于请求在某一特定时间(ms)之前的所有消息;Unix时间戳(毫秒) | 否 | Earliest | 源端 | fallback_offset=Earliest | -| offset_storage | 定义在获取或提交组偏移量时,要使用的可用存储:- Zookeeper:基于Zookeeper的存储(从kafka 0.8.1开始可用);- Kafka:基于Kafka的存储(从Kafka 0.8.2开始可用)。这是组存储其偏移量的首选方法。 | 否 | Kafka | 源端 | offset_storage=Kafka | -| timeout | 从kafka订阅数据时,如果超时后没有获取到有效数据,退出 | 否 | 500 | 源端 | timeout=never | -| use_ssl | 是否使用SSL认证 | 否 | | 源端 | | -| cert | SSL证书的文件路径 | 否 | | | 源端 | | -| cert_key | SSL证书key的文件路径 | 否 | | 源端 || - - -#### 示例一 - -从192.168.1.92服务器的Kafka实例中消费数据,同步到192.168.1.92上的TDengine,不使用parser。 - -1. kafka - -```shell -#!/bin/bash -KAFKA_HOME=/root/zyyang/kafka_2.13-3.1.0 -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --delete -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --delete -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --partitions 5 --replication-factor 1 --create -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --partitions 1 --replication-factor 1 --create -$KAFKA_HOME/bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 << EOF -{"id": 1, "message": "hello"} -{"id": 2, "message": "hello"} -{"id": 3, "message": "hello"} -{"id": 4, "message": "hello"} -{"id": 5, "message": "hello"} -EOF -$KAFKA_HOME/bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 << EOF -{"id": 1, "message": "aaa"} -{"id": 2, "message": "aaa"} -{"id": 3, "message": "aaa"} -{"id": 4, "message": "aaa"} -{"id": 5, "message": "aaa"} -EOF -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp1 --describe -$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic tp2 --describe -``` - -2. TDengine - -```shell -drop database if exists kafka_to_taos; -create database if not exists kafka_to_taos precision 'ms'; -use kafka_to_taos; -``` - -3. taosx - -```shell -taosx run -f "kafka://192.168.1.92:9092/?topics=tp1,tp2&timeout=5000" -t "taos://192.168.1.92:6030/kafka_to_taos" --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"key\":{\"as\":\"binary\",\"alias\":\"k\"},\"value\":{\"as\":\"binary\",\"alias\":\"v\"}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"k\",\"v\"]}]}" -``` - -#### 示例2 - -从192.168.1.92服务器的Kafka实例中消费数据,同步到192.168.1.92上的TDengine,使用parser解析value中的JSON数据。 - -1. kafka,同“示例1” -2. TDengine,同“示例1” -3. Taosx - -```shell -taosx run -f "kafka://192.168.1.92:9092/?topics=tp1,tp2&timeout=5000" -t "taos://192.168.0.201:6030/kafka_to_taos" --parser "{\"parse\":{\"ts\":{\"as\":\"timestamp(ms)\"},\"topic\":{\"as\":\"varchar\",\"alias\":\"t\"},\"partition\":{\"as\":\"int\",\"alias\":\"p\"},\"offset\":{\"as\":\"bigint\",\"alias\":\"o\"},\"value\":{\"json\":[\"id::int\",\"message::binary\"]}},\"model\":[{\"name\":\"t_{t}\",\"using\":\"kafka_data\",\"tags\":[\"t\",\"p\"],\"columns\":[\"ts\",\"o\",\"id\",\"message\"]}]}" -``` - -## 服务模式 - -在服务模式下, 一共需要三个组件协同完成数据迁移。 taosX,Agent 以及 taosExplorer 均已服务态运行,各种操作通过 taosExplorer 的图形界面进行。taos-Explorer 组件除了数据迁移之外,还提供了使用 TDengine 的图形化界面。 - -### 部署 taosX - -#### 配置 - -taosX 仅支持通过命令行参数进行配置。服务模式下,taosX 支持的命令行参数可以通过以下方式查看: - -``` -taosx serve --help -``` - -建议通过 Systemd 的方式,启动 taosX 的服务模式,其 Systemd 的配置文件位于:`/etc/systemd/system/taosx.service`. 如需修改 taosX 的启动参数,可以编辑该文件中的以下行: - -``` -ExecStart=/usr/bin/taosx serve -v -``` - -修改后,需执行以下命令重启 taosX 服务,使配置生效: - -``` -systemctl daemon-reload -systemctl restart taosx -``` - -#### 启动 - -Linux 系统上以 Systemd 的方式启动 taosX 的命令如下: - -```shell -systemctl start taosx -``` - -Windows 系统上,请在 "Services" 系统管理工具中找到 "taosX" 服务,然后点击 "启动这个服务"。 - -#### 问题排查 - -1. 如何修改 taosX 的日志级别? - -taosX 的日志级别是通过命令行参数指定的,默认的日志级别为 Info, 具体参数如下: -- INFO: `taosx serve -v` -- DEBUG: `taosx serve -vv` -- TRACE: `taosx serve -vvv` - -Systemd 方式启动时,如何修改命令行参数,请参考“配置”章节。 - -2. 如何查看 taosX 的日志? - -以 Systemd 方式启动时,可通过 journalctl 命令查看日志。以滚动方式,实时查看最新日志的命令如下: - -``` -journalctl -u taosx -f -``` - -### 部署 Agent - -#### 配置 - -Agent 默认的配置文件位于`/etc/taos/agent.toml`, 包含以下配置项: -- endpoint: 必填,taosX 的 GRPC endpoint -- token: 必填,在 taosExplorer 上创建 agent 时,产生的token -- debug_level: 非必填,默认为 info, 还支持 debug, trace 等级别 - -如下所示: - -```TOML -endpoint = "grpc://:6055" -token = "" -log_level = "debug" -``` - -日志保存时间设置 -日志保存的天数可以通过环境变量进行设置 TAOSX_LOGS_KEEP_DAYS, 默认为 30 天。 - -```shell -export TAOSX_LOGS_KEEP_DAYS=7 -``` - -#### 启动 - -Linux 系统上 Agent 可以通过 Systemd 命令启动: - -``` -systemctl start taosx-agent -``` - -Windows 系统上通过系统管理工具 "Services" 找到 taosx-agent 服务,然后启动它。 - -#### 问题排查 - -可以通过 journalctl 查看 Agent 的日志 - -``` -journalctl -u taosx-agent -f -``` - -### 部署 taosExplorer - - -### 数据同步功能 - -请参考 taosExplorer \ No newline at end of file diff --git a/docs/zh/18-data-transfer/02-explorer.md b/docs/zh/18-data-transfer/02-explorer.md deleted file mode 100644 index fd374cc734..0000000000 --- a/docs/zh/18-data-transfer/02-explorer.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: 基于可视化界面的数据接入和数据迁移 ---- - -本节讲述使用 taos Explorer 的可视化界面进行数据迁移,使用此功能需要依赖 taosd, taosAdapter, taosX, taos-explorer 等几个服务组件。关于 taosd 和 taosAdapter 的部署请参考 [系统部署](../../deployment/deploy),[taosX](../taosX),以及 [部署 taos-explorer](../../operation/web) - -## 功能入口 - -点击 explorer 左侧功能列表中的 "数据写入",可以配置不同类型的数据源,包括 TDengine Subscription, PI, OPC-UA, OPC-DA, InfluxDB, MQTT,Kafka, CSV 等,将它们的数据写入到当前正在被管理的 TDengine 集群中。 - -## TDengine 订阅 - -进入TDengine订阅任务配置页面: -1. 在连接协议栏中,配置连接协议,默认为原生连接,可配置为WS、WSS; -2. 在服务器栏中配置服务器的 IP 或域名; -3. 在端口栏中配置连接的端口号,默认值为6030; -4. 在主题栏中,配置可以配置订阅一个或多个数据库,或超级表或普通表,也可以是一个已创建的 Topic; -5. 在认证栏,可以配置访问 TDengine 的用户名密码,用户名默认值为 root,密码默认值为 taosdata;如果数据源为云服务实例,则可以选择令牌认证方式并配置实例 token; -6. 在订阅初始位置栏,可配置从最早数据(earliest)或最晚(latest)数据开始订阅,默认为 earliest; -7. 在超时栏配置超时时间,可配置为 never: 表示无超时时间,持续进行订阅,也可指定超时时间:5s, 1m 等,支持单位 ms(毫秒),s(秒),m(分钟),h(小时),d(天),M(月),y(年)。 -8. 在目标数据库栏中,选择本地 TDengine 的库作为目标库,点击 submit,即可启动一个 TDengine 订阅任务。 - -## Pi - -1. 在 PI 数据接入页面,设置 PI 服务器的名称、AF 数据库名称。 -2. 在监测点集栏,可以配置选择 Point 模式监测点集合、Point 模式监测的 AF 模板、AF 模式监测的 AF 模板。 -3. 在 PI 系统设置栏,可以配置 PI 系统名,默认为 PI 服务器名。 -4. 在 Data Queue 栏,可以配置 PI 连接器运行参数:MaxWaitLen(数据最大缓冲条数),默认值为 1000 ,有效取值范围为 [1,10000];UpdateInterval(PI System 取数据频率),默认值为 10000(毫秒:ms),有效取值范围为 [10,600000];重启补偿时间(Max Backfill Range,单位:天),每次重启服务时向前补偿该天数的数据,默认为1天。 -5. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit ,即可启动一个 PI 数据接入任务。 - -## OPC-UA - -1. 在 OPC-UA页面,配置 OPC-server 的地址,输入格式为 127.0.0.1:6666/OPCUA/ServerPath。 -2. 在认证栏,选择访问方式。可以选择匿名访问、用户名密码访问、证书访问。使用证书访问时,需配置证书文件信息、私钥文件信息、OPC-UA 安全协议和 OPC-UA 安全策略 -3. 在 Data Sets 栏,配置点位信息。(可通过“选择”按钮选择正则表达式过滤点位,每次最多能过滤出10条点位);点位配置有两种方式:1.手动输入点位信息 2.上传csv文件配置点位信息 -4. 在连接配置栏,配置连接超时间隔和采集超时间隔(单位:秒),默认值为10秒。 -5. 在采集配置栏,配置采集间隔(单位:秒)、点位数量、采集模式。采集模式可选择observe(轮询模式)和subscribe(订阅模式),默认值为observe。 -6. 在库表配置栏,配置目标 TDengine 中存储数据的超级表、子表结构信息。 -7. 在其他配置栏,配置并行度、单次采集上报批次(默认值100)、上报超时时间(单位:秒,默认值10)、是否开启debug级别日志。 -8. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit,即可启动一个 OPC-UA 数据接入任务。 - -## OPC-DA - -1. 在 OPC-DA页面,配置 OPC-server 的地址,输入格式为 127.0.0.1<,localhost>/Matrikon.OPC.Simulation.1。 -2. 在数据点栏,配置 OPC-DA 采集点信息。(可通过“选择”按钮选择正则表达式过滤点位,每次最多能过滤出10条点位)。点位配置有两种方式:1.手动输入点位信息 2.上传csv文件配置点位信息 -3. 在连接栏,配置连接超时时间(单位:秒,默认值为10秒)、采集超时时间(单位:秒,默认值为10秒)。 -4. 在库表配置栏,配置目标 TDengine 中存储数据的超级表、子表结构信息。 -5. 在其他配置栏,配置并行度、单次采集上报批次(默认值100)、上报超时时间(单位:秒,默认值10)、是否开启debug级别日志。 -6. 在目标数据库栏,选择需要写入的 TDengine 数据库,点击 submit,即可启动一个 OPC-DA 数据接入任务。 - -## InfluxDB - -进入 InfluxDB 数据源同步任务的编辑页面后: -1. 在服务器地址输入框, 输入 InfluxDB 服务器的地址,可以输入 IP 地址或域名,此项为必填字段; -2. 在端口输入框, 输入 InfluxDB 服务器端口,默认情况下,InfluxDB 监听8086端口的 HTTP 请求和8088端口的 HTTPS 请求,此项为必填字段; -3. 在组织 ID 输入框,输入将要同步的组织 ID,此项为必填字段; -4. 在令牌 Token 输入框,输入一个至少拥有读取这个组织 ID 下的指定 Bucket 权限的 Token, 此项为必填字段; -5. 在同步设置的起始时间项下,通过点选选择一个同步数据的起始时间,起始时间使用 UTC 时间, 此项为必填字段; -6. 在同步设置的结束时间项下,当不指定结束时间时,将持续进行最新数据的同步;当指定结束时间时,将只同步到这个结束时间为止; 结束时间使用 UTC 时间,此项为可选字段; -7. 在桶 Bucket 输入框,输入一个需要同步的 Bucket,目前只支持同步一个 Bucket 至 TDengine 数据库,此项为必填字段; -8. 在目标数据库下拉列表,选择一个将要写入的 TDengine 目标数据库 (注意:目前只支持同步到精度为纳秒的 TDengine 目标数据库),此项为必填字段; -9. 填写完成以上信息后,点击提交按钮,即可直接启动从 InfluxDB 到 TDengine 的数据同步。 - -## MQTT - -进入 MQTT 数据源同步任务的编辑页面后: -1. 在 MQTT 地址卡片,输入 MQTT 地址,必填字段,包括 IP 和 端口号,例如:192.168.1.10:1883; -2. 在认证卡片,输入 MQTT 连接器访问 MQTT 服务器时的用户名和密码,这两个字段为选填字段,如果未输入,即采用匿名认证的方式; -3. 在 SSL 证书卡片,可以选择是否打开 SSL/TLS 开关,如果打开此开关,MQTT 连接器和 MQTT 服务器之间的通信将采用 SSL/TLS 的方式进行加密;打开这个开关后,会出现 CA, 客户端证书和客户端私钥三个必填配置项,可以在这里输入证书和私钥文件的内容; -4. 在连接卡片,可以配置以下信息: - - MQTT 协议:支持3.1/3.1.1/5.0三个版本; - - Client ID: MQTT 连接器连接 MQTT 服务器时所使用的客户端 ID, 用于标识客户端的身份; - - Keep Alive: 用于配置 MQTT 连接器与 MQTT 服务器之间的Keep Alive时间,默认值为60秒; - - Clean Session: 用于配置 MQTT 连接器是否以Clean Session的方式连接至 MQTT 服务器,默认值为True; - - 订阅主题及 QoS 配置:这里用来配置监听的 MQTT 主题,以及该主题支持的最大QoS, 主题和 QoS 的配置之间用::分隔,多个主题之间用,分隔,主题的配置可以支持 MQTT 协议的通配符#和+; -5. 在其他卡片,可以配置 MQTT 连接器的日志级别,支持 error, warn, info, debug, trace 5个级别,默认值为 info; -6. MQTT Payload 解析卡片,用于配置如何解析 MQTT 消息: - - 配置表的第一行为 ts 字段,该字段为 TIMESTAMP 类型,它的值为 MQTT 连接器收到 MQTT 消息的时间; - - 配置表的第二行为 topic 字段,为该消息的主题名称,可以选择将该字段作为列或者标签同步至 TDengine; - - 配置表的第三行为 qos 字段,为该消息的 QoS 属性,可以选择将该字段作为列或者标签同步至 TDengine; - - 剩余的配置项皆为自定义字段,每个字段都需要配置:字段(来源),列(目标),列类型(目标)。字段(来源)是指该 MQTT 消息中的字段名称,当前仅支持 JSON 类型的 MQTT 消息同步,可以使用 JSON Path 语法从 MQTT 消息中提取字段,例如:$.data.id; 列(目标)是指同步至 TDengine 后的字段名称;列类型(目标)是指同步至 TDengine 后的字段类型,可以从下拉列表中选择;当且仅当以上3个配置都填写后,才能新增下一个字段; - - 如果 MQTT 消息中包含时间戳,可以选择新增一个自定义字段,将其作为同步至 TDengine 时的主键;需要注意的是,MQTT 消息中时间戳的仅支持 Unix Timestamp格式,且该字段的列类型(目标)的选择,需要与创建 TDengine 数据库时的配置一致; - - 子表命名规则:用于配置子表名称,采用“前缀+{列类型(目标)}”的格式,例如:d{id}; - - 超级表名:用于配置同步至 TDengine 时,采用的超级表名; -7. 在目标数据库卡片,可以选择同步至 TDengine 的数据库名称,支持直接从下拉列表中选择。 -8. 填写完成以上信息后,点击提交按钮,即可直接启动从 MQTT 到 TDengine 的数据同步。 - -## Kafka - -1. 在Kafka页面,配置Kafka选项,必填字段,包括:bootstrap_server,例如192.168.1.92:9092; -2. 如果使用SSL认证,在SSL认证卡中,选择cert和cert_key的文件路径; -3. 配置其他参数,topics、topic_partitions这2个参数至少填写一个,其他参数有默认值; -4. 如果消费的Kafka数据是JSON格式,可以配置parser卡片,对数据进行解析转换; -5. 在目标数据库卡片中,选择同步到TDengine的数据库名称,支持从下拉列表中选择; -6. 填写完以上信息后,点击提交按钮,即可启动从Kafka到TDengine的数据同步。 - -## CSV - -1. 在CSV页面,配置CSV选项,可设置忽略前N行,可输入具体的数字 -2. CSV的写入配置,设置批次写入量,默认是1000 -3. CSV文件解析,用于获取CSV对应的列信息: - - 上传CSV文件或者输入CSV文件的地址 - - 选择是否包包含Header - - 包含Header情况下直接执行下一步,查询出对应CSV的列信息,获取CSV的配置信息 - - 不包含Header情况,需要输入自定列信息,并以逗号分隔,然后下一步,获取CSV的配置信息 - - CSV的配置项,每个字段都需要配置:CSV列,DB列,列类型(目标),主键(整个配置只能有一个主键,且主键必须是TIMESTAMP类型),作为列,作为Tag。CSV列是指该 CSV文件中的列或者自定义的列;DB列是对应的数据表的列 - - 子表命名规则:用于配置子表名称,采用“前缀+{列类型(目标)}”的格式,例如:d{id}; - - 超级表名:用于配置同步至 TDengine 时,采用的超级表名; -4. 在目标数据库卡片,可以选择同步至 TDengine 的数据库名称,支持直接从下拉列表中选择。 -5. 填写完成以上信息后,点击提交按钮,即可直接启动从 CSV到 TDengine 的数据同步。 - - -## 备份和恢复 - -您可以将当前连接的 TDengine 集群中的数据备份至一个或多个本地文件中,稍后可以通过这些文件进行数据恢复。本章节将介绍数据备份和恢复的具体步骤。 - -### 备份数据到本地文件 - -1. 进入系统管理页面,点击【备份】进入数据备份页面,点击右上角【新增备份】。 -2. 在数据备份配置页面中可以配置三个参数: - - 备份周期:必填项,配置每次执行数据备份的时间间隔,可通过下拉框选择每天、每 7 天、每 30 天执行一次数据备份,配置后,会在对应的备份周期的0:00时启动一次数据备份任务; - - 数据库:必填项,配置需要备份的数据库名(数据库的 wal_retention_period 参数需大于0); - - 目录:必填项,配置将数据备份到 taosX 所在运行环境中指定的路径下,如 /root/data_backup; -3. 点击【确定】,可创建数据备份任务。 - -### 从本地文件恢复 - -1. 完成数据备份任务创建后,在页面中对应的数据备份任务右侧点击【数据恢复】,可将已经备份到指定路径下的数据恢复到当前 TDengine 中。 \ No newline at end of file diff --git a/docs/zh/18-data-transfer/index.md b/docs/zh/18-data-transfer/index.md deleted file mode 100644 index 749ad16308..0000000000 --- a/docs/zh/18-data-transfer/index.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: 数据集成 ---- \ No newline at end of file From c6607931939b3fb4994ed2b13c1ece74e5981bef Mon Sep 17 00:00:00 2001 From: Wade Zhang Date: Fri, 25 Aug 2023 23:34:39 +0800 Subject: [PATCH 08/15] doc: remove grant from website --- docs/zh/12-taos-sql/25-grant.md | 239 -------------------------------- 1 file changed, 239 deletions(-) delete mode 100644 docs/zh/12-taos-sql/25-grant.md diff --git a/docs/zh/12-taos-sql/25-grant.md b/docs/zh/12-taos-sql/25-grant.md deleted file mode 100644 index 42d740539f..0000000000 --- a/docs/zh/12-taos-sql/25-grant.md +++ /dev/null @@ -1,239 +0,0 @@ ---- -sidebar_label: 权限管理 -title: 权限管理 -description: 企业版中才具有的权限管理功能 ---- - -本节讲述如何在 TDengine 中进行权限管理的相关操作。权限管理是 TDengine 企业版的特有功能,欲试用 TDengine 企业版请联系 TDengine 销售或市场团队。 - -TDengine 中的权限管理分为用户管理、数据库授权管理以及消息订阅授权管理。 - -当 TDengine 安装并部署成功后,系统中内置有 "root" 用户。持有默认 "root" 用户密码的系统管理员应该第一时间修改 root 用户的密码,并根据业务需要创建普通用户并为这些用户授予适当的权限。在未授权的情况下,普通用户可以创建 DATABASE,并拥有自己创建的 DATABASE 的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他(即非该用户所创建的) DATABASE 的读写权限,使其可以在这些 DATABASE 上读写数据,但不能对其进行删除和修改数据库的操作。超级用户或者 topic 的创建者也可以给其它用户授予对某个 topic 的订阅权限。 - -## 用户管理 - -用户管理涉及用户的整个生命周期,从创建用户、对用户进行授权、撤销对用户的授权、查看用户信息、直到删除用户。 - -### 创建用户 - -创建用户的操作只能由 root 用户进行,语法如下 - -```sql -CREATE USER user_name PASS 'password' [SYSINFO {1\|0}]; -``` - -说明: - -- user_name 最长为 23 字节。 -- password 最长为 128 字节,合法字符包括"a-zA-Z0-9!?\$%\^&\*()_–+={[}]:;@\~\#\|\<,\>.?/",不可以出现单双引号、撇号、反斜杠和空格,且不可以为空。 -- SYSINFO 表示用户是否可以查看系统信息。1 表示可以查看,0 表示不可以查看。系统信息包括服务端配置信息、服务端各种节点信息(如 DNODE、QNODE等)、存储相关的信息等。默认为可以查看系统信息。 - -示例:创建密码为123456且可以查看系统信息的用户 test - -``` -SQL taos\> create user test pass '123456' sysinfo 1; Query OK, 0 of 0 rows affected (0.001254s) -``` - -### 查看用户 - -查看系统中的用户信息请使用 show users 命令,示例如下 - -```sql -show users; -``` - -也可以通过查询系统表 `INFORMATION_SCHEMA.INS_USERS` 获取系统中的用户信息,示例如下 - -```sql -select * from information_schema.ins_users; -``` - -### 删除用户 - -删除用户请使用 - -```sql -DROP USER user_name; -``` - -### 修改用户信息 - -修改用户信息的命令如下 - -```sql -ALTER USER user_name alter_user_clause alter_user_clause: { PASS 'literal' \| ENABLE value \| SYSINFO value } -``` - -说明: - -- PASS:修改用户密码。 -- ENABLE:修改用户是否启用。1 表示启用此用户,0 表示禁用此用户。 -- SYSINFO:修改用户是否可查看系统信息。1 表示可以查看系统信息,0 表示不可以查看系统信息。 - -示例:禁用 test 用户 - -```sql -alter user test enable 0; Query OK, 0 of 0 rows affected (0.001160s) -``` - -```sql -CREATE USER use_name PASS 'password' [SYSINFO {1|0}]; -``` - -## 访问控制 - -在 TDengine 企业版中,系统管理员可以根据业务和数据安全的需要控制任意一个用户对每一个数据库、订阅甚至表级别的访问。 - -```sql -GRANT privileges ON priv_level TO user_name - -privileges : { - ALL - | priv_type [, priv_type] ... -} - -priv_type : { - READ - | WRITE -} - -priv_level : { - dbname.* - | *.* -} -``` - -### 数据库权限 - - -TDengine 有超级用户和普通用户两类用户。超级用户缺省创建为root,拥有所有权限。使用超级用户创建出来的用户为普通用户。在未授权的情况下,普通用户可以创建 DATABASE,并拥有自己创建的 DATABASE 的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他 DATABASE 的读写权限,使其可以在此 DATABASE 上读写数据,但不能对其进行删除和修改数据库的操作。 - -对于非DATABASE的对象,如USER、DNODE、UDF、QNODE等,普通用户只有读权限(一般为SHOW命令),不能创建和修改。 - -对数据库的访问权限包含读和写两种权限,它们可以被分别授予,也可以被同时授予。 - -补充说明 - -- priv_level 格式中 "." 之前为数据库名称, "." 之后为表名称 -- "dbname.\*" 意思是名为 "dbname" 的数据库中的所有表 -- "\*.\*" 意思是所有数据库名中的所有表 - -**下表中总结了数据库权限的各种组合** - -对 root 用户和普通用户的权限的说明如下表 - -| 用户 | 描述 | 权限说明 | -|----------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 超级用户 | 只有 root 是超级用户 | DB 外部 所有操作权限,例如user、dnode、udf、qnode等的CRUD DB 权限,包括 创建 删除 更新,例如修改 Option,移动 Vgruop等 读 写 Enable/Disable 用户 | -| 普通用户 | 除 root 以外的其它用户均为普通用户 | 在可读的 DB 中,普通用户可以进行读操作 select describe show subscribe 在可写 DB 的内部,用户可以进行写操作: 创建、删除、修改 超级表 创建、删除、修改 子表 创建、删除、修改 topic 写入数据 被限制系统信息时,不可进行如下操作 show dnode、mnode、vgroups、qnode、snode 修改用户包括自身密码 show db时只能看到自己的db,并且不能看到vgroups、副本、cache等信息 无论是否被限制系统信息,都可以 管理 udf 可以创建 DB 自己创建的 DB 具备所有权限 非自己创建的 DB ,参照读、写列表中的权限 | - -### 消息订阅授权 - -任意用户都可以在自己拥有读权限的数据库上创建 topic。超级用户 root 可以在任意数据库上创建 topic。每个 topic 的订阅权限都可以被独立授权给任何用户,不管该用户是否拥有该数据库的访问权限。删除 topic 只能由 root 用户或者该 topic 的创建者进行。topic 只能由超级用户、topic的创建者或者被显式授予 subscribe 权限的用户订阅。 - -授予订阅权限的语法如下: - -```sql -GRANT privileges ON priv_level TO user_name privileges : { ALL | priv_type [, priv_type] ... } priv_type : { SUBSCRIBE } priv_level : { topic_name } -``` - -### 基于标签的授权(表级授权) - -从 TDengine 3.0.5.0 开始,我们支持按标签授权某个超级表中部分特定的子表。具体的 SQL 语法如下。 - -```sql -GRANT privileges ON priv_level [WITH tag_condition] TO user_name - -privileges : { - ALL - | SUBSCRIBE - | priv_type [, priv_type] ... -} - -priv_type : { - READ - | WRITE -} - -priv_level : { - dbname.tbname - | dbname.* - | *.* - | topic_name -} - -REVOKE privileges ON priv_level [WITH tag_condition] FROM user_name - -privileges : { - ALL - | priv_type [, priv_type] ... -} - -priv_type : { - READ - | WRITE -} - -priv_level : { - dbname.tbname - | dbname.* - | *.* -} -``` - -上面 SQL 的语义为: - -- 用户可以通过 dbname.tbname 来为指定的表(包括超级表和普通表)授予或回收其读写权限,不支持直接对子表授予或回收权限。 -- 用户可以通过 dbname.tbname 和 WITH 子句来为符合条件的所有子表授予或回收其读写权限。使用 WITH 子句时,权限级别必须为超级表。 - -**表级权限和数据库权限的关系** - -下表列出了在不同的数据库授权和表级授权的组合下产生的实际权限。 - -| |**表无授权** | **表读授权** | **表读授权有标签条件** | **表写授权** | **表写授权有标签条件** | -| -------------- | ---------------- | -------- | ---------- | ------ | ----------- | -| **数据库无授权** | 无授权 | 对此表有读权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表无权限 | 对此表有写权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有写权限,对数据库下的其他表无权限 | -| **数据库读授权** | 对所有表有读权限 | 对所有表有读权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表有读权限 | 对此表有写权限,对所有表有读权限 | 对此表符合标签权限的子表有写权限,所有表有读权限 | -| **数据库写授权** | 对所有表有写权限 | 对此表有读权限,对所有表有写权限 | 对此表符合标签权限的子表有读权限,对所有表有写权限 | 对所有表有写权限 | 对此表符合标签权限的子表有写权限,数据库下的其他表有写权限 | - -### 查看用户授权 - -使用下面的命令可以显示一个用户所拥有的授权: - -```sql -show user privileges -``` -## 撤销授权 - -```sql -REVOKE privileges ON priv_level FROM user_name - -privileges : { - ALL - | priv_type [, priv_type] ... -} - -priv_type : { - READ - | WRITE -} - -priv_level : { - dbname.* - | *.* -} - -``` - -### 撤销授权 - -1. 撤销数据库访问的授权 - -```sql -REVOKE privileges ON priv_level FROM user_name privileges : { ALL \| priv_type [, priv_type] ... } priv_type : { READ \| WRITE } priv_level : { dbname.\* \| \*.\* } -``` - -2. 撤销数据订阅的授权 - -```sql -REVOKE privileges ON priv_level FROM user_name privileges : { ALL \| priv_type [, priv_type] ... } priv_type : { SUBSCRIBE } priv_level : { topi_name } From 1372cede489fc173ab2eab01c12ebc12ba13186d Mon Sep 17 00:00:00 2001 From: dmchen Date: Mon, 28 Aug 2023 17:44:10 +0800 Subject: [PATCH 09/15] init --- include/common/tmsg.h | 44 ------------------------ source/dnode/mnode/impl/src/mndDb.c | 35 +++++++++++++++++-- source/dnode/mnode/impl/src/mndDnode.c | 23 ++++++++----- source/dnode/mnode/impl/src/mndMnode.c | 10 ++---- source/dnode/mnode/impl/src/mndProfile.c | 11 +++--- source/dnode/mnode/impl/src/mndQnode.c | 2 +- source/dnode/mnode/impl/src/mndStb.c | 24 +++++++++++-- source/dnode/mnode/impl/src/mndStream.c | 19 ++++++++-- source/dnode/mnode/impl/src/mndTopic.c | 11 ++++-- source/dnode/mnode/impl/src/mndUser.c | 20 +++++++---- source/dnode/mnode/impl/src/mndVgroup.c | 8 +++-- source/dnode/vnode/src/vnd/vnodeSvr.c | 6 +++- 12 files changed, 127 insertions(+), 86 deletions(-) diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 42a0549024..8deec53470 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -767,8 +767,6 @@ typedef struct { char* pAst2; int64_t deleteMark1; int64_t deleteMark2; - int32_t sqlLen; - char* sql; } SMCreateStbReq; int32_t tSerializeSMCreateStbReq(void* buf, int32_t bufLen, SMCreateStbReq* pReq); @@ -789,8 +787,6 @@ typedef struct { int8_t source; // 1-taosX or 0-taosClient int8_t reserved[6]; tb_uid_t suid; - int32_t sqlLen; - char* sql; } SMDropStbReq; int32_t tSerializeSMDropStbReq(void* buf, int32_t bufLen, SMDropStbReq* pReq); @@ -804,8 +800,6 @@ typedef struct { int32_t ttl; int32_t commentLen; char* comment; - int32_t sqlLen; - char* sql; } SMAlterStbReq; int32_t tSerializeSMAlterStbReq(void* buf, int32_t bufLen, SMAlterStbReq* pReq); @@ -875,8 +869,6 @@ int32_t tDeserializeSCreateAcctReq(void* buf, int32_t bufLen, SCreateAcctReq* pR typedef struct { char user[TSDB_USER_LEN]; - int32_t sqlLen; - char *sql; } SDropUserReq, SDropAcctReq; int32_t tSerializeSDropUserReq(void* buf, int32_t bufLen, SDropUserReq* pReq); @@ -889,8 +881,6 @@ typedef struct { int8_t enable; char user[TSDB_USER_LEN]; char pass[TSDB_USET_PASSWORD_LEN]; - int32_t sqlLen; - char* sql; } SCreateUserReq; int32_t tSerializeSCreateUserReq(void* buf, int32_t bufLen, SCreateUserReq* pReq); @@ -907,8 +897,6 @@ typedef struct { char tabName[TSDB_TABLE_NAME_LEN]; char* tagCond; int32_t tagCondLen; - int32_t sqlLen; - char* sql; } SAlterUserReq; int32_t tSerializeSAlterUserReq(void* buf, int32_t bufLen, SAlterUserReq* pReq); @@ -1071,8 +1059,6 @@ typedef struct { int16_t hashPrefix; int16_t hashSuffix; int32_t tsdbPageSize; - int32_t sqlLen; - char* sql; } SCreateDbReq; int32_t tSerializeSCreateDbReq(void* buf, int32_t bufLen, SCreateDbReq* pReq); @@ -1098,8 +1084,6 @@ typedef struct { int32_t minRows; int32_t walRetentionPeriod; int32_t walRetentionSize; - int32_t sqlLen; - char* sql; } SAlterDbReq; int32_t tSerializeSAlterDbReq(void* buf, int32_t bufLen, SAlterDbReq* pReq); @@ -1108,8 +1092,6 @@ int32_t tDeserializeSAlterDbReq(void* buf, int32_t bufLen, SAlterDbReq* pReq); typedef struct { char db[TSDB_DB_FNAME_LEN]; int8_t ignoreNotExists; - int32_t sqlLen; - char* sql; } SDropDbReq; int32_t tSerializeSDropDbReq(void* buf, int32_t bufLen, SDropDbReq* pReq); @@ -1307,8 +1289,6 @@ void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp); typedef struct { char db[TSDB_DB_FNAME_LEN]; STimeWindow timeRange; - int32_t sqlLen; - char* sql; } SCompactDbReq; int32_t tSerializeSCompactDbReq(void* buf, int32_t bufLen, SCompactDbReq* pReq); @@ -1872,8 +1852,6 @@ void tFreeSExplainRsp(SExplainRsp* pRsp); typedef struct { char fqdn[TSDB_FQDN_LEN]; // end point, hostname:port int32_t port; - int32_t sqlLen; - char* sql; } SCreateDnodeReq; int32_t tSerializeSCreateDnodeReq(void* buf, int32_t bufLen, SCreateDnodeReq* pReq); @@ -1885,8 +1863,6 @@ typedef struct { int32_t port; int8_t force; int8_t unsafe; - int32_t sqlLen; - char* sql; } SDropDnodeReq; int32_t tSerializeSDropDnodeReq(void* buf, int32_t bufLen, SDropDnodeReq* pReq); @@ -1902,8 +1878,6 @@ enum { typedef struct { int32_t dnodeId; int8_t restoreType; - int32_t sqlLen; - char* sql; } SRestoreDnodeReq; int32_t tSerializeSRestoreDnodeReq(void* buf, int32_t bufLen, SRestoreDnodeReq* pReq); @@ -1913,8 +1887,6 @@ typedef struct { int32_t dnodeId; char config[TSDB_DNODE_CONFIG_LEN]; char value[TSDB_DNODE_VALUE_LEN]; - int32_t sqlLen; - char* sql; } SMCfgDnodeReq; int32_t tSerializeSMCfgDnodeReq(void* buf, int32_t bufLen, SMCfgDnodeReq* pReq); @@ -1930,8 +1902,6 @@ int32_t tDeserializeSDCfgDnodeReq(void* buf, int32_t bufLen, SDCfgDnodeReq* pReq typedef struct { int32_t dnodeId; - int32_t sqlLen; - char *sql; } SMCreateMnodeReq, SMDropMnodeReq, SDDropMnodeReq, SMCreateQnodeReq, SMDropQnodeReq, SDCreateQnodeReq, SDDropQnodeReq, SMCreateSnodeReq, SMDropSnodeReq, SDCreateSnodeReq, SDDropSnodeReq; @@ -1972,8 +1942,6 @@ int32_t tDeserializeSKillTransReq(void* buf, int32_t bufLen, SKillTransReq* pReq typedef struct { int32_t useless; // useless - int32_t sqlLen; - char* sql; } SBalanceVgroupReq; int32_t tSerializeSBalanceVgroupReq(void* buf, int32_t bufLen, SBalanceVgroupReq* pReq); @@ -1992,8 +1960,6 @@ typedef struct { int32_t dnodeId1; int32_t dnodeId2; int32_t dnodeId3; - int32_t sqlLen; - char* sql; } SRedistributeVgroupReq; int32_t tSerializeSRedistributeVgroupReq(void* buf, int32_t bufLen, SRedistributeVgroupReq* pReq); @@ -2001,8 +1967,6 @@ int32_t tDeserializeSRedistributeVgroupReq(void* buf, int32_t bufLen, SRedistrib typedef struct { int32_t useless; - int32_t sqlLen; - char* sql; } SBalanceVgroupLeaderReq; int32_t tSerializeSBalanceVgroupLeaderReq(void* buf, int32_t bufLen, SBalanceVgroupLeaderReq* pReq); @@ -2262,7 +2226,6 @@ typedef struct { int64_t deleteMark; int8_t igUpdate; int64_t lastTs; - int32_t sqlLen; } SCMCreateStreamReq; typedef struct { @@ -2299,7 +2262,6 @@ typedef struct { char subDbName[TSDB_DB_FNAME_LEN]; char* ast; char subStbName[TSDB_TABLE_FNAME_LEN]; - int32_t sqlLen; } SCMCreateTopicReq; int32_t tSerializeSCMCreateTopicReq(void* buf, int32_t bufLen, const SCMCreateTopicReq* pReq); @@ -2484,8 +2446,6 @@ typedef struct { typedef struct { char name[TSDB_TOPIC_FNAME_LEN]; int8_t igNotExists; - int32_t sqlLen; - char* sql; } SMDropTopicReq; int32_t tSerializeSMDropTopicReq(void* buf, int32_t bufLen, SMDropTopicReq* pReq); @@ -2585,8 +2545,6 @@ typedef struct SVCreateTbReq { SSchemaWrapper schemaRow; } ntb; }; - int32_t sqlLen; - char* sql; } SVCreateTbReq; int tEncodeSVCreateTbReq(SEncoder* pCoder, const SVCreateTbReq* pReq); @@ -3061,8 +3019,6 @@ typedef struct { typedef struct { char name[TSDB_STREAM_FNAME_LEN]; int8_t igNotExists; - int32_t sqlLen; - char* sql; } SMDropStreamReq; typedef struct { diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index c58df5c88c..972705f7a8 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -736,7 +736,23 @@ static int32_t mndProcessCreateDbReq(SRpcMsg *pReq) { code = mndCreateDb(pMnode, pReq, &createReq, pUser); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "createDB", createReq.db, "", ""); + char detail[3000] = {0}; + sprintf(detail, "buffer:%d, cacheLast:%d, cacheLastSize:%d, compression:%d, daysPerFile:%d, " + "daysToKeep0:%d, daysToKeep:%d, daysToKeep2:%d, hashPrefix:%d, " + "hashSuffix:%d, ignoreExist:%d, maxRows:%d, minRows:%d, numOfRetensions:%d, " + "numOfStables:%d, numOfVgroups:%d, pages:%d, pageSize:%d, precision:%d, " + "replications:%d, schemaless:%d, sstTrigger:%d, strict:%d, " + "tsdbPageSize:%d, walFsyncPeriod:%d, walLevel:%d, walRetentionPeriod:%d, " + "walRetentionSize:%" PRId64 ", walRollPeriod:%d, walSegmentSize:%" PRId64, + createReq.buffer, createReq.cacheLast, createReq.cacheLastSize, createReq.compression, createReq.daysPerFile, + createReq.daysToKeep0, createReq.daysToKeep1, createReq.daysToKeep2, createReq.hashPrefix, + createReq.hashSuffix, createReq.ignoreExist, createReq.maxRows, createReq.minRows, createReq.numOfRetensions, + createReq.numOfStables, createReq.numOfVgroups, createReq.pages, createReq.pageSize, createReq.precision, + createReq.replications, createReq.schemaless, createReq.sstTrigger, createReq.strict, + createReq.tsdbPageSize, createReq.walFsyncPeriod, createReq.walLevel, createReq.walRetentionPeriod, + createReq.walRetentionSize, createReq.walRollPeriod, createReq.walSegmentSize); + + auditRecord(pReq, pMnode->clusterId, "createDB", createReq.db, "", detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -980,7 +996,17 @@ static int32_t mndProcessAlterDbReq(SRpcMsg *pReq) { if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; } - auditRecord(pReq, pMnode->clusterId, "alterDB", alterReq.db, "", ""); + char detail[3000] = {0}; + sprintf(detail, "buffer:%d, cacheLast:%d, cacheLastSize:%d, daysPerFile:%d, daysToKeep0:%d, " + "daysToKeep1:%d, daysToKeep2:%d, db:%s, minRows:%d, pages:%d, pageSize:%d, " + "replications:%d, sstTrigger:%d, strict:%d, walFsyncPeriod:%d, " + "walRetentionSize:%d", + alterReq.buffer, alterReq.cacheLast, alterReq.cacheLastSize, alterReq.daysPerFile, alterReq.daysToKeep0, + alterReq.daysToKeep1, alterReq.daysToKeep2, alterReq.db, alterReq.minRows, alterReq.pages, alterReq.pageSize, + alterReq.replications, alterReq.sstTrigger, alterReq.strict, alterReq.walFsyncPeriod, + alterReq.walRetentionSize); + + auditRecord(pReq, pMnode->clusterId, "alterDB", alterReq.db, "", detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -1271,7 +1297,10 @@ static int32_t mndProcessDropDbReq(SRpcMsg *pReq) { code = TSDB_CODE_ACTION_IN_PROGRESS; } - auditRecord(pReq, pMnode->clusterId, "dropDB", dropReq.db, "", ""); + char detail[1000] = {0}; + sprintf(detail, "ignoreNotExists:%d", dropReq.ignoreNotExists); + + auditRecord(pReq, pMnode->clusterId, "dropDB", dropReq.db, "", detail); _OVER: if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_ACTION_IN_PROGRESS) { diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 1bcbc4982b..949d41ef07 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -910,11 +910,10 @@ static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq) { if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; tsGrantHBInterval = 5; - char detail[1000] = {0}; - sprintf(detail, "%s:%d", - createReq.fqdn, createReq.port); + char obj[200] = {0}; + sprintf(obj, "%s:%d", createReq.fqdn, createReq.port); - auditRecord(pReq, pMnode->clusterId, "createDnode", detail, "", ""); + auditRecord(pReq, pMnode->clusterId, "createDnode", obj, "", ""); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -1066,10 +1065,13 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) { char obj1[150] = {0}; sprintf(obj1, "%s:%d", dropReq.fqdn, dropReq.port); - char obj2[10] = {0}; + char obj2[30] = {0}; sprintf(obj2, "%d", dropReq.dnodeId); - auditRecord(pReq, pMnode->clusterId, "dropDnode", obj1, obj2, ""); + char detail[100] = {0}; + sprintf(detail, "force:%d, unsafe:%d", dropReq.force, dropReq.unsafe); + + auditRecord(pReq, pMnode->clusterId, "dropDnode", obj1, obj2, detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -1252,10 +1254,13 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) { } } - char detail[50] = {0}; - sprintf(detail, "%d", cfgReq.dnodeId); + char obj[50] = {0}; + sprintf(obj, "%d", cfgReq.dnodeId); - auditRecord(pReq, pMnode->clusterId, "alterDnode", detail, "", ""); + char detail[500] = {0}; + sprintf(detail, "config:%s, value:%s", cfgReq.config, cfgReq.value); + + auditRecord(pReq, pMnode->clusterId, "alterDnode", obj, "", detail); int32_t code = -1; SSdb *pSdb = pMnode->pSdb; diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c index 8b9deb3988..5827a30b43 100644 --- a/source/dnode/mnode/impl/src/mndMnode.c +++ b/source/dnode/mnode/impl/src/mndMnode.c @@ -653,14 +653,10 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) { code = mndCreateMnode(pMnode, pReq, pDnode, &createReq); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - char detail[1000] = {0}; - - char obj[20] = {0}; + char obj[40] = {0}; sprintf(obj, "%d", createReq.dnodeId); - sprintf(detail, "dnodeId:%d", createReq.dnodeId); - - auditRecord(pReq, pMnode->clusterId, "createMnode", obj, detail, ""); + auditRecord(pReq, pMnode->clusterId, "createMnode", obj, "", ""); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -798,7 +794,7 @@ static int32_t mndProcessDropMnodeReq(SRpcMsg *pReq) { code = mndDropMnode(pMnode, pReq, pObj); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - char obj[20] = {0}; + char obj[40] = {0}; sprintf(obj, "%d", dropReq.dnodeId); auditRecord(pReq, pMnode->clusterId, "dropMnode", obj, "", ""); diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index db1546e33f..9847024bee 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -309,15 +309,14 @@ _CONNECT: code = 0; - char detail[1000] = {0}; - - char obj[30] = {0}; + char obj[100] = {0}; sprintf(obj, "%s:%d", ip, pConn->port); - sprintf(detail, "user:%s, from:%s, connType%d", - connReq.user, obj, connReq.connType); + char detail[1000] = {0}; + sprintf(detail, "connType:%d, db:%s, pid:%d, startTime:%" PRId64 ", sVer:%s, app:%s", + connReq.connType, connReq.db, connReq.pid, connReq.startTime, connReq.sVer, connReq.app); - auditRecord(pReq, pMnode->clusterId, "login", connReq.app, obj, detail); + auditRecord(pReq, pMnode->clusterId, "login", connReq.user, obj, detail); _OVER: diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c index 45efabe97d..767e06a8d4 100644 --- a/source/dnode/mnode/impl/src/mndQnode.c +++ b/source/dnode/mnode/impl/src/mndQnode.c @@ -423,7 +423,7 @@ static int32_t mndProcessDropQnodeReq(SRpcMsg *pReq) { char obj[33] = {0}; sprintf(obj, "%d", dropReq.dnodeId); - auditRecord(pReq, pMnode->clusterId, "createQnode", obj, "", ""); + auditRecord(pReq, pMnode->clusterId, "dropQnode", obj, "", ""); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index aa3ee89fd3..a5fe818133 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -1174,7 +1174,17 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) { } if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "createStb", pDb->name, createReq.name, ""); + char detail[2000] = {0}; + sprintf(detail, "colVer:%d, delay1:%" PRId64 ", delay2:%" PRId64 ", deleteMark1:%" PRId64 ", " + "deleteMark2:%" PRId64 ", igExists:%d, numOfColumns:%d, numOfFuncs:%d, numOfTags:%d, " + "source:%d, suid:%" PRId64 ", tagVer:%d, ttl:%d, " + "watermark1:%" PRId64 ", watermark2:%" PRId64, + createReq.colVer, createReq.delay1, createReq.delay2, createReq.deleteMark1, + createReq.deleteMark2, createReq.igExists, createReq.numOfColumns, createReq.numOfFuncs, createReq.numOfTags, + createReq.source, createReq.suid, createReq.tagVer, createReq.ttl, + createReq.watermark1, createReq.watermark2); + + auditRecord(pReq, pMnode->clusterId, "createStb", pDb->name, createReq.name, detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -2244,7 +2254,11 @@ static int32_t mndProcessAlterStbReq(SRpcMsg *pReq) { code = mndAlterStb(pMnode, pReq, &alterReq, pDb, pStb); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "alterStb", pDb->name, alterReq.name, ""); + char detail[2000] = {0}; + sprintf(detail, "alterType:%d, numOfFields:%d, ttl:%d" , + alterReq.alterType, alterReq.numOfFields, alterReq.ttl); + + auditRecord(pReq, pMnode->clusterId, "alterStb", pDb->name, alterReq.name, detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -2507,7 +2521,11 @@ static int32_t mndProcessDropStbReq(SRpcMsg *pReq) { code = mndDropStb(pMnode, pReq, pDb, pStb); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "dropStb", pDb->name, dropReq.name, ""); + char detail[2000] = {0}; + sprintf(detail, "igNotExists:%d, source:%d" , + dropReq.igNotExists, dropReq.source); + + auditRecord(pReq, pMnode->clusterId, "dropStb", pDb->name, dropReq.name, detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index c553257094..03bb84b04d 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -829,7 +829,19 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) { code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "createStream", createStreamReq.name, "", ""); + char detail[2000] = {0}; + sprintf(detail, "checkpointFreq:%" PRId64 ", createStb:%d, deleteMark:%" PRId64 ", " + "fillHistory:%d, igExists:%d, " + "igExpired:%d, igUpdate:%d, lastTs:%" PRId64 ", " + "maxDelay:%" PRId64 ", numOfTags:%d, sourceDB:%s, " + "targetStbFullName:%s, triggerType:%d, watermark:%" PRId64, + createStreamReq.checkpointFreq, createStreamReq.createStb, createStreamReq.deleteMark, + createStreamReq.fillHistory, createStreamReq.igExists, + createStreamReq.igExpired, createStreamReq.igUpdate, createStreamReq.lastTs, + createStreamReq.maxDelay, createStreamReq.numOfTags, createStreamReq.sourceDB, + createStreamReq.targetStbFullName, createStreamReq.triggerType, createStreamReq.watermark); + + auditRecord(pReq, pMnode->clusterId, "createStream", createStreamReq.name, "", detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -1076,7 +1088,10 @@ static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) { return -1; } - auditRecord(pReq, pMnode->clusterId, "dropStream", dropReq.name, "", ""); + char detail[100] = {0}; + sprintf(detail, "igNotExists:%d", dropReq.igNotExists); + + auditRecord(pReq, pMnode->clusterId, "dropStream", dropReq.name, "", detail); sdbRelease(pMnode->pSdb, pStream); mndTransDrop(pTrans); diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c index 831e67bea3..e1d964a8a3 100644 --- a/source/dnode/mnode/impl/src/mndTopic.c +++ b/source/dnode/mnode/impl/src/mndTopic.c @@ -622,7 +622,11 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) { code = TSDB_CODE_ACTION_IN_PROGRESS; } - auditRecord(pReq, pMnode->clusterId, "crateTopic", createTopicReq.name, createTopicReq.subDbName, createTopicReq.sql); + char detail[1000] = {0}; + sprintf(detail, "igExists:%d, subStbName:%s, subType:%d, withMeta:%d", + createTopicReq.igExists, createTopicReq.subStbName, createTopicReq.subType, createTopicReq.withMeta); + + auditRecord(pReq, pMnode->clusterId, "crateTopic", createTopicReq.name, createTopicReq.subDbName, detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -815,7 +819,10 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { return -1; } - auditRecord(pReq, pMnode->clusterId, "dropTopic", dropReq.name, "", dropReq.sql); + char detail[100] = {0}; + sprintf(detail, "igNotExists:%d", dropReq.igNotExists); + + auditRecord(pReq, pMnode->clusterId, "dropTopic", dropReq.name, "", detail); return TSDB_CODE_ACTION_IN_PROGRESS; } diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 8afc73bef6..098f260bb6 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -656,7 +656,11 @@ static int32_t mndProcessCreateUserReq(SRpcMsg *pReq) { code = mndCreateUser(pMnode, pOperUser->acct, &createReq, pReq); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "createUser", createReq.user, "", ""); + char detail[1000] = {0}; + sprintf(detail, "createType:%d, enable:%d, superUser:%d, sysInfo:%d", + createReq.createType, createReq.enable, createReq.superUser, createReq.sysInfo); + + auditRecord(pReq, pMnode->clusterId, "createUser", createReq.user, "", detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -973,13 +977,17 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) { code = mndAlterUser(pMnode, pUser, &newUser, pReq); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + char detail[1000] = {0}; + sprintf(detail, "alterType:%d, enable:%d, superUser:%d, sysInfo:%d, tabName:%s", + alterReq.alterType, alterReq.enable, alterReq.superUser, alterReq.sysInfo, alterReq.tabName); + if(alterReq.alterType == TSDB_ALTER_USER_PASSWD){ - auditRecord(pReq, pMnode->clusterId, "changePassword", alterReq.user, alterReq.objname, ""); + auditRecord(pReq, pMnode->clusterId, "changePassword", alterReq.user, alterReq.objname, detail); } else if(alterReq.alterType == TSDB_ALTER_USER_SUPERUSER || alterReq.alterType == TSDB_ALTER_USER_ENABLE || alterReq.alterType == TSDB_ALTER_USER_SYSINFO){ - auditRecord(pReq, pMnode->clusterId, "alterUser", alterReq.user, alterReq.objname, ""); + auditRecord(pReq, pMnode->clusterId, "alterUser", alterReq.user, alterReq.objname, detail); } else if(alterReq.alterType == TSDB_ALTER_USER_ADD_READ_DB|| alterReq.alterType == TSDB_ALTER_USER_ADD_WRITE_DB|| @@ -988,10 +996,10 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) { alterReq.alterType == TSDB_ALTER_USER_ADD_READ_TABLE|| alterReq.alterType == TSDB_ALTER_USER_ADD_WRITE_TABLE|| alterReq.alterType == TSDB_ALTER_USER_ADD_ALL_TABLE){ - auditRecord(pReq, pMnode->clusterId, "GrantPrivileges", alterReq.user, alterReq.objname, ""); + auditRecord(pReq, pMnode->clusterId, "GrantPrivileges", alterReq.user, alterReq.objname, detail); } else{ - auditRecord(pReq, pMnode->clusterId, "RevokePrivileges", alterReq.user, alterReq.objname, ""); + auditRecord(pReq, pMnode->clusterId, "RevokePrivileges", alterReq.user, alterReq.objname, detail); } _OVER: @@ -1063,7 +1071,7 @@ static int32_t mndProcessDropUserReq(SRpcMsg *pReq) { code = mndDropUser(pMnode, pReq, pUser); if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; - auditRecord(pReq, pMnode->clusterId, "dropUser", dropReq.user, "", dropReq.sql); + auditRecord(pReq, pMnode->clusterId, "dropUser", dropReq.user, "", ""); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index ff621198ff..b16ec8c2cb 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -2175,7 +2175,11 @@ static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) { char obj[33] = {0}; sprintf(obj, "%d", req.vgId); - auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", obj, "", req.sql); + char detail[1000] = {0}; + sprintf(detail, "dnodeId1:%d, dnodeId2:%d, dnodeId3:%d", + req.dnodeId1, req.dnodeId2, req.dnodeId3); + + auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", obj, "", detail); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { @@ -2987,7 +2991,7 @@ static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) { code = mndBalanceVgroup(pMnode, pReq, pArray); } - auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql); + auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", ""); _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index 3687756ffc..ccdde8ade4 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -934,7 +934,11 @@ static int32_t vnodeProcessCreateTbReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t clusterId = pVnode->config.syncCfg.nodeInfo[0].clusterId; - auditRecord(pReq, clusterId, "createTable", pVnode->config.dbname, pCreateReq->name, ""); + char detail[1000] = {0}; + sprintf(detail, "btime:%" PRId64 ", flags:%d, ttl:%d, type:%d", + pCreateReq->btime, pCreateReq->flags, pCreateReq->ttl, pCreateReq->type); + + auditRecord(pReq, clusterId, "createTable", pVnode->config.dbname, pCreateReq->name, detail); } vDebug("vgId:%d, add %d new created tables into query table list", TD_VID(pVnode), (int32_t)taosArrayGetSize(tbUids)); From 023cf096b3888aace8f81ff58e91f97b6f48cec3 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Tue, 29 Aug 2023 10:25:44 +0800 Subject: [PATCH 10/15] handle taosd quit --- source/libs/transport/src/transSvr.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/libs/transport/src/transSvr.c b/source/libs/transport/src/transSvr.c index c6c412022a..40610d7651 100644 --- a/source/libs/transport/src/transSvr.c +++ b/source/libs/transport/src/transSvr.c @@ -289,8 +289,15 @@ static bool uvHandleReq(SSvrConn* pConn) { } void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) { - SSvrConn* conn = cli->data; - STrans* pTransInst = conn->pTransInst; + SSvrConn* conn = cli->data; + SWorkThrd* pThrd = conn->hostThrd; + + if (true == pThrd->quit) { + tInfo("work thread received quit msg, destroy conn"); + destroyConn(conn, true); + return; + } + STrans* pTransInst = conn->pTransInst; SConnBuffer* pBuf = &conn->readBuf; if (nread > 0) { From b88d79d2efa403dd4ef7ca21acaa98218110ca55 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Tue, 29 Aug 2023 10:20:56 +0800 Subject: [PATCH 11/15] fix(tsdb/open fs): fix retval --- source/dnode/vnode/src/tsdb/tsdbFS2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index 6bdedebe35..a997c3eea5 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -637,7 +637,7 @@ _exit: } else { tsdbInfo("vgId:%d %s success", TD_VID(pTsdb->pVnode), __func__); } - return 0; + return code; } static int32_t close_file_system(STFileSystem *fs) { @@ -730,7 +730,7 @@ _exit: } else { tsdbInfo("vgId:%d %s success", TD_VID(pTsdb->pVnode), __func__); } - return 0; + return code; } static void tsdbDoWaitBgTask(STFileSystem *fs, STFSBgTask *task) { From 667fe69fd1ffea6c121edc2c999a4d0e6b7899bf Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 29 Aug 2023 10:40:32 +0800 Subject: [PATCH 12/15] fix: join on condition split issue --- source/libs/planner/src/planOptimizer.c | 3 +++ tests/system-test/2-query/stbJoin.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 7ce6994ce6..51d5c96c86 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -969,6 +969,9 @@ static int32_t pushDownCondOptDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* p if (NULL == pJoin->node.pConditions) { int32_t code = pushDownCondOptJoinExtractCond(pCxt, pJoin); + if (TSDB_CODE_SUCCESS == code) { + code = pushDownCondOptJoinExtractEqualOnCond(pCxt, pJoin); + } if (TSDB_CODE_SUCCESS == code) { OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE); pCxt->optimized = true; diff --git a/tests/system-test/2-query/stbJoin.py b/tests/system-test/2-query/stbJoin.py index b4d6301424..e21a875cf2 100644 --- a/tests/system-test/2-query/stbJoin.py +++ b/tests/system-test/2-query/stbJoin.py @@ -106,6 +106,9 @@ class TDTestCase: tdSql.query(f"select a.ts, b.ts from sta a, stb b where a.ts=b.ts and (a.tg1=b.tg1 and a.tg1 > b.tg1);") tdSql.checkRows(0) + tdSql.query(f"select a.* from sta a join stb b on a.tg1=b.tg1 and a.ts=b.ts and a.tg2=b.tg2;") + tdSql.checkRows(12) + # tdSql.checkData(0,1,10) tdSql.error(f"select a.* from sta a join stb b on a.tg1=b.tg1 where a.ts=b.ts or a.tg2=b.tg2;") From 5d04461b79fc76cbda5367e15a758b0c450e5e3b Mon Sep 17 00:00:00 2001 From: wade zhang <95411902+gccgdb1234@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:01:32 +0800 Subject: [PATCH 13/15] Update 09-storage.md --- docs/zh/17-operation/09-storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/17-operation/09-storage.md b/docs/zh/17-operation/09-storage.md index ca3f3af49b..185b2c40ec 100644 --- a/docs/zh/17-operation/09-storage.md +++ b/docs/zh/17-operation/09-storage.md @@ -53,4 +53,4 @@ dataDir /mnt/data6 2 0 ## 同级挂载点选择策略 -一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 `minimalDataDirGB` \ No newline at end of file +一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 2GB,即会跳过可用空间小于 2GB 的挂载点。 From fb5b34184fcee0f3b6d8f448c651a95fd79a512d Mon Sep 17 00:00:00 2001 From: wade zhang <95411902+gccgdb1234@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:20:42 +0800 Subject: [PATCH 14/15] Update 09-storage.md --- docs/zh/17-operation/09-storage.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/zh/17-operation/09-storage.md b/docs/zh/17-operation/09-storage.md index 5c06c3cc99..185b2c40ec 100644 --- a/docs/zh/17-operation/09-storage.md +++ b/docs/zh/17-operation/09-storage.md @@ -53,8 +53,4 @@ dataDir /mnt/data6 2 0 ## 同级挂载点选择策略 -<<<<<<< HEAD 一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 2GB,即会跳过可用空间小于 2GB 的挂载点。 -======= -一般情况下,当 TDengine 要从同级挂载点中选择一个用于生成新的数据文件时,采用 round robin 策略进行选择。但现实中有可能每个磁盘的容量不相同,或者容量相同但写入的数据量不相同,这就导致会出现每个磁盘上的可用空间不均衡,在实际进行选择时有可能会选择到一个剩余空间已经很小的磁盘。为了解决这个问题,从 3.1.1.0 开始引入了一个新的配置 `minDiskFreeSize`,当某块磁盘上的可用空间小于等于这个阈值时,该磁盘将不再被选择用于生成新的数据文件。该配置项的单位为字节,其值应该大于 2GB,即会跳过可用空间小于 2GB 的挂载点。 ->>>>>>> 5d04461b79fc76cbda5367e15a758b0c450e5e3b From df2b2484df89563abcb7a828a2421e59d73c76a1 Mon Sep 17 00:00:00 2001 From: Shungang Li Date: Tue, 29 Aug 2023 17:15:40 +0800 Subject: [PATCH 15/15] fix: ttl cache entry record the original information for deletion --- source/dnode/vnode/src/inc/metaTtl.h | 4 +- source/dnode/vnode/src/meta/metaTtl.c | 53 +++++++++++++++++---------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/source/dnode/vnode/src/inc/metaTtl.h b/source/dnode/vnode/src/inc/metaTtl.h index c2cd389dab..ead2d89b28 100644 --- a/source/dnode/vnode/src/inc/metaTtl.h +++ b/source/dnode/vnode/src/inc/metaTtl.h @@ -26,7 +26,7 @@ extern "C" { #endif typedef enum DirtyEntryType { - ENTRY_TYPE_DEL = 1, + ENTRY_TYPE_DELETE = 1, ENTRY_TYPE_UPSERT = 2, } DirtyEntryType; @@ -44,6 +44,8 @@ typedef struct STtlManger { typedef struct { int64_t ttlDays; int64_t changeTimeMs; + int64_t ttlDaysDirty; + int64_t changeTimeMsDirty; } STtlCacheEntry; typedef struct { diff --git a/source/dnode/vnode/src/meta/metaTtl.c b/source/dnode/vnode/src/meta/metaTtl.c index 3c45982311..f920296b4a 100644 --- a/source/dnode/vnode/src/meta/metaTtl.c +++ b/source/dnode/vnode/src/meta/metaTtl.c @@ -209,7 +209,8 @@ static int32_t ttlMgrFillCacheOneEntry(const void *pKey, int keyLen, const void int64_t ttlDays = *(int64_t *)pVal; int64_t changeTimeMs = ttlKey->deleteTimeMs - ttlDays * tsTtlUnit * 1000; - STtlCacheEntry data = {.ttlDays = ttlDays, .changeTimeMs = changeTimeMs}; + STtlCacheEntry data = { + .ttlDays = ttlDays, .changeTimeMs = changeTimeMs, .ttlDaysDirty = ttlDays, .changeTimeMsDirty = changeTimeMs}; return taosHashPut(pCache, &uid, sizeof(uid), &data, sizeof(data)); } @@ -257,34 +258,37 @@ static int32_t ttlMgrFindExpiredOneEntry(const void *pKey, int keyLen, const voi static int ttlMgrConvert(TTB *pOldTtlIdx, TTB *pNewTtlIdx, void *pMeta) { SMeta *meta = pMeta; - metaInfo("ttlMgr convert ttl start."); + metaInfo("ttlMgr convert start."); SConvertData cvData = {.pNewTtlIdx = pNewTtlIdx, .pMeta = meta}; int ret = tdbTbTraversal(pOldTtlIdx, &cvData, ttlMgrConvertOneEntry); if (ret < 0) { - metaError("failed to convert ttl since %s", tstrerror(terrno)); + metaError("failed to convert since %s", tstrerror(terrno)); } - metaInfo("ttlMgr convert ttl end."); + metaInfo("ttlMgr convert end."); return ret; } int ttlMgrInsertTtl(STtlManger *pTtlMgr, const STtlUpdTtlCtx *updCtx) { if (updCtx->ttlDays == 0) return 0; - STtlCacheEntry cacheEntry = {.ttlDays = updCtx->ttlDays, .changeTimeMs = updCtx->changeTimeMs}; + STtlCacheEntry cacheEntry = {.ttlDays = updCtx->ttlDays, + .changeTimeMs = updCtx->changeTimeMs, + .ttlDaysDirty = updCtx->ttlDays, + .changeTimeMsDirty = updCtx->changeTimeMs}; STtlDirtyEntry dirtryEntry = {.type = ENTRY_TYPE_UPSERT}; int ret = taosHashPut(pTtlMgr->pTtlCache, &updCtx->uid, sizeof(updCtx->uid), &cacheEntry, sizeof(cacheEntry)); if (ret < 0) { - metaError("%s, ttlMgr insert failed to update ttl cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr insert failed to update cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } ret = taosHashPut(pTtlMgr->pDirtyUids, &updCtx->uid, sizeof(updCtx->uid), &dirtryEntry, sizeof(dirtryEntry)); if (ret < 0) { - metaError("%s, ttlMgr insert failed to update ttl dirty uids since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr insert failed to update dirty uids since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } @@ -304,11 +308,11 @@ _out: int ttlMgrDeleteTtl(STtlManger *pTtlMgr, const STtlDelTtlCtx *delCtx) { if (delCtx->ttlDays == 0) return 0; - STtlDirtyEntry dirtryEntry = {.type = ENTRY_TYPE_DEL}; + STtlDirtyEntry dirtryEntry = {.type = ENTRY_TYPE_DELETE}; int ret = taosHashPut(pTtlMgr->pDirtyUids, &delCtx->uid, sizeof(delCtx->uid), &dirtryEntry, sizeof(dirtryEntry)); if (ret < 0) { - metaError("%s, ttlMgr del failed to update ttl dirty uids since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr del failed to update dirty uids since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } @@ -332,19 +336,22 @@ int ttlMgrUpdateChangeTime(STtlManger *pTtlMgr, const STtlUpdCtimeCtx *pUpdCtime goto _out; } - STtlCacheEntry cacheEntry = {.ttlDays = oldData->ttlDays, .changeTimeMs = pUpdCtimeCtx->changeTimeMs}; + STtlCacheEntry cacheEntry = {.ttlDays = oldData->ttlDays, + .changeTimeMs = oldData->changeTimeMs, + .ttlDaysDirty = oldData->ttlDays, + .changeTimeMsDirty = pUpdCtimeCtx->changeTimeMs}; STtlDirtyEntry dirtryEntry = {.type = ENTRY_TYPE_UPSERT}; ret = taosHashPut(pTtlMgr->pTtlCache, &pUpdCtimeCtx->uid, sizeof(pUpdCtimeCtx->uid), &cacheEntry, sizeof(cacheEntry)); if (ret < 0) { - metaError("%s, ttlMgr update ctime failed to update ttl cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr update ctime failed to update cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } ret = taosHashPut(pTtlMgr->pDirtyUids, &pUpdCtimeCtx->uid, sizeof(pUpdCtimeCtx->uid), &dirtryEntry, sizeof(dirtryEntry)); if (ret < 0) { - metaError("%s, ttlMgr update ctime failed to update ttl dirty uids since %s", pTtlMgr->logPrefix, + metaError("%s, ttlMgr update ctime failed to update dirty uids since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } @@ -396,27 +403,35 @@ int ttlMgrFlush(STtlManger *pTtlMgr, TXN *pTxn) { STtlIdxKeyV1 ttlKey; ttlMgrBuildKey(&ttlKey, cacheEntry->ttlDays, cacheEntry->changeTimeMs, *pUid); + STtlIdxKeyV1 ttlKeyDirty; + ttlMgrBuildKey(&ttlKeyDirty, cacheEntry->ttlDaysDirty, cacheEntry->changeTimeMsDirty, *pUid); + if (pEntry->type == ENTRY_TYPE_UPSERT) { - ret = tdbTbUpsert(pTtlMgr->pTtlIdx, &ttlKey, sizeof(ttlKey), &cacheEntry->ttlDays, sizeof(cacheEntry->ttlDays), - pTxn); + // delete old key & upsert new key + tdbTbDelete(pTtlMgr->pTtlIdx, &ttlKey, sizeof(ttlKey), pTxn); // maybe first insert, ignore error + ret = tdbTbUpsert(pTtlMgr->pTtlIdx, &ttlKeyDirty, sizeof(ttlKeyDirty), &cacheEntry->ttlDaysDirty, + sizeof(cacheEntry->ttlDaysDirty), pTxn); if (ret < 0) { - metaError("%s, ttlMgr flush failed to flush ttl cache upsert since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr flush failed to upsert since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } - } else if (pEntry->type == ENTRY_TYPE_DEL) { + + cacheEntry->ttlDays = cacheEntry->ttlDaysDirty; + cacheEntry->changeTimeMs = cacheEntry->changeTimeMsDirty; + } else if (pEntry->type == ENTRY_TYPE_DELETE) { ret = tdbTbDelete(pTtlMgr->pTtlIdx, &ttlKey, sizeof(ttlKey), pTxn); if (ret < 0) { - metaError("%s, ttlMgr flush failed to flush ttl cache del since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr flush failed to delete since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } ret = taosHashRemove(pTtlMgr->pTtlCache, pUid, sizeof(*pUid)); if (ret < 0) { - metaError("%s, ttlMgr flush failed to delete ttl cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); + metaError("%s, ttlMgr flush failed to remove cache since %s", pTtlMgr->logPrefix, tstrerror(terrno)); goto _out; } } else { - metaError("%s, ttlMgr flush failed to flush ttl cache, unknown type: %d", pTtlMgr->logPrefix, pEntry->type); + metaError("%s, ttlMgr flush failed, unknown type: %d", pTtlMgr->logPrefix, pEntry->type); goto _out; }