From ce9b84831d7e5bf171b6081566ae2af85a58c120 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Wed, 16 Dec 2020 18:43:08 +0000 Subject: [PATCH 01/22] TD-2334 --- src/client/inc/tsclient.h | 2 -- src/client/src/tscSql.c | 39 ++++++++++---------------------------- src/client/src/tscSystem.c | 1 - src/client/src/tscUtil.c | 19 +++++-------------- 4 files changed, 15 insertions(+), 46 deletions(-) diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 21a7624b28..7ce9809420 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -307,7 +307,6 @@ typedef struct STscObj { SRpcCorEpSet *tscCorMgmtEpSet; void* pDnodeConn; pthread_mutex_t mutex; - T_REF_DECLARE() } STscObj; typedef struct SSubqueryState { @@ -483,7 +482,6 @@ extern int tscObjRef; extern void * tscTmr; extern void * tscQhandle; extern int tscKeepConn[]; -extern int tsInsertHeadSize; extern int tscNumOfThreads; extern int tscRefId; diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index d7dec2f356..9ad38e3360 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -115,9 +115,7 @@ static SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pa pObj->signature = pObj; pObj->pDnodeConn = pDnodeConn; - T_REF_INIT_VAL(pObj, 1); - tstrncpy(pObj->user, user, sizeof(pObj->user)); secretEncryptLen = MIN(secretEncryptLen, sizeof(pObj->pass)); memcpy(pObj->pass, secretEncrypt, secretEncryptLen); @@ -172,11 +170,9 @@ static SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pa if (taos != NULL) { *taos = pObj; } - - registerSqlObj(pSql); - tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg); - pObj->rid = taosAddRef(tscRefId, pObj); + registerSqlObj(pSql); + return pSql; } @@ -288,34 +284,19 @@ void taos_close(TAOS *taos) { return; } - // make sure that the close connection can only be executed once. - pObj->signature = NULL; - taosTmrStopA(&(pObj->pTimer)); - - if (pObj->hbrid > 0) { - SSqlObj* pHb = (SSqlObj*)taosAcquireRef(tscObjRef, pObj->hbrid); - if (pHb != NULL) { - if (pHb->rpcRid > 0) { // wait for rsp from dnode - rpcCancelRequest(pHb->rpcRid); - pHb->rpcRid = -1; - } - - tscDebug("%p HB is freed", pHb); - taos_free_result(pHb); - taosReleaseRef(tscObjRef, pHb->self); + SSqlObj* pHb = (SSqlObj*)taosAcquireRef(tscObjRef, pObj->hbrid); + if (pHb != NULL) { + if (pHb->rpcRid > 0) { // wait for rsp from dnode + rpcCancelRequest(pHb->rpcRid); + pHb->rpcRid = -1; } - } - int32_t ref = T_REF_DEC(pObj); - assert(ref >= 0); - - if (ref > 0) { - tscDebug("%p %d remain sqlObjs, not free tscObj and dnodeConn:%p", pObj, ref, pObj->pDnodeConn); - return; + tscDebug("%p HB is freed", pHb); + taosReleaseRef(tscObjRef, pHb->self); + taos_free_result(pHb); } tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn); - taosRemoveRef(tscRefId, pObj->rid); } diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index 1eddeacc65..d98ab2facc 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -36,7 +36,6 @@ int tscObjRef = -1; void * tscTmr; void * tscQhandle; void * tscCheckDiskUsageTmr; -int tsInsertHeadSize; int tscRefId = -1; int tscNumOfThreads; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 7dfab427b5..95ba2bd849 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -460,15 +460,7 @@ void tscFreeRegisteredSqlObj(void *pSql) { assert(p->self != 0); tscFreeSqlObj(p); - - int32_t ref = T_REF_DEC(pTscObj); - assert(ref >= 0); - - tscDebug("%p free sqlObj completed, tscObj:%p ref:%d", p, pTscObj, ref); - if (ref == 0) { - tscDebug("%p all sqlObj freed, free tscObj:%p", p, pTscObj); - taosRemoveRef(tscRefId, pTscObj->rid); - } + taosReleaseRef(tscRefId, pTscObj->rid); } void tscFreeTableMetaHelper(void *pTableMeta) { @@ -810,6 +802,7 @@ static void extractTableMeta(SSqlCmd* pCmd) { } int32_t tscMergeTableDataBlocks(SSqlObj* pSql) { + const int INSERT_HEAD_SIZE = sizeof(SMsgDesc) + sizeof(SSubmitMsg); SSqlCmd* pCmd = &pSql->cmd; void* pVnodeDataBlockHashList = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); @@ -824,7 +817,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql) { STableDataBlocks* dataBuf = NULL; int32_t ret = tscGetDataBlockFromList(pVnodeDataBlockHashList, pOneTableBlock->vgId, TSDB_PAYLOAD_SIZE, - tsInsertHeadSize, 0, pOneTableBlock->tableId, pOneTableBlock->pTableMeta, &dataBuf, pVnodeDataBlockList); + INSERT_HEAD_SIZE, 0, pOneTableBlock->tableId, pOneTableBlock->pTableMeta, &dataBuf, pVnodeDataBlockList); if (ret != TSDB_CODE_SUCCESS) { tscError("%p failed to prepare the data block buffer for merging table data, code:%d", pSql, ret); taosHashCleanup(pVnodeDataBlockHashList); @@ -1917,9 +1910,7 @@ void tscResetForNextRetrieve(SSqlRes* pRes) { } void registerSqlObj(SSqlObj* pSql) { - int32_t ref = T_REF_INC(pSql->pTscObj); - tscDebug("%p add to tscObj:%p, ref:%d", pSql, pSql->pTscObj, ref); - + taosAcquireRef(tscRefId, pSql->pTscObj->rid); pSql->self = taosAddRef(tscObjRef, pSql); } @@ -2626,4 +2617,4 @@ int32_t copyTagData(STagData* dst, const STagData* src) { } return 0; -} \ No newline at end of file +} From c2801a46c8c1fe92f4926135a86a250827f9a8ff Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 18 Dec 2020 15:05:13 +0800 Subject: [PATCH 02/22] [TD-2484]: use IPv4's AI_INET instead of AI_UNSPEC --- src/dnode/src/dnodeTelemetry.c | 4 ++-- src/rpc/src/rpcMain.c | 2 +- src/sync/src/syncMain.c | 2 +- src/util/inc/tsocket.h | 2 +- src/util/src/tnettest.c | 2 +- src/util/src/tsocket.c | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/dnode/src/dnodeTelemetry.c b/src/dnode/src/dnodeTelemetry.c index 85f0137d89..ff9598ecc5 100644 --- a/src/dnode/src/dnodeTelemetry.c +++ b/src/dnode/src/dnodeTelemetry.c @@ -195,7 +195,7 @@ static void addRuntimeInfo(SBufferWriter* bw) { static void sendTelemetryReport() { char buf[128]; - uint32_t ip = taosGetIpFromFqdn(TELEMETRY_SERVER); + uint32_t ip = taosGetIpv4FromFqdn(TELEMETRY_SERVER); if (ip == 0xffffffff) { dTrace("failed to get IP address of " TELEMETRY_SERVER ", reason:%s", strerror(errno)); return; @@ -308,4 +308,4 @@ void dnodeCleanupTelemetry() { pthread_join(tsTelemetryThread, NULL); tsem_destroy(&tsExitSem); } -} \ No newline at end of file +} diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index 200d189d45..9a3a42ed15 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -576,7 +576,7 @@ static void rpcFreeMsg(void *msg) { static SRpcConn *rpcOpenConn(SRpcInfo *pRpc, char *peerFqdn, uint16_t peerPort, int8_t connType) { SRpcConn *pConn; - uint32_t peerIp = taosGetIpFromFqdn(peerFqdn); + uint32_t peerIp = taosGetIpv4FromFqdn(peerFqdn); if (peerIp == 0xFFFFFFFF) { tError("%s, failed to resolve FQDN:%s", pRpc->label, peerFqdn); terrno = TSDB_CODE_RPC_FQDN_ERROR; diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index ac79b48606..3369d052d8 100644 --- a/src/sync/src/syncMain.c +++ b/src/sync/src/syncMain.c @@ -486,7 +486,7 @@ static void syncRemovePeer(SSyncPeer *pPeer) { } static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo) { - uint32_t ip = taosGetIpFromFqdn(pInfo->nodeFqdn); + uint32_t ip = taosGetIpv4FromFqdn(pInfo->nodeFqdn); if (ip == 0xFFFFFFFF) { sError("failed to add peer, can resolve fqdn:%s since %s", pInfo->nodeFqdn, strerror(errno)); terrno = TSDB_CODE_RPC_FQDN_ERROR; diff --git a/src/util/inc/tsocket.h b/src/util/inc/tsocket.h index 391cc44acc..a339955cc0 100644 --- a/src/util/inc/tsocket.h +++ b/src/util/inc/tsocket.h @@ -33,7 +33,7 @@ SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port); int32_t taosKeepTcpAlive(SOCKET sockFd); int32_t taosGetFqdn(char *); -uint32_t taosGetIpFromFqdn(const char *); +uint32_t taosGetIpv4FromFqdn(const char *); void tinet_ntoa(char *ipstr, uint32_t ip); uint32_t ip2uint(const char *const ip_addr); diff --git a/src/util/src/tnettest.c b/src/util/src/tnettest.c index 89601147a5..e1b834b949 100644 --- a/src/util/src/tnettest.c +++ b/src/util/src/tnettest.c @@ -449,7 +449,7 @@ static void taosNetTestClient(char *host, int32_t startPort, int32_t pkgLen) { int32_t endPort = startPort + 11; uInfo("work as client, host:%s startPort:%d endPort:%d pkgLen:%d\n", host, startPort, endPort, pkgLen); - uint32_t serverIp = taosGetIpFromFqdn(host); + uint32_t serverIp = taosGetIpv4FromFqdn(host); if (serverIp == 0xFFFFFFFF) { uError("failed to resolve fqdn:%s", host); exit(-1); diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 2543c81708..46068e8992 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -40,9 +40,9 @@ int32_t taosGetFqdn(char *fqdn) { return 0; } -uint32_t taosGetIpFromFqdn(const char *fqdn) { +uint32_t taosGetIpv4FromFqdn(const char *fqdn) { struct addrinfo hints = {0}; - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; struct addrinfo *result = NULL; From 25d5c9bbb33b4b5bca9ad3d66a831545dd5b73dd Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Fri, 18 Dec 2020 16:49:37 +0800 Subject: [PATCH 03/22] [TD-2464]: validate maxTablesPerVnode and reset to minTablesPerVnode --- src/common/src/tglobal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index 279a2fef04..f007a82f84 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -1443,6 +1443,12 @@ int32_t taosCheckGlobalCfg() { tsNumOfCores = 1; } + if (tsMaxTablePerVnode < tsMinTablePerVnode) { + uError("maxTablesPerVnode(%d) < minTablesPerVnode(%d), reset to minTablesPerVnode(%d)", + tsMaxTablePerVnode, tsMinTablePerVnode, tsMinTablePerVnode); + tsMaxTablePerVnode = tsMinTablePerVnode; + } + // todo refactor tsVersion = 0; for (int i = 0; i < 10; i++) { From d238b751a60d5affeaabefc8b9a27bdc5b63db77 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Fri, 18 Dec 2020 10:44:57 +0000 Subject: [PATCH 04/22] fix bug --- src/client/src/tscSQLParser.c | 54 +++++++++++++++++------------------ src/query/src/qParserImpl.c | 7 ++++- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 5d748528ac..2d608fb5f7 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -996,33 +996,6 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC return false; } - int32_t nLen = 0; - for (int32_t i = 0; i < numOfTags; ++i) { - TAOS_FIELD* p = taosArrayGet(pTagsList, i); - if (p->bytes == 0) { - invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7); - return false; - } - - nLen += p->bytes; - } - - // max tag row length must be less than TSDB_MAX_TAGS_LEN - if (nLen > TSDB_MAX_TAGS_LEN) { - invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); - return false; - } - - // field name must be unique - for (int32_t i = 0; i < numOfTags; ++i) { - TAOS_FIELD* p = taosArrayGet(pTagsList, i); - - if (has(pFieldList, 0, p->name) == true) { - invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); - return false; - } - } - /* timestamp in tag is not allowed */ for (int32_t i = 0; i < numOfTags; ++i) { TAOS_FIELD* p = taosArrayGet(pTagsList, i); @@ -1054,6 +1027,33 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC } } + int32_t nLen = 0; + for (int32_t i = 0; i < numOfTags; ++i) { + TAOS_FIELD* p = taosArrayGet(pTagsList, i); + if (p->bytes == 0) { + invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7); + return false; + } + + nLen += p->bytes; + } + + // max tag row length must be less than TSDB_MAX_TAGS_LEN + if (nLen > TSDB_MAX_TAGS_LEN) { + invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); + return false; + } + + // field name must be unique + for (int32_t i = 0; i < numOfTags; ++i) { + TAOS_FIELD* p = taosArrayGet(pTagsList, i); + + if (has(pFieldList, 0, p->name) == true) { + invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); + return false; + } + } + return true; } diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index 14fea2d5df..647e9f269e 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -384,7 +384,12 @@ void tSQLSetColumnInfo(TAOS_FIELD *pField, SStrToken *pName, TAOS_FIELD *pType) pField->name[pName->n] = 0; pField->type = pType->type; - pField->bytes = pType->bytes; + if(pField->type < TSDB_DATA_TYPE_BOOL || pField->type > TSDB_DATA_TYPE_NCHAR){ + pField->bytes = 0; + } else { + pField->bytes = pType->bytes; + } + } void tSQLSetColumnType(TAOS_FIELD *pField, SStrToken *type) { From cb32f467c8ab2f8bd23a2b2044c7a15b90f2b333 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Sat, 19 Dec 2020 16:13:39 +0800 Subject: [PATCH 05/22] TD-2270 --- src/balance/src/bnMain.c | 156 ++++++++++++------------------------ src/balance/src/bnScore.c | 2 +- src/dnode/src/dnodeVMgmt.c | 3 +- src/inc/taosmsg.h | 10 ++- src/mnode/inc/mnodeDef.h | 5 +- src/mnode/inc/mnodeDnode.h | 6 +- src/mnode/src/mnodeDb.c | 2 +- src/mnode/src/mnodeDnode.c | 38 ++++----- src/mnode/src/mnodeVgroup.c | 14 ++-- src/vnode/inc/vnodeInt.h | 3 +- src/vnode/src/vnodeCfg.c | 19 +++-- src/vnode/src/vnodeMain.c | 2 +- src/vnode/src/vnodeMgmt.c | 3 +- 13 files changed, 111 insertions(+), 152 deletions(-) diff --git a/src/balance/src/bnMain.c b/src/balance/src/bnMain.c index d80488fe9f..2532cf09a7 100644 --- a/src/balance/src/bnMain.c +++ b/src/balance/src/bnMain.c @@ -44,7 +44,7 @@ static void bnUnLock() { static bool bnCheckFree(SDnodeObj *pDnode) { if (pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) { - mError("dnode:%d, status:%s not available", pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status)); + mError("dnode:%d, status:%s not available", pDnode->dnodeId, dnodeStatus[pDnode->status]); return false; } @@ -92,13 +92,12 @@ static void bnDiscardVnode(SVgObj *pVgroup, SVnodeGid *pVnodeGid) { } static void bnSwapVnodeGid(SVnodeGid *pVnodeGid1, SVnodeGid *pVnodeGid2) { - // SVnodeGid tmp = *pVnodeGid1; - // *pVnodeGid1 = *pVnodeGid2; - // *pVnodeGid2 = tmp; + SVnodeGid tmp = *pVnodeGid1; + *pVnodeGid1 = *pVnodeGid2; + *pVnodeGid2 = tmp; } int32_t bnAllocVnodes(SVgObj *pVgroup) { - static int32_t randIndex = 0; int32_t dnode = 0; int32_t vnodes = 0; @@ -120,8 +119,7 @@ int32_t bnAllocVnodes(SVgObj *pVgroup) { break; } else { mDebug("dnode:%d, is not selected, status:%s vnodes:%d disk:%fGB role:%d", pDnode->dnodeId, - mnodeGetDnodeStatusStr(pDnode->status), pDnode->openVnodes, pDnode->diskAvailable, - pDnode->alternativeRole); + dnodeStatus[pDnode->status], pDnode->openVnodes, pDnode->diskAvailable, pDnode->alternativeRole); } } } @@ -137,7 +135,7 @@ int32_t bnAllocVnodes(SVgObj *pVgroup) { while (1) { pIter = mnodeGetNextDnode(pIter, &pDnode); if (pDnode == NULL) break; - mDebug("dnode:%d, status:%s vnodes:%d disk:%fGB role:%d", pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status), + mDebug("dnode:%d, status:%s vnodes:%d disk:%fGB role:%d", pDnode->dnodeId, dnodeStatus[pDnode->status], pDnode->openVnodes, pDnode->diskAvailable, pDnode->alternativeRole); mnodeDecDnodeRef(pDnode); } @@ -149,36 +147,6 @@ int32_t bnAllocVnodes(SVgObj *pVgroup) { } } - /* - * make the choice more random. - * replica 1: no choice - * replica 2: there are 2 combinations - * replica 3 or larger: there are 6 combinations - */ - if (pVgroup->numOfVnodes == 1) { - } else if (pVgroup->numOfVnodes == 2) { - if (randIndex++ % 2 == 0) { - bnSwapVnodeGid(pVgroup->vnodeGid, pVgroup->vnodeGid + 1); - } - } else { - int32_t randVal = randIndex++ % 6; - if (randVal == 1) { // 1, 0, 2 - bnSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 1); - } else if (randVal == 2) { // 1, 2, 0 - bnSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 1); - bnSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); - } else if (randVal == 3) { // 2, 1, 0 - bnSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 2); - } else if (randVal == 4) { // 2, 0, 1 - bnSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 2); - bnSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); - } - if (randVal == 5) { // 0, 2, 1 - bnSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); - } else { - } // 0, 1, 2 - } - bnReleaseDnodes(); bnUnLock(); return TSDB_CODE_SUCCESS; @@ -214,44 +182,8 @@ static bool bnCheckVgroupReady(SVgObj *pVgroup, SVnodeGid *pRmVnode) { static int32_t bnRemoveVnode(SVgObj *pVgroup) { if (pVgroup->numOfVnodes <= 1) return -1; - SVnodeGid *pRmVnode = NULL; - SVnodeGid *pSelVnode = NULL; - int32_t maxScore = 0; - - for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { - SVnodeGid *pVnode = &(pVgroup->vnodeGid[i]); - SDnodeObj *pDnode = mnodeGetDnode(pVnode->dnodeId); - - if (pDnode == NULL) { - mError("vgId:%d, dnode:%d not exist, remove it", pVgroup->vgId, pVnode->dnodeId); - pRmVnode = pVnode; - break; - } - - if (pDnode->status == TAOS_DN_STATUS_DROPPING) { - mDebug("vgId:%d, dnode:%d in dropping state", pVgroup->vgId, pVnode->dnodeId); - pRmVnode = pVnode; - } else if (pVnode->dnodeId == pVgroup->lbDnodeId) { - mDebug("vgId:%d, dnode:%d in updating state", pVgroup->vgId, pVnode->dnodeId); - pRmVnode = pVnode; - } else { - if (pSelVnode == NULL) { - pSelVnode = pVnode; - maxScore = pDnode->score; - } else { - if (maxScore < pDnode->score) { - pSelVnode = pVnode; - maxScore = pDnode->score; - } - } - } - - mnodeDecDnodeRef(pDnode); - } - - if (pRmVnode != NULL) { - pSelVnode = pRmVnode; - } + SVnodeGid *pSelVnode = &pVgroup->vnodeGid[pVgroup->numOfVnodes - 1]; + mDebug("vgId:%d, vnode in dnode:%d will be dropped", pVgroup->vgId, pSelVnode->dnodeId); if (!bnCheckVgroupReady(pVgroup, pSelVnode)) { mDebug("vgId:%d, is not ready", pVgroup->vgId); @@ -275,36 +207,42 @@ static bool bnCheckDnodeInVgroup(SDnodeObj *pDnode, SVgObj *pVgroup) { return false; } -/** - * desc: add vnode to vgroup, find a new one if dest dnode is null - **/ +static SDnodeObj *bnGetAvailDnode(SVgObj *pVgroup) { + for (int32_t i = 0; i < tsBnDnodes.size; ++i) { + SDnodeObj *pDnode = tsBnDnodes.list[i]; + if (bnCheckDnodeInVgroup(pDnode, pVgroup)) continue; + if (!bnCheckFree(pDnode)) continue; + + mDebug("vgId:%d, add vnode to dnode:%d", pVgroup->vgId, pDnode->dnodeId); + return pDnode; + } + + return NULL; +} + static int32_t bnAddVnode(SVgObj *pVgroup, SDnodeObj *pSrcDnode, SDnodeObj *pDestDnode) { - if (pDestDnode == NULL) { - for (int32_t i = 0; i < tsBnDnodes.size; ++i) { - SDnodeObj *pDnode = tsBnDnodes.list[i]; - if (pDnode == pSrcDnode) continue; - if (bnCheckDnodeInVgroup(pDnode, pVgroup)) continue; - if (!bnCheckFree(pDnode)) continue; - - pDestDnode = pDnode; - mDebug("vgId:%d, add vnode to dnode:%d", pVgroup->vgId, pDnode->dnodeId); + if (pDestDnode == NULL || pSrcDnode == pDestDnode) { + return TSDB_CODE_MND_DNODE_NOT_EXIST; + } + + SVnodeGid vnodeGids[TSDB_MAX_REPLICA]; + memcpy(&vnodeGids, &pVgroup->vnodeGid, sizeof(SVnodeGid) * TSDB_MAX_REPLICA); + + int32_t numOfVnodes = pVgroup->numOfVnodes; + vnodeGids[numOfVnodes].dnodeId = pDestDnode->dnodeId; + vnodeGids[numOfVnodes].pDnode = pDestDnode; + numOfVnodes++; + + for (int32_t v = 0; v < numOfVnodes; ++v) { + if (pSrcDnode != NULL && pSrcDnode->dnodeId == vnodeGids[v].dnodeId) { + bnSwapVnodeGid(&vnodeGids[v], &vnodeGids[numOfVnodes - 1]); + pVgroup->lbDnodeId = pSrcDnode->dnodeId; break; } } - if (pDestDnode == NULL) { - return TSDB_CODE_MND_DNODE_NOT_EXIST; - } - - SVnodeGid *pVnodeGid = pVgroup->vnodeGid + pVgroup->numOfVnodes; - pVnodeGid->dnodeId = pDestDnode->dnodeId; - pVnodeGid->pDnode = pDestDnode; - pVgroup->numOfVnodes++; - - if (pSrcDnode != NULL) { - pVgroup->lbDnodeId = pSrcDnode->dnodeId; - } - + memcpy(&pVgroup->vnodeGid, &vnodeGids, sizeof(SVnodeGid) * TSDB_MAX_REPLICA); + pVgroup->numOfVnodes = numOfVnodes; atomic_add_fetch_32(&pDestDnode->openVnodes, 1); mnodeUpdateVgroup(pVgroup); @@ -315,16 +253,16 @@ static int32_t bnAddVnode(SVgObj *pVgroup, SDnodeObj *pSrcDnode, SDnodeObj *pDes static bool bnMonitorBalance() { if (tsBnDnodes.size < 2) return false; + mDebug("monitor dnodes for balance, avail:%d", tsBnDnodes.size); for (int32_t src = tsBnDnodes.size - 1; src >= 0; --src) { SDnodeObj *pDnode = tsBnDnodes.list[src]; - mDebug("%d-dnode:%d, state:%s, score:%.1f, numOfCores:%d, openVnodes:%d", tsBnDnodes.size - src - 1, - pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status), pDnode->score, pDnode->numOfCores, - pDnode->openVnodes); + mDebug("%d-dnode:%d, state:%s, score:%.1f, cores:%d, vnodes:%d", tsBnDnodes.size - src - 1, pDnode->dnodeId, + dnodeStatus[pDnode->status], pDnode->score, pDnode->numOfCores, pDnode->openVnodes); } float scoresDiff = tsBnDnodes.list[tsBnDnodes.size - 1]->score - tsBnDnodes.list[0]->score; if (scoresDiff < 0.01) { - mDebug("all dnodes:%d is already balanced, scoresDiff:%f", tsBnDnodes.size, scoresDiff); + mDebug("all dnodes:%d is already balanced, scoreDiff:%.1f", tsBnDnodes.size, scoresDiff); return false; } @@ -412,7 +350,13 @@ static int32_t bnMonitorVgroups() { } else if (vgReplica < dbReplica) { mInfo("vgId:%d, replica:%d numOfVnodes:%d, try add one vnode", pVgroup->vgId, dbReplica, vgReplica); hasUpdatingVgroup = true; - code = bnAddVnode(pVgroup, NULL, NULL); + + SDnodeObj *pAvailDnode = bnGetAvailDnode(pVgroup); + if (pAvailDnode == NULL) { + code = TSDB_CODE_MND_DNODE_NOT_EXIST; + } else { + code = bnAddVnode(pVgroup, NULL, pAvailDnode); + } } mnodeDecVgroupRef(pVgroup); diff --git a/src/balance/src/bnScore.c b/src/balance/src/bnScore.c index e5ad7a2119..cbc2c62184 100644 --- a/src/balance/src/bnScore.c +++ b/src/balance/src/bnScore.c @@ -299,7 +299,7 @@ static int32_t bnRetrieveScores(SShowObj *pShow, char *data, int32_t rows, void cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_TO_VARSTR(pWrite, mnodeGetDnodeStatusStr(pDnode->status)); + STR_TO_VARSTR(pWrite, dnodeStatus[pDnode->status]); cols++; numOfRows++; diff --git a/src/dnode/src/dnodeVMgmt.c b/src/dnode/src/dnodeVMgmt.c index e3cf0820ae..4753ebc400 100644 --- a/src/dnode/src/dnodeVMgmt.c +++ b/src/dnode/src/dnodeVMgmt.c @@ -129,7 +129,8 @@ static void *dnodeProcessMgmtQueue(void *wparam) { static SCreateVnodeMsg* dnodeParseVnodeMsg(SRpcMsg *rpcMsg) { SCreateVnodeMsg *pCreate = rpcMsg->pCont; pCreate->cfg.vgId = htonl(pCreate->cfg.vgId); - pCreate->cfg.cfgVersion = htonl(pCreate->cfg.cfgVersion); + pCreate->cfg.dbCfgVersion = htonl(pCreate->cfg.dbCfgVersion); + pCreate->cfg.vgCfgVersion = htonl(pCreate->cfg.vgCfgVersion); pCreate->cfg.maxTables = htonl(pCreate->cfg.maxTables); pCreate->cfg.cacheBlockSize = htonl(pCreate->cfg.cacheBlockSize); pCreate->cfg.totalBlocks = htonl(pCreate->cfg.totalBlocks); diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index b7f0de54fe..2df243eb3e 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -518,14 +518,15 @@ typedef struct SRetrieveTableRsp { typedef struct { int32_t vgId; - int32_t cfgVersion; + int32_t dbCfgVersion; int64_t totalStorage; int64_t compStorage; int64_t pointsWritten; uint8_t status; uint8_t role; uint8_t replica; - uint8_t reserved[5]; + uint8_t reserved; + int32_t vgCfgVersion; } SVnodeLoad; typedef struct { @@ -641,7 +642,7 @@ typedef struct { typedef struct { uint32_t vgId; - int32_t cfgVersion; + int32_t dbCfgVersion; int32_t maxTables; int32_t cacheBlockSize; int32_t totalBlocks; @@ -660,7 +661,8 @@ typedef struct { int8_t wals; int8_t quorum; int8_t update; - int8_t reserved[15]; + int8_t reserved[11]; + int32_t vgCfgVersion; } SVnodeCfg; typedef struct { diff --git a/src/mnode/inc/mnodeDef.h b/src/mnode/inc/mnodeDef.h index 6d3061c426..583acc19b4 100644 --- a/src/mnode/inc/mnodeDef.h +++ b/src/mnode/inc/mnodeDef.h @@ -144,7 +144,8 @@ typedef struct SVgObj { int8_t status; int8_t reserved0[4]; SVnodeGid vnodeGid[TSDB_MAX_REPLICA]; - int8_t reserved1[12]; + int32_t vgCfgVersion; + int8_t reserved1[8]; int8_t updateEnd[4]; int32_t refCount; int32_t numOfTables; @@ -181,7 +182,7 @@ typedef struct SDbObj { int8_t reserved0[4]; char acct[TSDB_USER_LEN]; int64_t createdTime; - int32_t cfgVersion; + int32_t dbCfgVersion; SDbCfg cfg; int8_t status; int8_t reserved1[11]; diff --git a/src/mnode/inc/mnodeDnode.h b/src/mnode/inc/mnodeDnode.h index 8bc29ef9ef..b959da73e8 100644 --- a/src/mnode/inc/mnodeDnode.h +++ b/src/mnode/inc/mnodeDnode.h @@ -55,12 +55,12 @@ typedef enum EDnodeOfflineReason { TAOS_DN_OFF_OTHERS } EDnodeOfflineReason; +extern char* dnodeStatus[]; +extern char* dnodeRoles[]; + int32_t mnodeInitDnodes(); void mnodeCleanupDnodes(); -char* mnodeGetDnodeStatusStr(int32_t dnodeStatus); -void mgmtMonitorDnodeModule(); - int32_t mnodeGetDnodesNum(); int32_t mnodeGetOnlinDnodesCpuCoreNum(); int32_t mnodeGetOnlineDnodesNum(); diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index 25dbb10536..0eb9828959 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -1015,7 +1015,7 @@ static int32_t mnodeAlterDb(SDbObj *pDb, SAlterDbMsg *pAlter, void *pMsg) { if (memcmp(&newCfg, &pDb->cfg, sizeof(SDbCfg)) != 0) { pDb->cfg = newCfg; - pDb->cfgVersion++; + pDb->dbCfgVersion++; SSdbRow row = { .type = SDB_OPER_GLOBAL, .pTable = tsDbSdb, diff --git a/src/mnode/src/mnodeDnode.c b/src/mnode/src/mnodeDnode.c index 745fbf2d98..27588669eb 100644 --- a/src/mnode/src/mnodeDnode.c +++ b/src/mnode/src/mnodeDnode.c @@ -63,7 +63,6 @@ static int32_t mnodeGetVnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC static int32_t mnodeRetrieveVnodes(SShowObj *pShow, char *data, int32_t rows, void *pConn); static int32_t mnodeGetDnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); static int32_t mnodeRetrieveDnodes(SShowObj *pShow, char *data, int32_t rows, void *pConn); -static char* mnodeGetDnodeAlternativeRoleStr(int32_t alternativeRole); static void mnodeUpdateDnodeEps(); static char* offlineReason[] = { @@ -557,7 +556,8 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) { for (int32_t j = 0; j < openVnodes; ++j) { SVnodeLoad *pVload = &pStatus->load[j]; pVload->vgId = htonl(pVload->vgId); - pVload->cfgVersion = htonl(pVload->cfgVersion); + pVload->dbCfgVersion = htonl(pVload->dbCfgVersion); + pVload->vgCfgVersion = htonl(pVload->vgCfgVersion); SVgObj *pVgroup = mnodeGetVgroup(pVload->vgId); if (pVgroup == NULL) { @@ -833,12 +833,12 @@ static int32_t mnodeRetrieveDnodes(SShowObj *pShow, char *data, int32_t rows, vo cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - char* status = mnodeGetDnodeStatusStr(pDnode->status); + char* status = dnodeStatus[pDnode->status]; STR_TO_VARSTR(pWrite, status); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - char* role = mnodeGetDnodeAlternativeRoleStr(pDnode->alternativeRole); + char* role = dnodeRoles[pDnode->alternativeRole]; STR_TO_VARSTR(pWrite, role); cols++; @@ -1154,21 +1154,17 @@ static int32_t mnodeRetrieveVnodes(SShowObj *pShow, char *data, int32_t rows, vo return numOfRows; } -char* mnodeGetDnodeStatusStr(int32_t dnodeStatus) { - switch (dnodeStatus) { - case TAOS_DN_STATUS_OFFLINE: return "offline"; - case TAOS_DN_STATUS_DROPPING: return "dropping"; - case TAOS_DN_STATUS_BALANCING: return "balancing"; - case TAOS_DN_STATUS_READY: return "ready"; - default: return "undefined"; - } -} +char* dnodeStatus[] = { + "offline", + "dropping", + "balancing", + "ready", + "undefined" +}; -static char* mnodeGetDnodeAlternativeRoleStr(int32_t alternativeRole) { - switch (alternativeRole) { - case TAOS_DN_ALTERNATIVE_ROLE_ANY: return "any"; - case TAOS_DN_ALTERNATIVE_ROLE_MNODE: return "mnode"; - case TAOS_DN_ALTERNATIVE_ROLE_VNODE: return "vnode"; - default:return "any"; - } -} +char* dnodeRoles[] = { + "any", + "mnode", + "vnode", + "any" +}; diff --git a/src/mnode/src/mnodeVgroup.c b/src/mnode/src/mnodeVgroup.c index eec559600f..8e9bf97496 100644 --- a/src/mnode/src/mnodeVgroup.c +++ b/src/mnode/src/mnodeVgroup.c @@ -256,6 +256,8 @@ SVgObj *mnodeGetVgroup(int32_t vgId) { } void mnodeUpdateVgroup(SVgObj *pVgroup) { + pVgroup->vgCfgVersion++; + SSdbRow row = { .type = SDB_OPER_GLOBAL, .pTable = tsVgroupSdb, @@ -339,10 +341,11 @@ void mnodeUpdateVgroupStatus(SVgObj *pVgroup, SDnodeObj *pDnode, SVnodeLoad *pVl pVgroup->pointsWritten = htobe64(pVload->pointsWritten); } - if (pVload->cfgVersion != pVgroup->pDb->cfgVersion || pVload->replica != pVgroup->numOfVnodes) { - mError("dnode:%d, vgId:%d, vnode cfgVersion:%d repica:%d not match with mnode cfgVersion:%d replica:%d", - pDnode->dnodeId, pVload->vgId, pVload->cfgVersion, pVload->replica, pVgroup->pDb->cfgVersion, - pVgroup->numOfVnodes); + if (pVload->dbCfgVersion != pVgroup->pDb->dbCfgVersion || pVload->replica != pVgroup->numOfVnodes || + pVload->vgCfgVersion != pVgroup->vgCfgVersion) { + mError("dnode:%d, vgId:%d, vnode cfgVersion:%d:%d repica:%d not match with mnode cfgVersion:%d:%d replica:%d", + pDnode->dnodeId, pVload->vgId, pVload->dbCfgVersion, pVload->vgCfgVersion, pVload->replica, + pVgroup->pDb->dbCfgVersion, pVgroup->vgCfgVersion, pVgroup->numOfVnodes); mnodeSendAlterVgroupMsg(pVgroup); } } @@ -840,7 +843,8 @@ static SCreateVnodeMsg *mnodeBuildVnodeMsg(SVgObj *pVgroup) { SVnodeCfg *pCfg = &pVnode->cfg; pCfg->vgId = htonl(pVgroup->vgId); - pCfg->cfgVersion = htonl(pDb->cfgVersion); + pCfg->dbCfgVersion = htonl(pDb->dbCfgVersion); + pCfg->vgCfgVersion = htonl(pVgroup->vgCfgVersion); pCfg->cacheBlockSize = htonl(pDb->cfg.cacheBlockSize); pCfg->totalBlocks = htonl(pDb->cfg.totalBlocks); pCfg->maxTables = htonl(maxTables + 1); diff --git a/src/vnode/inc/vnodeInt.h b/src/vnode/inc/vnodeInt.h index b28eb690fe..fb1868ab13 100644 --- a/src/vnode/inc/vnodeInt.h +++ b/src/vnode/inc/vnodeInt.h @@ -56,7 +56,8 @@ typedef struct { int64_t sync; void * events; void * cq; // continuous query - int32_t cfgVersion; + int32_t dbCfgVersion; + int32_t vgCfgVersion; STsdbCfg tsdbCfg; SSyncCfg syncCfg; SWalCfg walCfg; diff --git a/src/vnode/src/vnodeCfg.c b/src/vnode/src/vnodeCfg.c index e0881db000..aff7315d28 100644 --- a/src/vnode/src/vnodeCfg.c +++ b/src/vnode/src/vnodeCfg.c @@ -22,7 +22,8 @@ static void vnodeLoadCfg(SVnodeObj *pVnode, SCreateVnodeMsg* vnodeMsg) { tstrncpy(pVnode->db, vnodeMsg->db, sizeof(pVnode->db)); - pVnode->cfgVersion = vnodeMsg->cfg.cfgVersion; + pVnode->dbCfgVersion = vnodeMsg->cfg.dbCfgVersion; + pVnode->vgCfgVersion = vnodeMsg->cfg.vgCfgVersion; pVnode->tsdbCfg.cacheBlockSize = vnodeMsg->cfg.cacheBlockSize; pVnode->tsdbCfg.totalBlocks = vnodeMsg->cfg.totalBlocks; pVnode->tsdbCfg.daysPerFile = vnodeMsg->cfg.daysPerFile; @@ -95,12 +96,19 @@ int32_t vnodeReadCfg(SVnodeObj *pVnode) { } tstrncpy(vnodeMsg.db, db->valuestring, sizeof(vnodeMsg.db)); - cJSON *cfgVersion = cJSON_GetObjectItem(root, "cfgVersion"); - if (!cfgVersion || cfgVersion->type != cJSON_Number) { + cJSON *dbCfgVersion = cJSON_GetObjectItem(root, "cfgVersion"); + if (!dbCfgVersion || dbCfgVersion->type != cJSON_Number) { vError("vgId:%d, failed to read %s, cfgVersion not found", pVnode->vgId, file); goto PARSE_VCFG_ERROR; } - vnodeMsg.cfg.cfgVersion = cfgVersion->valueint; + vnodeMsg.cfg.dbCfgVersion = dbCfgVersion->valueint; + + cJSON *vgCfgVersion = cJSON_GetObjectItem(root, "vgCfgVersion"); + if (!vgCfgVersion || vgCfgVersion->type != cJSON_Number) { + vError("vgId:%d, failed to read %s, vgCfgVersion not found", pVnode->vgId, file); + goto PARSE_VCFG_ERROR; + } + vnodeMsg.cfg.vgCfgVersion = vgCfgVersion->valueint; cJSON *cacheBlockSize = cJSON_GetObjectItem(root, "cacheBlockSize"); if (!cacheBlockSize || cacheBlockSize->type != cJSON_Number) { @@ -278,7 +286,8 @@ int32_t vnodeWriteCfg(SCreateVnodeMsg *pMsg) { len += snprintf(content + len, maxLen - len, "{\n"); len += snprintf(content + len, maxLen - len, " \"db\": \"%s\",\n", pMsg->db); - len += snprintf(content + len, maxLen - len, " \"cfgVersion\": %d,\n", pMsg->cfg.cfgVersion); + len += snprintf(content + len, maxLen - len, " \"cfgVersion\": %d,\n", pMsg->cfg.dbCfgVersion); + len += snprintf(content + len, maxLen - len, " \"vgCfgVersion\": %d,\n", pMsg->cfg.vgCfgVersion); len += snprintf(content + len, maxLen - len, " \"cacheBlockSize\": %d,\n", pMsg->cfg.cacheBlockSize); len += snprintf(content + len, maxLen - len, " \"totalBlocks\": %d,\n", pMsg->cfg.totalBlocks); len += snprintf(content + len, maxLen - len, " \"daysPerFile\": %d,\n", pMsg->cfg.daysPerFile); diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index d7e33deb15..b1815e959d 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -154,7 +154,7 @@ int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) { SVnodeObj *pVnode = vparam; // vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS - // cfgVersion can be corrected by status msg + // dbCfgVersion can be corrected by status msg if (!vnodeSetUpdatingStatus(pVnode)) { vDebug("vgId:%d, vnode is not ready, do alter operation later", pVnode->vgId); return TSDB_CODE_SUCCESS; diff --git a/src/vnode/src/vnodeMgmt.c b/src/vnode/src/vnodeMgmt.c index cf42690d7d..ee5aa5ca90 100644 --- a/src/vnode/src/vnodeMgmt.c +++ b/src/vnode/src/vnodeMgmt.c @@ -134,7 +134,8 @@ static void vnodeBuildVloadMsg(SVnodeObj *pVnode, SStatusMsg *pStatus) { SVnodeLoad *pLoad = &pStatus->load[pStatus->openVnodes++]; pLoad->vgId = htonl(pVnode->vgId); - pLoad->cfgVersion = htonl(pVnode->cfgVersion); + pLoad->dbCfgVersion = htonl(pVnode->dbCfgVersion); + pLoad->vgCfgVersion = htonl(pVnode->vgCfgVersion); pLoad->totalStorage = htobe64(totalStorage); pLoad->compStorage = htobe64(compStorage); pLoad->pointsWritten = htobe64(pointsWritten); From e948fcf46ed56196ea8e9b95e1fec7dcc5efa7b6 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 13:16:30 +0800 Subject: [PATCH 06/22] [TD-2522] fix: fix some typo in taos.cfg --- packaging/cfg/taos.cfg | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index 8c2ef19382..73fa915abd 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -39,10 +39,10 @@ # number of management nodes in the system # numOfMnodes 3 -# enable/disable backuping vnode directory when removing dnode +# enable/disable backuping vnode directory when removing vnode # vnodeBak 1 -# if report installation / use information +# enable/disable installation / usage report # telemetryReporting 1 # enable/disable load balancing @@ -81,7 +81,7 @@ # minimum time window, milli-second # minIntervalTime 10 -# maximum delay before launching a stream compution, milli-second +# maximum delay before launching a stream computation, milli-second # maxStreamCompDelay 20000 # maximum delay before launching a stream computation for the first time, milli-second @@ -156,7 +156,7 @@ # max number of connections allowed in dnode # maxShellConns 5000 -# max numerber of connections allowed in client +# max number of connections allowed in client # maxConnections 5000 # stop writing logs when the disk size of the log folder is less than this value @@ -187,7 +187,7 @@ # restfulRowLimit 10240 # The following parameter is used to limit the maximum number of lines in log files. -# max number of rows per log filters +# max number of lines per log filters # numOfLogLines 10000000 # enable/disable async log @@ -199,7 +199,9 @@ # The following parameters are used for debug purpose only. # debugFlag 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR -# 131: output warning and error, 135: output debug, warning and error, 143 : output trace, debug, warning and error to log. +# 131: output warning and error +# 135: output debug, warning and error +# 143: output trace, debug, warning and error to log # 199: output debug, warning and error to both screen and file # 207: output trace, debug, warning and error to both screen and file @@ -231,10 +233,10 @@ # cDebugFlag 131 # debug flag for JNI -# jniDebugflag 131 +# jniDebugFlag 131 # debug flag for storage -# uDebugflag 131 +# uDebugFlag 131 # debug flag for http server # httpDebugFlag 131 @@ -243,12 +245,12 @@ # monDebugFlag 131 # debug flag for query -# qDebugflag 131 +# qDebugFlag 131 # debug flag for vnode -# vDebugflag 131 +# vDebugFlag 131 -# debug flag for http server +# debug flag for TSDB # tsdbDebugFlag 131 # debug flag for continue query From 2b81e6d2cafb629ce1c66c6a5e9551338be4922a Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Tue, 22 Dec 2020 08:29:04 +0000 Subject: [PATCH 07/22] [TD-2528]: messy characters in alert msgs --- alert/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alert/go.mod b/alert/go.mod index 01c557d564..43920f1f1a 100644 --- a/alert/go.mod +++ b/alert/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( github.com/jmoiron/sqlx v1.2.0 github.com/mattn/go-sqlite3 v2.0.3+incompatible - github.com/taosdata/driver-go v0.0.0-20200727182616-1a3b1941c206 + github.com/taosdata/driver-go v0.0.0-20201113094317-050667e5b4d0 go.uber.org/zap v1.14.1 google.golang.org/appengine v1.6.5 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c From 9c6c29397e808a9377c42c759ed92d297280bba7 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 19:27:08 +0800 Subject: [PATCH 08/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for faq-ch --- .../webdocs/markdowndocs/faq-ch.md | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/faq-ch.md b/documentation20/webdocs/markdowndocs/faq-ch.md index d89cdd4c92..a085e6159a 100644 --- a/documentation20/webdocs/markdowndocs/faq-ch.md +++ b/documentation20/webdocs/markdowndocs/faq-ch.md @@ -27,43 +27,40 @@ * 云服务器:检查云服务器的安全组是否打开TCP/UDP 端口6030-6042的访问权限 * 本地虚拟机:检查网络能否ping通,尽量避免使用`localhost` 作为hostname * 公司服务器:如果为NAT网络环境,请务必检查服务器能否将消息返回值客户端 - + 2. 确保客户端与服务端版本号是完全一致的,开源社区版和企业版也不能混用 3. 在服务器,执行 `systemctl status taosd` 检查*taosd*运行状态。如果没有运行,启动*taosd* -4. 确认客户端连接时指定了正确的服务器FQDN (Fully Qualified Domain Name(可在服务器上执行Linux命令hostname -f获得)),FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 +4. 确认客户端连接时指定了正确的服务器FQDN (Fully Qualified Domain Name(可在服务器上执行Linux命令hostname -f获得)),FQDN配置参考:一篇文章说清楚TDengine的FQDN。 5. ping服务器FQDN,如果没有反应,请检查你的网络,DNS设置,或客户端所在计算机的系统hosts文件 6. 检查防火墙设置(Ubuntu 使用 ufw status,CentOS 使用 firewall-cmd --list-port),确认TCP/UDP 端口6030-6042 是打开的 -7. 对于Linux上的JDBC(ODBC, Python, Go等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里 +7. 对于Linux上的JDBC(ODBC, Python, Go等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里 8. 对于windows上的JDBC, ODBC, Python, Go等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 *C:\Windows\System32*) 9. 如果仍不能排除连接故障 - + * Linux 系统请使用命令行工具nc来分别判断指定端口的TCP和UDP连接是否通畅 检查UDP端口连接是否工作:`nc -vuz {hostIP} {port} ` 检查服务器侧TCP端口连接是否工作:`nc -l {port}` 检查客户端侧TCP端口连接是否工作:`nc {hostIP} {port}` - + * Windows 系统请使用 PowerShell 命令 Net-TestConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问 - -10. 也可以使用taos程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括TCP和UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)。 - +10. 也可以使用taos程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括TCP和UDP):TDengine 内嵌网络检测工具使用指南。 ## 6. 遇到错误“Unexpected generic error in RPC”或者"TDengine Error: Unable to resolve FQDN", 我怎么办? 产生这个错误,是由于客户端或数据节点无法解析FQDN(Fully Qualified Domain Name)导致。对于TAOS Shell或客户端应用,请做如下检查: -1. 请检查连接的服务器的FQDN是否正确,FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 +1. 请检查连接的服务器的FQDN是否正确,FQDN配置参考:一篇文章说清楚TDengine的FQDN。 2. 如果网络配置有DNS server, 请检查是否正常工作 3. 如果网络没有配置DNS server, 请检查客户端所在机器的hosts文件,查看该FQDN是否配置,并是否有正确的IP地址。 4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法连接服务器的 - ## 7. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误 如果你确认语法正确,2.0之前版本,请检查SQL语句长度是否超过64K。如果超过,也会返回这个错误。 @@ -86,7 +83,7 @@ TDengine还没有一组专用的validation queries。然而建议你使用系统 ## 11. 最有效的写入数据的方法是什么?windows系统下插入的nchar类数据中的汉字被解析成了乱码如何解决? -windows下插入nchar类的数据中如果有中文,请先确认系统的地区设置成了中国(在Control Panel里可以设置),这时cmd中的`taos`客户端应该已经可以正常工作了;如果是在IDE里开发Java应用,比如Eclipse, Intellij,请确认IDE里的文件编码为GBK(这是Java默认的编码类型),然后在生成Connection时,初始化客户端的配置,具体语句如下: +Windows下插入nchar类的数据中如果有中文,请先确认系统的地区设置成了中国(在Control Panel里可以设置),这时cmd中的`taos`客户端应该已经可以正常工作了;如果是在IDE里开发Java应用,比如Eclipse, Intellij,请确认IDE里的文件编码为GBK(这是Java默认的编码类型),然后在生成Connection时,初始化客户端的配置,具体语句如下: ```JAVA Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties properties = new Properties(); @@ -94,7 +91,7 @@ properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8"); Connection = DriverManager.getConnection(url, properties); ``` ## 12.TDengine GO windows驱动的如何编译? -请看为此问题撰写的技术博客 +请看为此问题撰写的技术博客 ## 13.JDBC报错: the excuted SQL is not a DML or a DDL? 请更新至最新的JDBC驱动 @@ -105,18 +102,14 @@ Connection = DriverManager.getConnection(url, properties); 2.0.4 ``` -## 14. taos connect failed, reason: invalid timestamp +## 14. taos connect failed, reason: invalid timestamp 常见原因是服务器和客户端时间没有校准,可以通过和时间服务器同步的方式(Linux 下使用 ntpdate 命令,Windows 在系统时间设置中选择自动同步)校准。 - - ## 15. 表名显示不全 由于 taos shell 在终端中显示宽度有限,有可能比较长的表名显示不全,如果按照显示的不全的表名进行相关操作会发生 Table does not exist 错误。解决方法可以是通过修改 taos.cfg 文件中的设置项 maxBinaryDisplayWidth, 或者直接输入命令 set max_binary_display_width 100。或者在命令结尾使用 \G 参数来调整结果的显示方式。 - - ## 16. 如何进行数据迁移? TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A移动机器B时,注意如下两件事: @@ -125,13 +118,11 @@ TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A - 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。 - 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。 - - ## 17. 怎么报告问题? -如果 FAQ 中的信息不能够帮到您,需要 TDengine 技术团队的技术支持与协助,请将以下两个目录中内容打包: +如果 FAQ 中的信息不能够帮到您,需要 TDengine 技术团队的技术支持与协助,请将以下两个目录中内容打包: 1. /var/log/taos -2. /etc/taos +2. /etc/taos 附上必要的问题描述,以及发生该问题的执行操作,出现问题的表征及大概的时间,在 GitHub提交Issue。 From 77f1e67b1104a9054fe1867b338a20369b987048 Mon Sep 17 00:00:00 2001 From: liuyq-617 Date: Tue, 22 Dec 2020 19:28:18 +0800 Subject: [PATCH 09/22] fix script errors --- tests/test-all.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test-all.sh b/tests/test-all.sh index 0affe5edf4..58ca4d73d6 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -33,7 +33,9 @@ function runSimCaseOneByOnefq { start_time=`date +%s` ./test.sh -f $case > /dev/null 2>&1 && \ echo -e "${GREEN}$case success${NC}" | tee -a out.log || \ - echo -e "${RED}$case failed${NC}" | tee -a out.log + grep 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log || echo -e "${RED}$case failed${NC}" | tee -a out.log + + out_log=`tail -1 out.log ` if [[ $out_log =~ 'failed' ]];then exit 8 From 82a7049afeb349c8a5c11a9e02d415fa98d4377c Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 19:35:03 +0800 Subject: [PATCH 10/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for replica-ch --- .../webdocs/markdowndocs/replica-ch.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/replica-ch.md b/documentation20/webdocs/markdowndocs/replica-ch.md index 1d80174455..4d714fb550 100644 --- a/documentation20/webdocs/markdowndocs/replica-ch.md +++ b/documentation20/webdocs/markdowndocs/replica-ch.md @@ -30,7 +30,7 @@ TDengine里存在vnode, mnode, vnode用来存储时序数据,mnode用来存储 - master: 具有最新的数据,容许客户端往里写入数据,一个虚拟节点组,至多一个master. - slave:与master是同步的,但不容许客户端往里写入数据,根据配置,可以容许客户端对其进行查询。 -- unsynced: 节点处于非同步状态,比如虚拟节点刚启动、或与其他虚拟节点的连接出现故障等。处于该状态时,该虚拟节点既不能提供写入,也不能提供查询服务 +- unsynced: 节点处于非同步状态,比如虚拟节点刚启动、或与其他虚拟节点的连接出现故障等。处于该状态时,该虚拟节点既不能提供写入,也不能提供查询服务。 - offline: 由于宕机或网络原因,无法访问到某虚拟节点时,其他虚拟节点将该虚拟节点标为离线。但请注意,该虚拟节点本身的状态可能是unsynced或其他,但不会是离线。 **Quorum:** @@ -83,10 +83,10 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性 如果一个虚拟节点(vnode A)检测到与同一虚拟节点组内另外一虚拟节点(vnode B)的连接中断,vnode A将立即把vnode B的role设置为offline。无论是接收到另外一虚拟节点发来的status消息,还是检测与另外一虚拟节点的连接中断,该虚拟节点都将进入状态处理流程。状态处理流程的规则如下: 1. 如果检测到在线的节点数没有超过一半,则将自己的状态设置为unsynced. -2. 如果在线的虚拟节点数超过一半,会检查master节点是否存在,如果存在,则会决定是否将自己状态改为slave或启动数据恢复流程 +2. 如果在线的虚拟节点数超过一半,会检查master节点是否存在,如果存在,则会决定是否将自己状态改为slave或启动数据恢复流程。 3. 如果master不存在,则会检查自己保存的各虚拟节点的状态信息与从另一节点接收到的是否一致,如果一致,说明节点组里状态已经稳定一致,则会触发选举流程。如果不一致,说明状态还没趋于一致,即使master不存在,也不进行选主。由于要求状态信息一致才进行选举,每个虚拟节点根据同样的信息,会选出同一个虚拟节点做master,无需投票表决。 4. 自己的状态是根据规则自己决定并修改的,并不需要其他节点同意,包括成为master。一个节点无权修改其他节点的状态。 -5. 如果一个虚拟节点检测到自己或其他虚拟节点的role发生改变,该节点会广播它自己保存的各个虚拟节点的状态信息(role和version). +5. 如果一个虚拟节点检测到自己或其他虚拟节点的role发生改变,该节点会广播它自己保存的各个虚拟节点的状态信息(role和version)。 具体的流程图如下: @@ -124,7 +124,7 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性 如果一虚拟节点(vnode B) 处于unsynced状态,master存在(vnode A),而且其版本号比master的低,它将立即启动数据恢复流程。在理解恢复流程时,需要澄清几个关于文件的概念和处理规则。 -1. 每个文件(无论是archived data的file还是wal)都有一个index, 这需要应用来维护(vnode里,该index就是fileId*3 + 0/1/2, 对应data, head与last三个文件)。如果index为0,表示系统里最老的数据文件。对于mnode里的文件,数量是固定的,对应于acct, user, db, table等文件。 +1. 每个文件(无论是archived data的file还是wal)都有一个index, 这需要应用来维护(vnode里,该index就是fileId*3 + 0/1/2, 对应data, head与last三个文件)。如果index为0,表示系统里最老的数据文件。对于mode里的文件,数量是固定的,对应于acct, user, db, table等文件。 2. 任何一个数据文件(file)有名字、大小,还有一个magic number。只有文件名、大小与magic number一致时,两个文件才判断是一样的,无需同步。Magic number可以是checksum, 也可以是简单的文件大小。怎么计算magic,换句话说,如何检测数据文件是否有效,完全由应用决定。 3. 文件名的处理有点复杂,因为每台服务器的路径可能不一致。比如node A的TDengine的数据文件存放在 /etc/taos目录下,而node B的数据存放在 /home/jhtao目录下。因此同步模块需要应用在启动一个同步实例时提供一个path,这样两台服务器的绝对路径可以不一样,但仍然可以做对比,做同步。 4. 当sync模块调用回调函数getFileInfo获得数据文件信息时,有如下的规则 @@ -212,10 +212,10 @@ Arbitrator的程序tarbitrator.c在复制模块的同一目录, 编译整个系 相同之处: -- 三大流程一致:Raft里有Leader election, replication, safety,完全对应TDengine的选举、数据转发、数据恢复三个流程 -- 节点状态定义一致:Raft里每个节点有Leader, Follower, Candidate三个状态,TDengine里是Master, Slave, Unsynced, Offline。多了一个offlince, 但本质上是一样的,因为offline是外界看一个节点的状态,但该节点本身是处于master, slave 或unsynced的 +- 三大流程一致:Raft里有Leader election, replication, safety,完全对应TDengine的选举、数据转发、数据恢复三个流程。 +- 节点状态定义一致:Raft里每个节点有Leader, Follower, Candidate三个状态,TDengine里是Master, Slave, Unsynced, Offline。多了一个offlince, 但本质上是一样的,因为offline是外界看一个节点的状态,但该节点本身是处于master, slave 或unsynced的。 - 数据转发流程完全一样,Master(leader)需要等待回复确认。 -- 数据恢复流程几乎一样,Raft没有涉及历史数据同步问题,只考虑了WAL数据同步 +- 数据恢复流程几乎一样,Raft没有涉及历史数据同步问题,只考虑了WAL数据同步。 不同之处: @@ -226,7 +226,7 @@ Arbitrator的程序tarbitrator.c在复制模块的同一目录, 编译整个系 ## Meta Data的数据复制 -TDengine里存在时序数据,也存在Meta Data。Meta Data对数据的可靠性要求更高,那么TDengine设计能否满足要求呢?下面做个仔细分析 +TDengine里存在时序数据,也存在Meta Data。Meta Data对数据的可靠性要求更高,那么TDengine设计能否满足要求呢?下面做个仔细分析。 TDengine里Meta Data包括以下: From a8e9928f6669033dd17ddd326b415b08209b5d60 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 19:40:21 +0800 Subject: [PATCH 11/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for Super Table-ch --- documentation20/webdocs/markdowndocs/Super Table-ch.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/Super Table-ch.md b/documentation20/webdocs/markdowndocs/Super Table-ch.md index 96e7104ab7..e5c7747157 100644 --- a/documentation20/webdocs/markdowndocs/Super Table-ch.md +++ b/documentation20/webdocs/markdowndocs/Super Table-ch.md @@ -161,7 +161,7 @@ SELECT function,… 超级表聚合查询,TDengine目前支持以下聚合\选择函数:sum、count、avg、first、last、min、max、top、bottom,以及针对全部或部分列的投影操作,使用方式与单表查询的计算过程相同。暂不支持其他类型的聚合计算和四则运算。当前所有的函数及计算过程均不支持嵌套的方式进行执行。 - 不使用GROUP BY的查询将会对超级表下所有满足筛选条件的表按时间进行聚合,结果输出默认是按照时间戳单调递增输出,用户可以使用ORDER BY _c0 ASC|DESC选择查询结果时间戳的升降排序;使用GROUP BY 的聚合查询会按照tags进行分组,并对每个组内的数据分别进行聚合,输出结果为各个组的聚合结果,组间的排序可以由ORDER BY 语句指定,每个分组内部,时间序列是单调递增的。 + 不使用GROUP BY的查询将会对超级表下所有满足筛选条件的表按时间进行聚合,结果输出默认是按照时间戳单调递增输出,用户可以使用ORDER BY _c0 ASC|DESC选择查询结果时间戳的升降排序;使用GROUP BY 的聚合查询会按照tags进行分组,并对每个组内的数据分别进行聚合,输出结果为各个组的聚合结果,组间的排序可以由ORDER BY 语句指定,每个分组内部,时间序列是单调递增的。 使用SLIMIT/SOFFSET语句指定组间分页,即指定结果集中输出的最大组数以及对组起始的位置。使用LIMIT/OFFSET语句指定组内分页,即指定结果集中每个组内最多输出多少条记录以及记录起始的位置。 @@ -178,7 +178,7 @@ CREATE TABLE thermometer (ts timestamp, degree double) TAGS(location binary(20), type int) ``` -假设有北京,天津和上海三个地区的采集器共4个,温度采集器有3种类型,我们就可以对每个采集器建表如下: +假设有北京,天津和上海三个地区的采集器共4个,温度采集器有3种类型,我们就可以对每个采集器建表如下: ```mysql CREATE TABLE therm1 USING thermometer TAGS (’beijing’, 1); From 4d81abf09cc561a805e775574e485cdb58233c91 Mon Sep 17 00:00:00 2001 From: liuyq-617 Date: Tue, 22 Dec 2020 19:43:11 +0800 Subject: [PATCH 12/22] fix script errors --- tests/test-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-all.sh b/tests/test-all.sh index 58ca4d73d6..e818f893b3 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -33,7 +33,7 @@ function runSimCaseOneByOnefq { start_time=`date +%s` ./test.sh -f $case > /dev/null 2>&1 && \ echo -e "${GREEN}$case success${NC}" | tee -a out.log || \ - grep 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log || echo -e "${RED}$case failed${NC}" | tee -a out.log + ( grep 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log ) || echo -e "${RED}$case failed${NC}" | tee -a out.log out_log=`tail -1 out.log ` From 13028794a6d4378d60e290bee7e1e883895d9969 Mon Sep 17 00:00:00 2001 From: liuyq-617 Date: Tue, 22 Dec 2020 19:44:38 +0800 Subject: [PATCH 13/22] fix script error --- tests/test-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-all.sh b/tests/test-all.sh index e818f893b3..4448c8a2a4 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -33,7 +33,7 @@ function runSimCaseOneByOnefq { start_time=`date +%s` ./test.sh -f $case > /dev/null 2>&1 && \ echo -e "${GREEN}$case success${NC}" | tee -a out.log || \ - ( grep 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log ) || echo -e "${RED}$case failed${NC}" | tee -a out.log + ( grep 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log ) || echo -e "${RED}$case failed${NC}" | tee -a out.log out_log=`tail -1 out.log ` From 3c95dc62d912eed5f2d923253623d040fc071eec Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 20:04:25 +0800 Subject: [PATCH 14/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for insert-ch --- .../webdocs/markdowndocs/insert-ch.md | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/insert-ch.md b/documentation20/webdocs/markdowndocs/insert-ch.md index 96e7a4613b..3fa48c1f50 100644 --- a/documentation20/webdocs/markdowndocs/insert-ch.md +++ b/documentation20/webdocs/markdowndocs/insert-ch.md @@ -28,10 +28,10 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, - 写入的数据的时间戳必须大于当前时间减去配置参数keep的时间。如果keep配置为3650天,那么无法写入比3650天还老的数据。写入数据的时间戳也不能大于当前时间加配置参数days。如果days配置为2,那么无法写入比当前时间还晚2天的数据。 ## Prometheus直接写入 -[Prometheus](https://www.prometheus.io/)作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具[Bailongma](https://github.com/taosdata/Bailongma),只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文[用Docker容器快速搭建一个Devops监控Demo](https://www.taosdata.com/blog/2020/02/03/1189.html)即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。 +Prometheus作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具Bailongma,只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文用Docker容器快速搭建一个Devops监控Demo即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。 ### 从源代码编译blm_prometheus -用户需要从github下载[Bailongma](https://github.com/taosdata/Bailongma)的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件: +用户需要从github下载Bailongma的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件: - Linux操作系统的服务器 - 安装好Golang, 1.10版本以上 - 对应的TDengine版本。因为用到了TDengine的客户端动态链接库,因此需要安装好和服务端相同版本的TDengine程序;比如服务端版本是TDengine 2.0.0, 则在bailongma所在的linux服务器(可以与TDengine在同一台服务器,或者不同服务器) @@ -45,10 +45,10 @@ go build 一切正常的情况下,就会在对应的目录下生成一个blm_prometheus的可执行程序。 ### 安装Prometheus -通过Prometheus的官网下载安装。[下载地址](https://prometheus.io/download/) +通过Prometheus的官网下载安装。下载地址 ### 配置Prometheus -参考Prometheus的[配置文档](https://prometheus.io/docs/prometheus/latest/configuration/configuration/),在Prometheus的配置文件中的部分,增加以下配置 +参考Prometheus的配置文档,在Prometheus的配置文件中的部分,增加以下配置 - url: bailongma API服务提供的URL, 参考下面的blm_prometheus启动示例章节 @@ -60,7 +60,7 @@ blm_prometheus程序有以下选项,在启动blm_prometheus程序时可以通 --tdengine-name 如果TDengine安装在一台具备域名的服务器上,也可以通过配置TDengine的域名来访问TDengine。在K8S环境下,可以配置成TDengine所运行的service name ---batch-size +--batch-size blm_prometheus会将收到的prometheus的数据拼装成TDengine的写入请求,这个参数控制一次发给TDengine的写入请求中携带的数据条数。 --dbname @@ -113,10 +113,10 @@ select * from apiserver_request_latencies_bucket; ``` ## Telegraf直接写入 -[Telegraf](https://www.influxdata.com/time-series-platform/telegraf/)是一流行的IT运维数据采集开源工具,TDengine提供一个小工具[Bailongma](https://github.com/taosdata/Bailongma),只需在Telegraf做简单配置,无需任何代码,就可将Telegraf采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文[用Docker容器快速搭建一个Devops监控Demo](https://www.taosdata.com/blog/2020/02/03/1189.html)即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。 +是一流行的IT运维数据采集开源工具,TDengine提供一个小工具Bailongma,只需在Telegraf做简单配置,无需任何代码,就可将Telegraf采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文用Docker容器快速搭建一个Devops监控Demo即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。 ### 从源代码编译blm_telegraf -用户需要从github下载[Bailongma](https://github.com/taosdata/Bailongma)的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件: +用户需要从github下载Bailongma的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件: - Linux操作系统的服务器 - 安装好Golang, 1.10版本以上 @@ -137,7 +137,7 @@ go build ### 配置Telegraf 修改Telegraf配置文件/etc/telegraf/telegraf.conf中与TDengine有关的配置项。 -在output plugins部分,增加[[outputs.http]]配置项: +在output plugins部分,增加[[outputs.http]]配置项: - url: bailongma API服务提供的URL, 参考下面的启动示例章节 - data_format: "json" @@ -148,16 +148,16 @@ go build - hostname: 区分不同采集设备的机器名称,需确保其唯一性 - metric_batch_size: 100,允许Telegraf每批次写入记录最大数量,增大其数量可以降低Telegraf的请求发送频率。 -关于如何使用Telegraf采集数据以及更多有关使用Telegraf的信息,请参考Telegraf官方的[文档](https://docs.influxdata.com/telegraf/v1.11/)。 +关于如何使用Telegraf采集数据以及更多有关使用Telegraf的信息,请参考Telegraf官方的文档。 ### 启动blm_telegraf程序 blm_telegraf程序有以下选项,在启动blm_telegraf程序时可以通过设定这些选项来设定blm_telegraf的配置。 ```sh ---host +--host TDengine服务端的IP地址,缺省值为空 ---batch-size +--batch-size blm_telegraf会将收到的telegraf的数据拼装成TDengine的写入请求,这个参数控制一次发给TDengine的写入请求中携带的数据条数。 --dbname @@ -218,15 +218,12 @@ use telegraf; select * from cpu; ``` - - MQTT是一流行的物联网数据传输协议,TDengine 可以很方便的接入 MQTT Broker 接受的数据并写入到 TDengine。 ## EMQ Broker 直接写入 -[EMQ](https://github.com/emqx/emqx)是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDengine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考 [EMQ 官方文档](https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine)。 +EMQ是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDengine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考EMQ 官方文档。 ## HiveMQ Broker 直接写入 -[HiveMQ](https://www.hivemq.com/) 是一个提供免费个人版和企业版的 MQTT 代理,主要用于企业和新兴的机器到机器M2M通讯和内部传输,满足可伸缩性、易管理和安全特性。HiveMQ 提供了开源的插件开发包。可以通过 HiveMQ extension - TDengine 保存数据到 TDengine。详细使用方法请参考 [HiveMQ extension - TDengine 说明文档](https://github.com/huskar-t/hivemq-tdengine-extension/blob/b62a26ecc164a310104df57691691b237e091c89/README.md)。 - +HiveMQ 是一个提供免费个人版和企业版的 MQTT 代理,主要用于企业和新兴的机器到机器M2M通讯和内部传输,满足可伸缩性、易管理和安全特性。HiveMQ 提供了开源的插件开发包。可以通过 HiveMQ extension - TDengine 保存数据到 TDengine。详细使用方法请参考 HiveMQ extension - TDengine 说明文档。 From 246fe071be4e155c563c9a05fa7e9ccccfbd2a34 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 20:17:42 +0800 Subject: [PATCH 15/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for TAOS SQL-ch --- .../webdocs/markdowndocs/TAOS SQL-ch.md | 179 ++++++++---------- 1 file changed, 80 insertions(+), 99 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md index 8ed497fe21..b68f60f529 100644 --- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md +++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md @@ -77,15 +77,13 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic SHOW VARIABLES; ``` - - **使用数据库** - + ```mysql USE db_name; ``` 使用/切换数据库 - - **删除数据库** ```mysql DROP DATABASE [IF EXISTS] db_name; @@ -120,7 +118,6 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。 - - **显示系统所有数据库** ```mysql SHOW DATABASES; @@ -128,7 +125,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ## 表管理 - **创建数据表** - + ```mysql CREATE TABLE [IF NOT EXISTS] tb_name (timestamp_field_name TIMESTAMP, field1_name data_type1 [, field2_name data_type2 ...]); ``` @@ -153,7 +150,6 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic 显示当前数据库下的所有数据表信息。说明:可在like中使用通配符进行名称的匹配。 通配符匹配:1)’%’ (百分号)匹配0到任意个字符;2)’_’下划线匹配一个字符。 - - **在线修改显示字符宽度** ```mysql @@ -184,18 +180,18 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ## 超级表STable管理 - **创建超级表** - + ```mysql CREATE TABLE [IF NOT EXISTS] stb_name (timestamp_field_name TIMESTAMP, field1_name data_type1 [, field2_name data_type2 ...]) TAGS (tag1_name tag_type1, tag2_name tag_type2 [, tag3_name tag_type3]); ``` 创建STable, 与创建表的SQL语法相似,但需指定TAGS字段的名称和类型 - + 说明: 1) TAGS 列的数据类型不能是timestamp类型; 2) TAGS 列名不能与其他列名相同; 3) TAGS 列名不能为预留关键字; 4) TAGS 最多允许128个,可以0个,总长度不超过16k个字符 - + - **删除超级表** ```mysql @@ -215,7 +211,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ```mysql DESCRIBE stb_name; ``` - + - **超级表增加列** ```mysql @@ -230,11 +226,11 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ## 超级表 STable 中 TAG 管理 - **添加标签** - + ```mysql ALTER TABLE stb_name ADD TAG new_tag_name tag_type; ``` - 为STable增加一个新的标签,并指定新标签的类型。标签总数不能超过128个,总长度不超过16k个字符. + 为STable增加一个新的标签,并指定新标签的类型。标签总数不能超过128个,总长度不超过16k个字符。 - **删除标签** @@ -265,36 +261,31 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ``` 向表tb_name中插入一条记录 - - **插入一条记录,数据对应到指定的列** ```mysql INSERT INTO tb_name (field1_name, ...) VALUES(field1_value, ...) ``` 向表tb_name中插入一条记录,数据对应到指定的列。SQL语句中没有出现的列,数据库将自动填充为NULL。主键(时间戳)不能为NULL。 - - **插入多条记录** ```mysql INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...)...; ``` 向表tb_name中插入多条记录 - - **按指定的列插入多条记录** ```mysql INSERT INTO tb_name (field1_name, ...) VALUES(field1_value1, ...) (field1_value2, ...) ``` 向表tb_name中按指定的列插入多条记录 - - **向多个表插入多条记录** ```mysql - INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...)... + INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...)... tb2_name VALUES (field1_value1, ...)(field1_value2, ...)...; ``` 同时向表tb1_name和tb2_name中分别插入多条记录 - - **同时向多个表按列插入多条记录** ```mysql INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) @@ -320,7 +311,7 @@ SELECT select_expr [, select_expr ...] [FILL fill_val] [SLIDING fill_val] [GROUP BY col_list] - [ORDER BY col_list { DESC | ASC }] + [ORDER BY col_list { DESC | ASC }] [SLIMIT limit_val [, SOFFSET offset_val]] [LIMIT limit_val [, OFFSET offset_val]] [>> export_file] @@ -382,7 +373,6 @@ taos> SELECT * FROM meters; Query OK, 9 row(s) in set (0.002022s) ``` - 通配符支持表名前缀,以下两个SQL语句均为返回全部的列: ```mysql SELECT * FROM d1001; @@ -592,11 +582,11 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表/超级表中记录行数或某列的非空值个数。 - 返回结果数据类型:长整型INT64。 - 应用字段:应用全部字段。 - 适用于:表、超级表。 - 说明:1)可以使用星号*来替代具体的字段,使用星号(*)返回全部记录数量。2)针对同一表的(不包含NULL值)字段查询结果均相同。3)如果统计对象是具体的列,则返回该列中非NULL值的记录数量。 + 功能说明:统计表/超级表中记录行数或某列的非空值个数。 + 返回结果数据类型:长整型INT64。 + 应用字段:应用全部字段。 + 适用于:表、超级表。 + 说明:1)可以使用星号*来替代具体的字段,使用星号(*)返回全部记录数量。2)针对同一表的(不包含NULL值)字段查询结果均相同。3)如果统计对象是具体的列,则返回该列中非NULL值的记录数量。 示例: ```mysql @@ -613,16 +603,15 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 Query OK, 1 row(s) in set (0.001075s) ``` - - **AVG** ```mysql SELECT AVG(field_name) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的平均值。 - 返回结果数据类型:双精度浮点数Double。 - 应用字段:不能应用在timestamp、binary、nchar、bool字段。 - 适用于:表、超级表。 - + 功能说明:统计表/超级表中某列的平均值。 + 返回结果数据类型:双精度浮点数Double。 + 应用字段:不能应用在timestamp、binary、nchar、bool字段。 + 适用于:表、超级表。 + 示例: ```mysql taos> SELECT AVG(current), AVG(voltage), AVG(phase) FROM meters; @@ -642,8 +631,8 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT TWA(field_name) FROM tb_name WHERE clause; ``` - 功能说明:时间加权平均函数。统计表/超级表中某列在一段时间内的时间加权平均。 - 返回结果数据类型:双精度浮点数Double。 + 功能说明:时间加权平均函数。统计表/超级表中某列在一段时间内的时间加权平均。 + 返回结果数据类型:双精度浮点数Double。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:时间加权平均(time weighted average, TWA)查询需要指定查询时间段的 _开始时间_ 和 _结束时间_ 。 适用于:表、超级表。 @@ -652,10 +641,10 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT SUM(field_name) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的和。 - 返回结果数据类型:双精度浮点数Double和长整型INT64。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 - 适用于:表、超级表。 + 功能说明:统计表/超级表中某列的和。 + 返回结果数据类型:双精度浮点数Double和长整型INT64。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 适用于:表、超级表。 示例: ```mysql @@ -676,9 +665,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT STDDEV(field_name) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表中某列的均方差。 - 返回结果数据类型:双精度浮点数Double。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表中某列的均方差。 + 返回结果数据类型:双精度浮点数Double。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 适用于:表。 示例: @@ -694,10 +683,10 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT LEASTSQUARES(field_name, start_val, step_val) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表中某列的值是主键(时间戳)的拟合直线方程。start_val是自变量初始值,step_val是自变量的步长值。 - 返回结果数据类型:字符串表达式(斜率, 截距)。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 - 说明:自变量是时间戳,因变量是该列的值。 + 功能说明:统计表中某列的值是主键(时间戳)的拟合直线方程。start_val是自变量初始值,step_val是自变量的步长值。 + 返回结果数据类型:字符串表达式(斜率, 截距)。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 说明:自变量是时间戳,因变量是该列的值。 适用于:表。 示例: @@ -715,8 +704,8 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最小值。 - 返回结果数据类型:同应用的字段。 + 功能说明:统计表/超级表中某列的值最小值。 + 返回结果数据类型:同应用的字段。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 示例: @@ -738,8 +727,8 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最大值。 - 返回结果数据类型:同应用的字段。 + 功能说明:统计表/超级表中某列的值最大值。 + 返回结果数据类型:同应用的字段。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 示例: @@ -757,14 +746,13 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 Query OK, 1 row(s) in set (0.000987s) ``` - - **FIRST** ```mysql SELECT FIRST(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最先写入的非NULL值。 - 返回结果数据类型:同应用的字段。 - 应用字段:所有字段。 + 功能说明:统计表/超级表中某列的值最先写入的非NULL值。 + 返回结果数据类型:同应用的字段。 + 应用字段:所有字段。 说明:1)如果要返回各个列的首个(时间戳最小)非NULL值,可以使用FIRST(*);2) 如果结果集中的某列全部为NULL值,则该列的返回结果也是NULL;3) 如果结果集中所有列全部为NULL值,则不返回结果。 示例: @@ -786,9 +774,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT LAST(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最后写入的非NULL值。 - 返回结果数据类型:同应用的字段。 - 应用字段:所有字段。 + 功能说明:统计表/超级表中某列的值最后写入的非NULL值。 + 返回结果数据类型:同应用的字段。 + 应用字段:所有字段。 说明:1)如果要返回各个列的最后(时间戳最大)一个非NULL值,可以使用LAST(*);2)如果结果集中的某列全部为NULL值,则该列的返回结果也是NULL;如果结果集中所有列全部为NULL值,则不返回结果。 示例: @@ -810,10 +798,10 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT TOP(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明: 统计表/超级表中某列的值最大*k*个非NULL值。若多于k个列值并列最大,则返回时间戳小的。 - 返回结果数据类型:同应用的字段。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 - 说明:1)*k*值取值范围1≤*k*≤100;2)系统同时返回该记录关联的时间戳列。 + 功能说明: 统计表/超级表中某列的值最大*k*个非NULL值。若多于k个列值并列最大,则返回时间戳小的。 + 返回结果数据类型:同应用的字段。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 说明:1)*k*值取值范围1≤*k*≤100;2)系统同时返回该记录关联的时间戳列。 示例: ```mysql @@ -837,9 +825,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT BOTTOM(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最小*k*个非NULL值。若多于k个列值并列最小,则返回时间戳小的。 - 返回结果数据类型:同应用的字段。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表/超级表中某列的值最小*k*个非NULL值。若多于k个列值并列最小,则返回时间戳小的。 + 返回结果数据类型:同应用的字段。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:1)*k*值取值范围1≤*k*≤100;2)系统同时返回该记录关联的时间戳列。 示例: @@ -863,9 +851,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause]; ``` - 功能说明:统计表中某列的值百分比分位数。 - 返回结果数据类型: 双精度浮点数Double。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表中某列的值百分比分位数。 + 返回结果数据类型: 双精度浮点数Double。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:*P*值取值范围0≤*P*≤100,为0的时候等同于MIN,为100的时候等同于MAX。 示例: @@ -881,9 +869,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT APERCENTILE(field_name, P) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表中某列的值百分比分位数,与PERCENTILE函数相似,但是返回近似结果。 - 返回结果数据类型: 双精度浮点数Double。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表中某列的值百分比分位数,与PERCENTILE函数相似,但是返回近似结果。 + 返回结果数据类型: 双精度浮点数Double。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:*P*值取值范围0≤*P*≤100,为0的时候等同于MIN,为100的时候等同于MAX。推荐使用```APERCENTILE```函数,该函数性能远胜于```PERCENTILE```函数 ```mysql taos> SELECT APERCENTILE(current, 20) FROM d1001; @@ -897,9 +885,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT LAST_ROW(field_name) FROM { tb_name | stb_name }; ``` - 功能说明:返回表(超级表)的最后一条记录。 - 返回结果数据类型:同应用的字段。 - 应用字段:所有字段。 + 功能说明:返回表(超级表)的最后一条记录。 + 返回结果数据类型:同应用的字段。 + 应用字段:所有字段。 说明:与last函数不同,last_row不支持时间范围限制,强制返回最后一条记录。 示例: @@ -922,11 +910,11 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT DIFF(field_name) FROM tb_name [WHERE clause]; ``` - 功能说明:统计表中某列的值与前一行对应值的差。 - 返回结果数据类型: 同应用字段。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表中某列的值与前一行对应值的差。 + 返回结果数据类型: 同应用字段。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:输出结果行数是范围内总行数减一,第一行没有结果输出。 - + 示例: ```mysql taos> SELECT DIFF(current) FROM d1001; @@ -937,14 +925,13 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 Query OK, 2 row(s) in set (0.001162s) ``` - - **SPREAD** ```mysql SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的最大值和最小值之差。 - 返回结果数据类型: 双精度浮点数。 - 应用字段:不能应用在binary、nchar、bool类型字段。 + 功能说明:统计表/超级表中某列的最大值和最小值之差。 + 返回结果数据类型: 双精度浮点数。 + 应用字段:不能应用在binary、nchar、bool类型字段。 说明:可用于TIMESTAMP字段,此时表示记录的时间覆盖范围。 示例: @@ -962,15 +949,14 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 Query OK, 1 row(s) in set (0.000836s) ``` - - **四则运算** ```mysql SELECT field_name [+|-|*|/|%][Value|field_name] FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列或多列间的值加、减、乘、除、取余计算结果。 - 返回结果数据类型:双精度浮点数。 - 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 + 功能说明:统计表/超级表中某列或多列间的值加、减、乘、除、取余计算结果。 + 返回结果数据类型:双精度浮点数。 + 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 说明:1)支持两列或多列之间进行计算,可使用括号控制计算优先级;2)NULL字段不参与计算,如果参与计算的某行中包含NULL,该行的计算结果为NULL。 ```mysql @@ -987,12 +973,12 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 TDengine支持按时间段进行聚合,可以将表中数据按照时间段进行切割后聚合生成结果,比如温度传感器每秒采集一次数据,但需查询每隔10分钟的温度平均值。这个聚合适合于降维(down sample)操作, 语法如下: ```mysql -SELECT function_list FROM tb_name +SELECT function_list FROM tb_name [WHERE where_condition] INTERVAL (interval [, offset]) [FILL ({NONE | VALUE | PREV | NULL | LINEAR})] -SELECT function_list FROM stb_name +SELECT function_list FROM stb_name [WHERE where_condition] INTERVAL (interval [, offset]) [FILL ({ VALUE | PREV | NULL | LINEAR})] @@ -1000,18 +986,17 @@ SELECT function_list FROM stb_name ``` - 聚合时间段的长度由关键词INTERVAL指定,最短时间间隔10毫秒(10a),并且支持偏移(偏移必须小于间隔)。聚合查询中,能够同时执行的聚合和选择函数仅限于单个输出的函数:count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last,不能使用具有多行输出结果的函数(例如:top、bottom、diff以及四则运算)。 -- WHERE语句可以指定查询的起止时间和其他过滤条件 +- WHERE语句可以指定查询的起止时间和其他过滤条件 - FILL语句指定某一时间区间数据缺失的情况下的填充模式。填充模式包括以下几种: 1. 不进行填充:NONE(默认填充模式)。 - - 2. VALUE填充:固定值填充,此时需要指定填充的数值。例如:fill(value, 1.23)。 - - 3. NULL填充:使用NULL填充数据。例如:fill(null)。 - - 4. PREV填充:使用前一个非NULL值填充数据。例如:fill(prev)。 - -说明: + 2. VALUE填充:固定值填充,此时需要指定填充的数值。例如:fill(value, 1.23)。 + + 3. NULL填充:使用NULL填充数据。例如:fill(null)。 + + 4. PREV填充:使用前一个非NULL值填充数据。例如:fill(prev)。 + +说明: 1. 使用FILL语句的时候可能生成大量的填充输出,务必指定查询的时间区间。针对每次查询,系统可返回不超过1千万条具有插值的结果。 2. 在时间维度聚合中,返回的结果中时间序列严格单调递增。 3. 如果查询对象是超级表,则聚合函数会作用于该超级表下满足值过滤条件的所有表的数据。如果查询中没有使用group by语句,则返回的结果按照时间序列严格单调递增;如果查询中使用了group by语句分组,则返回结果中每个group内不按照时间序列严格单调递增。 @@ -1040,8 +1025,6 @@ SELECT AVG(current),MAX(current),LEASTSQUARES(current, start_val, step_val), PER - SQL语句最大长度65480个字符,但可通过系统配置参数maxSQLLength修改,最长可配置为1M - 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制 - - ## TAOS SQL其他约定 **group by的限制** @@ -1054,6 +1037,4 @@ TAOS SQL支持表之间按主键时间戳来join两张表的列,暂不支持 **is not null与不为空的表达式适用范围** -is not null支持所有类型的列。不为空的表达式为 <>"",仅对非数值类型的列适用。 - - +is not null支持所有类型的列。不为空的表达式为 <>"",仅对非数值类型的列适用。 \ No newline at end of file From cf31990a076e972ca017d598c7565d4b91459169 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 20:23:34 +0800 Subject: [PATCH 16/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for architecture-ch --- .../webdocs/markdowndocs/architecture-ch.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/architecture-ch.md b/documentation20/webdocs/markdowndocs/architecture-ch.md index c9bfa30830..47fb8094b7 100644 --- a/documentation20/webdocs/markdowndocs/architecture-ch.md +++ b/documentation20/webdocs/markdowndocs/architecture-ch.md @@ -1,4 +1,4 @@ -#数据模型和整体架构 +# 数据模型和整体架构 ## 数据模型 ### 物联网典型场景 @@ -102,7 +102,7 @@ 每一条记录都有设备ID,时间戳,采集的物理量(如上图中的电流、电压、相位),还有与每个设备相关的静态标签(如上述表一中的位置Location和分组groupId)。每个设备是受外界的触发,或按照设定的周期采集数据。采集的数据点是时序的,是一个数据流。 -### 数据特征 +### 数据特征 除时序特征外,仔细研究发现,物联网、车联网、运维监测类数据还具有很多其他明显的特征: 1. 数据高度结构化; @@ -121,7 +121,7 @@ ### 关系型数据库模型 因为采集的数据一般是结构化数据,同时为降低学习门槛,TDengine采用传统的关系型数据库模型管理数据。因此用户需要先创建库,然后创建表,之后才能插入或查询数据。TDengine采用的是结构化存储,而不是NoSQL的key-value存储。 -### 一个数据采集点一张表 +### 一个数据采集点一张表 为充分利用其数据的时序性和其他数据特点,TDengine要求**对每个数据采集点单独建表**(比如有一千万个智能电表,就需创建一千万张表,上述表格中的d1001, d1002, d1003, d1004都需单独建表),用来存储这个采集点所采集的时序数据。这种设计有几大优点: 1. 能保证一个采集点的数据在存储介质上是以块为单位连续存储的。如果读取一个时间段的数据,它能大幅减少随机读取操作,成数量级的提升读取和查询速度。 @@ -150,7 +150,7 @@ TDengine 分布式架构的逻辑结构图如下:
图 1 TDengine架构示意图
一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine应用驱动(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过taosc的API与TDengine集群进行互动。下面对每个逻辑单元进行简要介绍。 -**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或Docker容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》。 +**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或Docker容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《一篇文章说清楚TDengine的FQDN》。 **数据节点(dnode):** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例,一个工作的系统必须有至少一个数据节点。dnode包含零到多个逻辑的虚拟节点(VNODE),零或者至多一个逻辑的管理节点(mnode)。dnode在系统中的唯一标识由实例的End Point (EP )决定。EP是dnode所在物理节点的FQDN (Fully Qualified Domain Name)和系统所配置的网络端口号(Port)的组合。通过配置不同的端口,一个物理节点(一台物理机、虚拟机或容器)可以运行多个实例,或有多个数据节点。 @@ -356,7 +356,7 @@ SQL语句的解析和校验工作在客户端完成。解析SQL语句并生成 客户端在获取查询结果的时候,dnode的查询执行队列中的工作线程会等待vnode执行线程执行完成,才能将查询结果返回到请求的客户端。 -### 按时间轴聚合、降采样、插值 +### 按时间轴聚合、降采样、插值 时序数据有别于普通数据的显著特征是每条记录均具有时间戳,因此针对具有时间戳数据在时间轴上进行聚合是不同于普通数据库的重要功能。从这点上来看,与流计算引擎的窗口查询有相似的地方。 From 5f3c6f5a7987ee7559e4c4380e5befc43f00cc48 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 20:26:45 +0800 Subject: [PATCH 17/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for Taos Error Code-ch --- documentation20/webdocs/markdowndocs/Taos Error Code-ch.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation20/webdocs/markdowndocs/Taos Error Code-ch.md b/documentation20/webdocs/markdowndocs/Taos Error Code-ch.md index a9a3dee432..95975dba5a 100644 --- a/documentation20/webdocs/markdowndocs/Taos Error Code-ch.md +++ b/documentation20/webdocs/markdowndocs/Taos Error Code-ch.md @@ -1,6 +1,5 @@ # TDengine 2.0 错误码以及对应的十进制码 - | 状态码 | 模 | 错误码(十六进制) | 错误描述 | 错误码(十进制) | |-----------------------| :---: | :---------: | :------------------------ | ---------------- | |TSDB_CODE_RPC_ACTION_IN_PROGRESS| 0 | 0x0001| "Action in progress"| -2147483647| From 5a49330c05c947b1032ece138de2cab54f52e9b5 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 22 Dec 2020 20:44:37 +0800 Subject: [PATCH 18/22] [TD-2522] fix: fix some typo in taos.cfg, fix convertor compliance for administrator-ch --- .../webdocs/markdowndocs/administrator-ch.md | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/administrator-ch.md b/documentation20/webdocs/markdowndocs/administrator-ch.md index 2c470a270d..81704c7dbd 100644 --- a/documentation20/webdocs/markdowndocs/administrator-ch.md +++ b/documentation20/webdocs/markdowndocs/administrator-ch.md @@ -12,7 +12,7 @@ Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSizePerTable + 0.5Kb) ``` -示例:假设是4核机器,cache是缺省大小16M, blocks是缺省值6,假设有10万张表,标签总长度是256字节,则总的内存需求为:4\*(16\*6+10) + 100000*(0.25+0.5)/1000 = 499M。 +示例:假设是4核机器,cache是缺省大小16M, blocks是缺省值6,假设有10万张表,标签总长度是256字节,则总的内存需求为:4\*(16\*6+10) + 100000*(0.25+0.5)/1000 = 499M。 实际运行的系统往往会根据数据特点的不同,将数据存放在不同的DB里。因此做规划时,也需要考虑。 @@ -35,7 +35,7 @@ TDengine相对于通用数据库,有超高的压缩比,在绝大多数场景 Raw DataSize = numOfTables * rowSizePerTable * rowsPerTable ``` -示例:1000万台智能电表,每台电表每15分钟采集一次数据,每次采集的数据128字节,那么一年的原始数据量是:10000000\*128\*24\*60/15*365 = 44.8512T。TDengine大概需要消耗44.851/5=8.97024T空间。 +示例:1000万台智能电表,每台电表每15分钟采集一次数据,每次采集的数据128字节,那么一年的原始数据量是:10000000\*128\*24\*60/15*365 = 44.8512T。TDengine大概需要消耗44.851/5=8.97024T空间。 用户可以通过参数keep,设置数据在磁盘中的最大保存时长。为进一步减少存储成本,TDengine还提供多级存储,最冷的数据可以存放在最廉价的存储介质上,应用的访问不用做任何调整,只是读取速度降低了。 @@ -121,7 +121,7 @@ taosd -C - replica:副本个数,取值范围:1-3。单位为个,默认值:1 - precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms -对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: +对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: ``` create database demo days 10 cache 32 blocks 8 replica 3; @@ -148,8 +148,8 @@ ALTER DNODE ``` - dnode_id: 可以通过SQL语句"SHOW DNODES"命令获取 -- config: 要调整的日志参数,在如下列表中取值 - > resetlog 截断旧日志文件,创建一个新日志文件 +- config: 要调整的日志参数,在如下列表中取值 + > resetlog 截断旧日志文件,创建一个新日志文件 > debugFlag < 131 | 135 | 143 > 设置debugFlag为131、135或者143 例如: @@ -157,9 +157,9 @@ ALTER DNODE alter dnode 1 debugFlag 135; ``` -## 客户端配置 +## 客户端配置 -TDengine系统的前台交互客户端应用程序为taos,以及应用驱动,它与taosd共享同一个配置文件taos.cfg。运行taos时,使用参数-c指定配置文件目录,如taos -c /home/cfg,表示使用/home/cfg/目录下的taos.cfg配置文件中的参数,缺省目录是/etc/taos。更多taos的使用方法请见[Shell命令行程序](https://www.taosdata.com/cn/documentation/administrator/#_TDengine_Shell命令行程序)。本节主要说明 taos 客户端应用在配置文件 taos.cfg 文件中使用到的参数。 +TDengine系统的前台交互客户端应用程序为taos,以及应用驱动,它与taosd共享同一个配置文件taos.cfg。运行taos时,使用参数-c指定配置文件目录,如taos -c /home/cfg,表示使用/home/cfg/目录下的taos.cfg配置文件中的参数,缺省目录是/etc/taos。更多taos的使用方法请见Shell命令行程序。本节主要说明 taos 客户端应用在配置文件 taos.cfg 文件中使用到的参数。 **2.0.10.0 之后版本支持命令行以下参数显示当前客户端参数的配置** @@ -176,7 +176,7 @@ taos -C 或 taos --dump-config - locale 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置 - + TDengine为存储中文、日文、韩文等非ASCII编码的宽字符,提供一种专门的字段类型nchar。写入nchar字段的数据将统一采用UCS4-LE格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用nchar字段来存储诸如中文、日文、韩文等非ASCII字符,需要正确设置客户端的编码格式。 客户端的输入的字符均采用操作系统当前默认的编码格式,在Linux系统上多为UTF-8,部分中文系统编码则可能是GB18030或GBK等。在docker环境中默认的编码是POSIX。在中文版Windows系统中,编码则是CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证nchar中的数据正确转换为UCS4-LE编码格式。 @@ -186,7 +186,7 @@ taos -C 或 taos --dump-config - charset 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置 - + 如果配置文件中不设置charset,在Linux系统中,taos在启动时候,自动读取系统当前的locale信息,并从locale信息中解析提取charset编码格式。如果自动读取locale信息失败,则尝试读取charset配置,如果读取charset配置也失败,则中断启动过程。 在Linux系统中,locale信息包含了字符编码信息,因此正确设置了Linux系统locale以后可以不用再单独设置charset。例如: @@ -242,12 +242,11 @@ taos -C 或 taos --dump-config 为了避免使用字符串时间格式带来的不确定性,也可以直接使用Unix时间戳。此外,还可以在SQL语句中使用带有时区的时间戳字符串,例如:RFC3339格式的时间戳字符串,2013-04-12T15:52:01.123+08:00或者ISO-8601格式时间戳字符串2013-04-12T15:52:01.123+0800。上述两个字符串转化为Unix时间戳不受系统所在时区的影响。 启动taos时,也可以从命令行指定一个taosd实例的end point,否则就从taos.cfg读取。 - + - maxBinaryDisplayWidth Shell中binary 和 nchar字段的显示宽度上限,超过此限制的部分将被隐藏。默认值:30。可在 shell 中通过命令 set max_binary_display_width nn 动态修改此选项。 - ## 用户管理 系统管理员可以在CLI界面里添加、删除用户,也可以修改密码。CLI里SQL语法如下: @@ -280,7 +279,7 @@ ALTER USER PRIVILEGE ; SHOW USERS; ``` -显示所有用户 +显示所有用户 **注意:**SQL 语法中,< >表示需要用户输入的部分,但请不要输入< >本身 @@ -428,8 +427,6 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下 您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录。 - - ## TDengine参数限制与保留关键字 - 数据库名:不能包含“.”以及特殊字符,不能超过32个字符 @@ -448,8 +445,6 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下 - 库的个数:仅受节点个数限制 - 单个库上虚拟节点个数:不能超过64个 - - 目前TDengine有将近200个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable名、数据列名及标签列名等。这些关键字列表如下: | 关键字列表 | | | | | @@ -489,5 +484,4 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下 | COMP | GE | METRIC | SELECT | VIEW | | CONCAT | GLOB | METRICS | SEMI | WAVG | | CONFIGS | GRANTS | MIN | SET | WHERE | -| CONFLICT | GROUP | | | | - +| CONFLICT | GROUP | | | | \ No newline at end of file From dbb40862365e32f3e65748222721bbbb283d4b87 Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Wed, 23 Dec 2020 13:24:25 +0800 Subject: [PATCH 19/22] [TD-2534]: fix crash on null pointer parser --- src/plugins/http/src/httpResp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/http/src/httpResp.c b/src/plugins/http/src/httpResp.c index 755dad2d85..a41367ad7f 100644 --- a/src/plugins/http/src/httpResp.c +++ b/src/plugins/http/src/httpResp.c @@ -136,7 +136,7 @@ void httpSendErrorResp(HttpContext *pContext, int32_t errNo) { else httpCode = 400; - if (pContext->parser->httpCode != 0) { + if (pContext->parser && pContext->parser->httpCode != 0) { httpCode = pContext->parser->httpCode; } From 566680c78e8759872054e4f7afd64ff78c4f6aa1 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Wed, 23 Dec 2020 08:15:22 +0000 Subject: [PATCH 20/22] [TD-2538]: crash when sql has limit & offset --- src/client/src/tscLocalMerge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index a99918975e..da763b9b0c 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -911,6 +911,13 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, } } + if (pRes->numOfRowsGroup >= pQueryInfo->limit.limit && pQueryInfo->limit.limit > 0) { + pRes->numOfRows = 0; + pBeforeFillData->num = 0; + pLocalReducer->discard = true; + return; + } + pRes->numOfRowsGroup += pRes->numOfRows; // impose the limitation of output rows on the final result From a94dee1c765d87f456ccab84ada3f63acd2c96da Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 23 Dec 2020 10:10:08 +0000 Subject: [PATCH 21/22] fix bug --- src/vnode/src/vnodeRead.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 637d470f8a..94fbe5066b 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -303,8 +303,11 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SVReadMsg *pRead) { // NOTE: set return code to be TSDB_CODE_QRY_HAS_RSP to notify dnode to return msg to client code = TSDB_CODE_QRY_HAS_RSP; } else { - void *h1 = qGetResultRetrieveMsg(*qhandle); - assert(h1 == NULL); + //void *h1 = qGetResultRetrieveMsg(*qhandle); + + /* remove this assert, one possible case that will cause h1 not NULL: query thread unlock pQInfo->lock, and then FETCH thread execute twice before query thread reach here */ + //assert(h1 == NULL); + freehandle = qQueryCompleted(*qhandle); } From c34cfa46d1642127a1be2c640c33ba6d2c4dee83 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 23 Dec 2020 10:41:47 +0000 Subject: [PATCH 22/22] fix bug --- src/client/src/tscSql.c | 20 +++++++++++--------- src/util/inc/tref.h | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 9ad38e3360..bb0d8005c2 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -284,16 +284,18 @@ void taos_close(TAOS *taos) { return; } - SSqlObj* pHb = (SSqlObj*)taosAcquireRef(tscObjRef, pObj->hbrid); - if (pHb != NULL) { - if (pHb->rpcRid > 0) { // wait for rsp from dnode - rpcCancelRequest(pHb->rpcRid); - pHb->rpcRid = -1; - } + if (RID_VALID(pObj->hbrid)) { + SSqlObj* pHb = (SSqlObj*)taosAcquireRef(tscObjRef, pObj->hbrid); + if (pHb != NULL) { + if (RID_VALID(pHb->rpcRid)) { // wait for rsp from dnode + rpcCancelRequest(pHb->rpcRid); + pHb->rpcRid = -1; + } - tscDebug("%p HB is freed", pHb); - taosReleaseRef(tscObjRef, pHb->self); - taos_free_result(pHb); + tscDebug("%p HB is freed", pHb); + taosReleaseRef(tscObjRef, pHb->self); + taos_free_result(pHb); + } } tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn); diff --git a/src/util/inc/tref.h b/src/util/inc/tref.h index cd5092f30a..085c10c551 100644 --- a/src/util/inc/tref.h +++ b/src/util/inc/tref.h @@ -52,6 +52,8 @@ void *taosIterateRef(int rsetId, int64_t rid); // return the number of references in system int taosListRef(); +#define RID_VALID(x) ((x) > 0) + /* sample code to iterate the refs void demoIterateRefs(int rsetId) {