From 7951386dd36cf63b89154242b684485f9cfb1fe2 Mon Sep 17 00:00:00 2001 From: xfan0805 Date: Tue, 24 Dec 2024 09:31:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=88=86=E5=8C=BA=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20#8652?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assests/migrations/000008_init.down.sql | 1 + .../assests/migrations/000008_init.up.sql | 9 + .../mysql/db-partition/handler/handler.go | 9 +- dbm-services/mysql/db-partition/main.go | 6 +- .../db-partition/model/init_custimazation.go | 46 ++++ .../service/check_partition_base_func.go | 26 +- .../db-partition/service/cron_basic_func.go | 8 +- .../db-partition/service/manage_config.go | 257 +++++++++--------- .../service/manage_config_object.go | 11 +- 9 files changed, 224 insertions(+), 149 deletions(-) create mode 100644 dbm-services/mysql/db-partition/assests/migrations/000008_init.down.sql create mode 100644 dbm-services/mysql/db-partition/assests/migrations/000008_init.up.sql create mode 100644 dbm-services/mysql/db-partition/model/init_custimazation.go diff --git a/dbm-services/mysql/db-partition/assests/migrations/000008_init.down.sql b/dbm-services/mysql/db-partition/assests/migrations/000008_init.down.sql new file mode 100644 index 0000000000..31ba96a1d0 --- /dev/null +++ b/dbm-services/mysql/db-partition/assests/migrations/000008_init.down.sql @@ -0,0 +1 @@ +SET NAMES utf8; diff --git a/dbm-services/mysql/db-partition/assests/migrations/000008_init.up.sql b/dbm-services/mysql/db-partition/assests/migrations/000008_init.up.sql new file mode 100644 index 0000000000..d82edbcef1 --- /dev/null +++ b/dbm-services/mysql/db-partition/assests/migrations/000008_init.up.sql @@ -0,0 +1,9 @@ +SET NAMES utf8; +CREATE TABLE `partition_customization_config` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `bk_biz_id` int(11) NOT NULL, + `immute_domain` varchar(255) NOT NULL DEFAULT '', + `partition_column` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `bk_biz_id` (`bk_biz_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/dbm-services/mysql/db-partition/handler/handler.go b/dbm-services/mysql/db-partition/handler/handler.go index cf18e0660e..cf47c4131c 100644 --- a/dbm-services/mysql/db-partition/handler/handler.go +++ b/dbm-services/mysql/db-partition/handler/handler.go @@ -1,9 +1,7 @@ -// Package handler TODO +// Package handler TODOG package handler import ( - "dbm-services/mysql/db-partition/model" - "dbm-services/mysql/db-partition/monitor" "errors" "fmt" "log/slog" @@ -11,6 +9,9 @@ import ( _ "runtime/debug" // debug TODO "time" + "dbm-services/mysql/db-partition/model" + "dbm-services/mysql/db-partition/monitor" + cron_pkg "github.com/robfig/cron/v3" "dbm-services/common/go-pubpkg/errno" @@ -185,7 +186,7 @@ func DisablePartitionByCluster(r *gin.Context) { SendResponse(r, err, nil) return } - slog.Info(fmt.Sprintf("ids: %v, operator: %s", input.Ids, input.Operator)) + slog.Info(fmt.Sprintf("cluster_ids: %v, operator: %s", input.ClusterIds, input.Operator)) err := input.DisablePartitionConfigByCluster() if err != nil { slog.Error(err.Error()) diff --git a/dbm-services/mysql/db-partition/main.go b/dbm-services/mysql/db-partition/main.go index 0a910773e4..2aa42deefc 100644 --- a/dbm-services/mysql/db-partition/main.go +++ b/dbm-services/mysql/db-partition/main.go @@ -1,11 +1,12 @@ package main import ( + "net/http" + "os" + "dbm-services/mysql/db-partition/monitor" "dbm-services/mysql/db-partition/service" "dbm-services/mysql/db-partition/util" - "net/http" - "os" "github.com/gin-gonic/gin" "github.com/golang-migrate/migrate/v4" @@ -82,4 +83,5 @@ func init() { model.DB.Init() model.InitClient() model.InitBkRepo() + model.InitCustimazation() } diff --git a/dbm-services/mysql/db-partition/model/init_custimazation.go b/dbm-services/mysql/db-partition/model/init_custimazation.go new file mode 100644 index 0000000000..257f025054 --- /dev/null +++ b/dbm-services/mysql/db-partition/model/init_custimazation.go @@ -0,0 +1,46 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package model + +import ( + "log/slog" + + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +var CustimazationMap map[int64]string + +// Custimazation TODO +type Custimazation struct { + id int `gorm:"column:id"` + BkBizId int64 `json:"bk_biz_id" gorm:"column:bk_biz_id"` + PartitionColumn string `json:"partition_column" gorm:"column:partition_column"` + ImmuteDomain string `json:"immute_domain" gorm:"column:immute_domain"` +} + +func InitCustimazation() { + CustimazationMap = make(map[int64]string) + custimazations := []Custimazation{} + result := DB.Self.Session(&gorm.Session{ + Logger: logger.Default.LogMode(logger.Info), + }).Table("partition_customization_config").Find(&custimazations) + if result.Error != nil { + slog.Error("定制化配置读取失败!", result.Error) + } + for _, cs := range custimazations { + if cs.ImmuteDomain != "" { + CustimazationMap[cs.BkBizId] = cs.ImmuteDomain + } else if cs.PartitionColumn != "" { + CustimazationMap[cs.BkBizId] = cs.PartitionColumn + } + } +} diff --git a/dbm-services/mysql/db-partition/service/check_partition_base_func.go b/dbm-services/mysql/db-partition/service/check_partition_base_func.go index 3f23433f7a..55205461e1 100644 --- a/dbm-services/mysql/db-partition/service/check_partition_base_func.go +++ b/dbm-services/mysql/db-partition/service/check_partition_base_func.go @@ -146,16 +146,9 @@ func (config *PartitionConfig) GetDbTableInfo(fromCron bool, host Host) (ptlist slog.Error("GetDbTableInfo", sql, err.Error()) return nil, err } - // (1)兼容【分区字段为空】的历史问题,对于某些特殊的分区类型,旧系统已经不在页面上支持,所以旧系统有意将分区字段留空, - // 使其无法在页面编辑,避免改变了其他所属分区类别,因此无法核对比较,但不影响新增和删除分区。 - // (2)兼容web、dnf业务的特殊定制类型,分区字段类型为int,但是系统记录为timestamp,因此无法核对比较,但不影响新增和删除分区。 - // (3)兼容minigame业务的特殊定制类型,分区类型为0,但是实际定义与分区类型存在差异,因此无法核对比较,但不影响新增和删除分区。 - webCustomization := config.BkBizId == 159 && config.PartitionColumn == "Fcreate_time" - iegamsCustomization := config.BkBizId == 5016839 && config.PartitionColumn == "Fcreate_time" - minigameCustomization := config.BkBizId == 121 && config.ImmuteDomain == "gamedb.game-record.minigame.db" - dnfCustomization := config.BkBizId == 105 && config.PartitionColumn == "occ_date" - if config.PartitionColumn != "" && !webCustomization && !iegamsCustomization && - !minigameCustomization && !dnfCustomization { + + flag := config.CustomizationCheck() + if flag { // 分区表至少会有一个分区 for _, v := range output.CmdResults[0].TableData { // 如果发现分区字段、分区间隔与规则不符合,需要重新做分区,页面调整了分区规则 @@ -215,6 +208,19 @@ func (config *PartitionConfig) GetDbTableInfo(fromCron bool, host Host) (ptlist return ptlist, nil } +func (config *PartitionConfig) CustomizationCheck() (flag bool) { + // (1)兼容【分区字段为空】的历史问题,对于某些特殊的分区类型,旧系统已经不在页面上支持,所以旧系统有意将分区字段留空, + // 使其无法在页面编辑,避免改变了其他所属分区类别,因此无法核对比较,但不影响新增和删除分区。 + // (2)兼容web、dnf业务的特殊定制类型,分区字段类型为int,但是系统记录为timestamp,因此无法核对比较,但不影响新增和删除分区。 + // (3)兼容minigame业务的特殊定制类型,分区类型为0,但是实际定义与分区类型存在差异,因此无法核对比较,但不影响新增和删除分区。 + var custFlag bool + if val, ok := model.CustimazationMap[config.BkBizId]; ok { + custFlag = config.PartitionColumn == val || config.ImmuteDomain == val + } + flag = config.PartitionColumn != "" && !custFlag + return flag +} + func CheckPartitionExpression(expression, method, column string, partitionType int) (bool, error) { columnWithBackquote := fmt.Sprintf("`%s`", column) switch partitionType { diff --git a/dbm-services/mysql/db-partition/service/cron_basic_func.go b/dbm-services/mysql/db-partition/service/cron_basic_func.go index bbc29144c3..a9b94b902f 100644 --- a/dbm-services/mysql/db-partition/service/cron_basic_func.go +++ b/dbm-services/mysql/db-partition/service/cron_basic_func.go @@ -12,8 +12,6 @@ package service import ( "context" - "dbm-services/common/go-pubpkg/errno" - "dbm-services/mysql/db-partition/util" "encoding/json" "fmt" "log/slog" @@ -23,6 +21,9 @@ import ( "sync" "time" + "dbm-services/common/go-pubpkg/errno" + "dbm-services/mysql/db-partition/util" + "golang.org/x/time/rate" "dbm-services/mysql/db-partition/model" @@ -357,7 +358,8 @@ func GetTendbclusterInstances(cluster string) (map[string][]SpiderNode, int, err domain := tmp[0] port, _ := strconv.Atoi(tmp[1]) cloud, _ := strconv.Atoi(tmp[2]) - address := fmt.Sprintf("%s:%d", domain, port) + // port加1000,去任意中控查询集群信息 + address := fmt.Sprintf("%s:%d", domain, port+1000) var splitCnt int var tdbctlPrimary string // 查询tdbctl diff --git a/dbm-services/mysql/db-partition/service/manage_config.go b/dbm-services/mysql/db-partition/service/manage_config.go index 50d7da0718..fcf5db93d5 100644 --- a/dbm-services/mysql/db-partition/service/manage_config.go +++ b/dbm-services/mysql/db-partition/service/manage_config.go @@ -15,10 +15,14 @@ import ( "errors" "fmt" "regexp" - "strconv" "strings" "time" + "gorm.io/gorm" + "gorm.io/gorm/clause" + + glogger "gorm.io/gorm/logger" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/model" @@ -27,8 +31,9 @@ import ( // GetPartitionsConfig TODO func (m *QueryParititionsInput) GetPartitionsConfig() ([]*PartitionConfigWithLog, int64, error) { - allResults := make([]*PartitionConfigWithLog, 0) - var configTb, logTb, orderBy, ascDesc string + allResults := []*PartitionConfigWithLog{} + var configTb, logTb, orderBy string + var desc bool // Cnt 用于返回匹配到的行数 type Cnt struct { Count int64 `gorm:"column:cnt"` @@ -44,73 +49,83 @@ func (m *QueryParititionsInput) GetPartitionsConfig() ([]*PartitionConfigWithLog default: return nil, 0, errors.New("不支持的db类型") } - where := " 1=1 " + tx := model.DB.Self.Table(configTb).Session(&gorm.Session{}).Where("1=1") + //where := " 1=1 " if m.BkBizId > 0 { - where = fmt.Sprintf("%s and bk_biz_id=%d", where, m.BkBizId) + tx.Where("bk_biz_id=?", m.BkBizId) } if len(m.Ids) != 0 { - var temp = make([]string, len(m.Ids)) - for k, id := range m.Ids { - temp[k] = strconv.FormatInt(id, 10) - } - ids := " and id in (" + strings.Join(temp, ",") + ") " - where = where + ids + tx.Where("id in ?", m.Ids) } if len(m.ImmuteDomains) != 0 { - dns := " and immute_domain in ('" + strings.Join(m.ImmuteDomains, "','") + "') " - where = where + dns + tx.Where("immute_domain in ?", m.ImmuteDomains) } if len(m.DbLikes) != 0 { - dblike := " and dblike in ('" + strings.Join(m.DbLikes, "','") + "') " - where = where + dblike + tx.Where("dblike in ?", m.DbLikes) } if len(m.TbLikes) != 0 { - tblike := " and tblike in ('" + strings.Join(m.TbLikes, "','") + "') " - where = where + tblike + tx.Where("tblike in ?", m.TbLikes) } cnt := Cnt{} - vsql := fmt.Sprintf("select count(*) as cnt from `%s` where %s", configTb, where) - err := model.DB.Self.Raw(vsql).Scan(&cnt).Error - if err != nil { - slog.Error(vsql, "execute error", err) - return nil, 0, err + cntResult := tx.Session(&gorm.Session{}).Select("count(*) as cnt").Find(&cnt) + if cntResult.Error != nil { + slog.Error("sql execute error", cntResult.Error) + return nil, 0, cntResult.Error } + if m.Limit == -1 { m.Limit = cnt.Count } - - limitCondition := fmt.Sprintf("limit %d offset %d", m.Limit, m.Offset) if m.OrderBy == "" { orderBy = "id" - ascDesc = "desc" + desc = true } else { orderBy = m.OrderBy - ascDesc = m.AscDesc + switch m.AscDesc { + case "desc": + desc = true + default: + desc = false + } } - condition := fmt.Sprintf("%s order by %s %s %s", where, orderBy, ascDesc, limitCondition) - /* - 一、ticket_id是非0的整数,则表示,最近一次任务生成了分区单据,单据执行状态就是最近这次任务的状态,需要从dbm ticket_ticket表中获取状态。 - 二、ticket_id是0,表示最近一次任务没有生成分区单据,status状态表示最近这次任务的状态,FAILED或者SUCCEEDED。 - (1)FAILED: 可能因为dry_run获取分区语句失败等,check_info显示错误信息; - (2)SUCCEEDED: 表示dry_run成功,并且没有需要实施的分区操作,无需创建单据。 - 三、ticket_id是NULL,status是NULL,分区规则还没有执行过 - */ - vsql = fmt.Sprintf("SELECT config.*, logs.create_time as execute_time, "+ - "logs.check_info as check_info, "+ - "logs.status as status FROM "+ - "(select * from %s where %s ) AS config LEFT JOIN "+ - "(SELECT log.* FROM %s AS log, "+ - "(SELECT inner_config.id AS config_id, MAX(inner_log.id) AS log_id FROM "+ - "%s AS inner_config LEFT JOIN "+ - "%s AS inner_log ON inner_config.id = inner_log.config_id where "+ - "inner_log.create_time > DATE_SUB(now(),interval 100 day) GROUP BY inner_config.id) "+ - "AS latest_log WHERE log.id = latest_log.log_id) AS logs ON config.id = logs.config_id", - configTb, condition, logTb, configTb, logTb) - err = model.DB.Self.Raw(vsql).Scan(&allResults).Error - if err != nil { - slog.Error(vsql, "execute error", err) - return nil, 0, err + + //order := fmt.Sprintf("%s %s", orderBy, ascDesc) + // 先在partition_config中查出分区配置的相关信息 + //Logger: glogger.Default.LogMode(glogger.Info) + order := clause.OrderByColumn{ + Column: clause.Column{ + Name: orderBy, + }, + Desc: desc, + } + result := tx.Session(&gorm.Session{Logger: glogger.Default.LogMode(glogger.Info)}). + Order(order).Limit(int(m.Limit)).Offset(m.Offset).Find(&allResults) + if result.Error != nil { + slog.Error("sql execute error", result.Error) + return nil, 0, result.Error + } + + logTx := model.DB.Self.Table(logTb) + for _, configResult := range allResults { + logInfo := struct { + ExecuteTime string `gorm:"execute_time"` + Status string `gorm:"status"` + CheckInfo string `gorm:"check_info"` + }{} + logResult := logTx.Session(&gorm.Session{}). + Select("create_time as execute_time,check_info as check_info,status as status"). + Where("config_id = ?", configResult.ID). + Where("create_time > DATE_SUB(now(),interval 100 day)"). + Order("id desc").Limit(1).Find(&logInfo) + if logResult.Error != nil { + slog.Error("sql execute err.", logResult.Error) + return nil, 0, logResult.Error + } + configResult.ExecuteTime = logInfo.ExecuteTime + configResult.Status = logInfo.Status + configResult.CheckInfo = logInfo.CheckInfo } + return allResults, cnt.Count, nil } @@ -126,30 +141,33 @@ func (m *QueryLogInput) GetPartitionLog() ([]*PartitionLog, int64, error) { default: return nil, 0, errors.New("不支持的db类型") } + + tx := model.DB.Self.Session(&gorm.Session{}).Table(logTb).Where("config_id=?", m.ConfigId) + if m.StartTime != "" && m.EndTime != "" { + tx.Where("create_time>? and create_time DATE_SUB(now(),interval 100 day)") + } + // Cnt 用于返回匹配到的行数 type Cnt struct { Count int64 `gorm:"column:cnt"` } - where := fmt.Sprintf(` config_id=%d and create_time> DATE_SUB(now(),interval 100 day) `, m.ConfigId) - if m.StartTime != "" && m.EndTime != "" { - where = fmt.Sprintf(` config_id=%d and create_time>'%s' and create_time<'%s' `, m.ConfigId, m.StartTime, m.EndTime) - } - limitCondition := fmt.Sprintf(" limit %d offset %d ", m.Limit, m.Offset) cnt := Cnt{} - vsql := fmt.Sprintf("select count(*) as cnt from `%s` where %s", logTb, where) - err := model.DB.Self.Raw(vsql).Scan(&cnt).Error - if err != nil { - slog.Error(vsql, "execute error", err) - return nil, 0, err - } - - vsql = fmt.Sprintf("select id, create_time as execute_time, "+ - "check_info, status from %s where %s order by execute_time desc %s", - logTb, where, limitCondition) - err = model.DB.Self.Raw(vsql).Scan(&allResults).Error - if err != nil { - slog.Error(vsql, "execute error", err) - return nil, 0, err + // 使用session函数,开启新的会话查询 + cntResult := tx.Session(&gorm.Session{}).Select("count(*) as cnt").Find(&cnt) + if cntResult.Error != nil { + slog.Error("cnt sql execute error", cntResult.Error) + return nil, 0, cntResult.Error + } + // 使用session函数,开启新的会话查询,避免和上面的查询重复(条件,返回字段) + result := tx.Session(&gorm.Session{}). + Select("id,create_time as execute_time,check_info,status"). + Limit(m.Limit).Offset(m.Offset).Find(&allResults) + if result.Error != nil { + slog.Error("sql execute error", result.Error) + return nil, 0, result.Error } return allResults, cnt.Count, nil } @@ -175,23 +193,19 @@ func (m *DeletePartitionConfigByIds) DeletePartitionsConfig() error { return errors.New("不支持的db类型") } + // 操作行为记录到日志 for _, configID := range m.Ids { CreateManageLog(tbName, logTbName, configID, "Delete", m.Operator) } - var list []string - for _, item := range m.Ids { - list = append(list, strconv.FormatInt(int64(item), 10)) - } - sql := fmt.Sprintf("delete from `%s` where id in (%s) and bk_biz_id = %d", tbName, strings.Join(list, ","), - m.BkBizId) - result := model.DB.Self.Exec(sql) + result := model.DB.Self.Table(tbName).Where("bk_biz_id=?", m.BkBizId).Delete(&PartitionConfig{}, m.Ids) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return errno.PartitionConfigNotExisted } + return nil } @@ -216,28 +230,13 @@ func (m *DeletePartitionConfigByClusterIds) DeletePartitionsConfigByCluster() (e return errors.New("不支持的db类型"), "" } - for _, clusterId := range m.ClusterIds { - var partitionConfig PartitionConfig - query := PartitionConfig{ - BkBizId: m.BkBizId, - ClusterId: clusterId, - } - result2 := model.DB.Self.Table(tbName).Where(&query).First(&partitionConfig) - if result2.Error != nil { - slog.Error("create manage log err", result2.Error) - } else { - CreateManageLog(tbName, logTbName, partitionConfig.ID, - "Delete by cluster", "uninstall_cluster") - } - } + // 以集群维度记录日志 + CreateManageLogByCluster(m.BkBizId, m.ClusterIds, tbName, logTbName, + "Delete by cluster", m.Operator) - var list []string - for _, item := range m.ClusterIds { - list = append(list, strconv.FormatInt(int64(item), 10)) - } - sql := fmt.Sprintf("delete from `%s` where cluster_id in (%s) and bk_biz_id = %d", tbName, strings.Join(list, ","), - m.BkBizId) - result := model.DB.Self.Exec(sql) + result := model.DB.Self.Session(&gorm.Session{}).Table(tbName). + Where("cluster_id in ? and bk_biz_id=?", m.ClusterIds, m.BkBizId). + Delete(&PartitionConfig{}) if result.Error != nil { return result.Error, "" } @@ -483,18 +482,13 @@ func (m *DisablePartitionInput) DisablePartitionConfig() error { default: return errors.New("不支持的db类型") } - var list []string - for _, item := range m.Ids { - list = append(list, strconv.FormatInt(int64(item), 10)) - } db := model.DB.Self.Table(tbName) - result := db. - Where(fmt.Sprintf("id in (%s)", strings.Join(list, ","))). - Update("phase", offline) + result := db.Where("id in ?", m.Ids).Update("phase", offline) if result.Error != nil { return result.Error } + for _, id := range m.Ids { CreateManageLog(tbName, logTbName, id, "Disable", m.Operator) } @@ -519,15 +513,10 @@ func (m *DisablePartitionInput) DisablePartitionConfigByCluster() error { default: return errors.New("不支持的db类型") } - var list []string - for _, item := range m.ClusterIds { - list = append(list, strconv.FormatInt(int64(item), 10)) - } db := model.DB.Self.Table(tbName) result := db. - Where(fmt.Sprintf("cluster_id in (%s)", strings.Join(list, ","))). - Update("phase", offlinewithclu) + Where("cluster_id in ?", m.ClusterIds).Update("phase", offlinewithclu) if result.Error != nil { return result.Error } @@ -555,15 +544,10 @@ func (m *EnablePartitionInput) EnablePartitionConfig() error { default: return errors.New("不支持的db类型") } - var list []string - for _, item := range m.Ids { - list = append(list, strconv.FormatInt(int64(item), 10)) - } db := model.DB.Self.Table(tbName) result := db. - Where(fmt.Sprintf("id in (%s)", strings.Join(list, ","))). - Update("phase", online) + Where("id in ?", m.Ids).Update("phase", online) if result.Error != nil { return result.Error } @@ -591,15 +575,8 @@ func (m *EnablePartitionInput) EnablePartitionByCluster() error { default: return errors.New("不支持的db类型") } - var list []string - for _, item := range m.ClusterIds { - list = append(list, strconv.FormatInt(int64(item), 10)) - - } db := model.DB.Self.Table(tbName) - result := db. - Where(fmt.Sprintf("cluster_id in (%s)", strings.Join(list, ","))). - Update("phase", online) + result := db.Where("cluster_id in ?", m.ClusterIds).Update("phase", online) if result.Error != nil { return result.Error } @@ -677,12 +654,13 @@ func (m *CreatePartitionsInput) checkExistRules(tbName string) (existRules []Exi // CreateManageLog 记录操作日志,日志不对外 func CreateManageLog(dbName string, logTbName string, id int, operate string, operator string) { /* - 1、根据config_id去配置表中查到相关配置信息 + 1、根据config_id去配置表中查到相关配置信息 此处id指的是config_id 2、写入日志表 */ var partitionConfig PartitionConfig partitionConfig.ID = id - model.DB.Self.Table(dbName).First(&partitionConfig) + // 注意 + model.DB.Self.Session(&gorm.Session{}).Table(dbName).First(&partitionConfig) jstring, jerr := json.Marshal(partitionConfig) if jerr != nil { slog.Error("create manage log err", jerr) @@ -701,6 +679,35 @@ func CreateManageLog(dbName string, logTbName string, id int, operate string, op } } +// CreateManageLogByCluster 以集群维度记录日志 +func CreateManageLogByCluster(bkBizId int64, clusterIds []int, tbName string, logTbName string, + operate string, operator string) { + /* + 需要在删除操作之前记录日志,不然查不到元数据信息 + 不是关键日志,故不在意记录后,后续操作做是否执行 + */ + for _, clusterId := range clusterIds { + // var partitionConfigIds []struct{ID int} + // 这里直接声明加初始化,避免为nil 不过实际也可以只声明,后面赋值使用,个人习惯 + partitionConfigIds := []struct{ ID int }{} + query := PartitionConfig{ + BkBizId: bkBizId, + ClusterId: clusterId, + } + selectResult := model.DB.Self.Table(tbName).Where(&query).Find(&partitionConfigIds) + if selectResult.Error != nil { + slog.Error("create manage log err.", selectResult.Error) + } else { + if selectResult.RowsAffected > 0 { + for _, id := range partitionConfigIds { + CreateManageLog(tbName, logTbName, id.ID, + operate, operator) + } + } + } + } +} + // Slice2Map TODO func Slice2Map(s []int) map[int]struct{} { m := make(map[int]struct{}) diff --git a/dbm-services/mysql/db-partition/service/manage_config_object.go b/dbm-services/mysql/db-partition/service/manage_config_object.go index 8eb91206a3..dd1ee24b66 100644 --- a/dbm-services/mysql/db-partition/service/manage_config_object.go +++ b/dbm-services/mysql/db-partition/service/manage_config_object.go @@ -14,9 +14,9 @@ const MysqlPartitionCronLogTable = "mysql_partition_cron_log" // SpiderPartitionCronLogTable TODO const SpiderPartitionCronLogTable = "spider_partition_cron_log" -const online = "online" -const offline = "offline" -const offlinewithclu = "offlinewithclu" +const online = "online" // 启用分区 +const offline = "offline" // 禁用 +const offlinewithclu = "offlinewithclu" // 集群维度的禁用 const extraTime = 15 // MysqlManageLogsTable TODO @@ -83,7 +83,7 @@ type CreatePartitionsInput struct { RemoteHashAlgorithm string `json:"remote_hash_algorithm"` } -// DeletePartitionConfigByIds TODO +// DeletePartitionConfigByIds Ids 是分区配置的主键id type DeletePartitionConfigByIds struct { ClusterType string `json:"cluster_type"` BkBizId int64 `json:"bk_biz_id"` @@ -99,9 +99,10 @@ type DeletePartitionConfigByClusterIds struct { ClusterIds []int `json:"cluster_ids"` } -// DisablePartitionInput TODO +// DisablePartitionInput type DisablePartitionInput struct { ClusterType string `json:"cluster_type"` + BkBizId int64 `json:"bk_biz_id"` Operator string `json:"operator"` Ids []int `json:"ids"` ClusterIds []int `json:"cluster_ids"`