使用go备份StarRocks建表语句方法实例

 更新时间:2023年12月08日 09:07:04   作者:CDH煎炒烹炸  
这篇文章主要为大家介绍了使用go备份StarRocks建表语句方法实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Golang从StarRocks集群中导出所有数据库的表结构

使用StarRocks的非稳定版的最新版本,为了防止因为未知BUG造成集群无法恢复,或者为了定期备份生产集群的元数据信息。都需要一个能够从集群导出表结构的脚本或者是程序。这里选择使用Golang来从StarRocks集群中导出所有数据库的表结构。

步骤

  • 获取所有的Database

  • 遍历每一个Database获取所有的表

  • 遍历每一张表获取每一张表的建表语句

  • 因为View的输出结果和Table的数据结果不同,需要进行分类判断。

  • 将数据写入文件,文件能直接使用source命令执行。

可执行的详细代码

如下:

package main
import (
 "database/sql"
 "errors"
 "fmt"
 "log"
 "os"
 _ "github.com/go-sql-driver/mysql"
 "github.com/spf13/pflag"
 "github.com/spf13/viper"
)
type Databases struct {
 Database string
}
type Tables struct {
 Tables string
}
type CreateTable struct {
 Table                string
 CreateString         string
 Character_set_client string
 Collation_connection string
}
const (
 defaultStarRocks  = "127.0.0.1"
 defaultPort       = 9030
 defaultUserName   = "root"
 defaultOutputFile = "ddl.sql"
)
func main() {
 var starRocks, userName, password, outputFile string
 var port int
 var includedSys bool
 pflag.StringVarP(&starRocks, "starrocks", "s", defaultStarRocks, "The address of starrocks without a database name.")
 pflag.IntVarP(&port, "port", "p", defaultPort, "The port of starrocks")
 pflag.StringVarP(&userName, "userName", "u", defaultUserName, "The use name of starrocks")
 pflag.StringVarP(&password, "password", "w", "", "The password of starrocks")
 pflag.StringVarP(&outputFile, "outputFile", "o", defaultOutputFile, "The output file name.")
 pflag.BoolVarP(&includedSys, "includedSys", "i", false, "Included the system database or not, default is not.")
 pflag.Parse()
 viper.BindPFlag("starrocks", pflag.Lookup("starrocks"))
 viper.BindPFlag("port", pflag.Lookup("port"))
 viper.BindPFlag("userName", pflag.Lookup("userName"))
 viper.BindPFlag("password", pflag.Lookup("password"))
 viper.BindPFlag("outputFile", pflag.Lookup("outputFile"))
 viper.BindPFlag("includedSys", pflag.Lookup("includedSys"))
 jdbcURL := fmt.Sprintf("%s:%s@tcp(%s:%d)/", userName, password, starRocks, port)
 sysDB := []string{"_statistics_", "information_schema", "sys"}
 databases := getDatabases(jdbcURL)
 if _, err := os.Stat(outputFile); err == nil {
  // File exists, remove it
  errRemove := os.Remove(outputFile)
  if errRemove != nil {
   log.Println("Error removing file:", errRemove)
   return
  }
  log.Println("File removed successfully.")
 }
 for _, db := range databases {
  if !includedSys && containsElement(sysDB, db) {
   continue
  }
  writeToFile(outputFile, fmt.Sprintf("-- Database: %s\n", db))
  writeToFile(outputFile, fmt.Sprintf("use %s;\n", db))
  tables := getTables(jdbcURL, db)
  for _, table := range tables {
   if table != "" {
    createTable := getCreateTable(jdbcURL, db, table)
    for k, v := range createTable {
     var objectType string
     if v == "VIEW" {
      objectType = "View"
     } else if v == "TABLE" {
      objectType = "Table"
     }
     writeToFile(outputFile, fmt.Sprintf("-- %s: %s\n", objectType, table))
     writeToFile(outputFile, fmt.Sprintf("-- Create %s: \n", objectType))
     writeToFile(outputFile, fmt.Sprintf("%s\n", k))
    }
   }
  }
 }
}
func writeToFile(outputFile string, s string) {
 file, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
 if err != nil {
  fmt.Println("Error opening file:", err)
  return
 }
 defer file.Close()
 _, err = file.Write([]byte(s))
 if err != nil {
  fmt.Println("Error writing to file:", err)
  return
 }
}
func containsElement(list []string, target string) bool {
 for _, element := range list {
  if element == target {
   return true
  }
 }
 return false
}
func getDatabases(jdbcURL string) []string {
 db, err := sql.Open("mysql", jdbcURL)
 if err != nil {
  log.Fatal(err)
 }
 defer db.Close()
 res, err := db.Query("show databases")
 if err != nil {
  log.Fatal(err)
 }
 var databases []string
 for res.Next() {
  var ds Databases
  err := res.Scan(&ds.Database)
  if err != nil {
   log.Fatal(err)
  }
  databases = append(databases, ds.Database)
 }
 return databases
}
func getTables(jdbcURL, dbName string) []string {
 db, err := sql.Open("mysql", jdbcURL+dbName)
 if err != nil {
  log.Fatal(err)
 }
 defer db.Close()
 res, err := db.Query("show tables")
 if err != nil {
  log.Fatal(err)
 }
 var tables []string
 for res.Next() {
  var ts Tables
  err := res.Scan(&ts.Tables)
  if err != nil {
   log.Fatal(err)
  }
  tables = append(tables, ts.Tables)
 }
 return tables
}
func getCreateTable(jdbcURL, dbName, tableName string) map[string]string {
 db, err := sql.Open("mysql", jdbcURL+dbName)
 if err != nil {
  log.Fatal(err)
 }
 defer db.Close()
 res, err := db.Query("show create table " + tableName)
 if err != nil {
  log.Fatal(err)
 }
 createTables := make(map[string]string)
 for res.Next() {
  var ct CreateTable
  cs, _ := res.Columns()
  err := errors.New("")
  if len(cs) == 4 {
   // for view
   err = res.Scan(&ct.Table, &ct.CreateString, &ct.Character_set_client, &ct.Collation_connection)
   if err != nil {
    log.Fatal(err)
   }
   createTables[ct.CreateString] = "VIEW"
  } else if len(cs) == 2 {
   // for table
   err = res.Scan(&ct.Table, &ct.CreateString)
   if err != nil {
    log.Fatal(err)
   }
   createTables[ct.CreateString] = "TABLE"
  }
 }
 return createTables
}

结果样例

执行完成后,结果样例:

-- Database: test
use test;
-- Table: test_table
-- Create Table: 
CREATE TABLE `test_table` (
  `day` date NULL COMMENT "天",
  `id` varchar(65533) NULL COMMENT "id",
  `amount` double NULL COMMENT "值",
  `insert_time` varchar(65533) NULL COMMENT "数据插入时间"
) ENGINE=OLAP 
UNIQUE KEY(`day`, `id`)
PARTITION BY RANGE(`day`)
(PARTITION p20231020 VALUES [("2023-10-20"), ("2023-10-21")),
PARTITION p20231021 VALUES [("2023-10-21"), ("2023-10-22")),
PARTITION p20231022 VALUES [("2023-10-22"), ("2023-10-23")),
PARTITION p20231023 VALUES [("2023-10-23"), ("2023-10-24")),
PARTITION p20231024 VALUES [("2023-10-24"), ("2023-10-25")),
PARTITION p20231025 VALUES [("2023-10-25"), ("2023-10-26")),
PARTITION p20231027 VALUES [("2023-10-27"), ("2023-10-28")),
PARTITION p20231028 VALUES [("2023-10-28"), ("2023-10-29")),
PARTITION p20231029 VALUES [("2023-10-29"), ("2023-10-30")),
PARTITION p20231030 VALUES [("2023-10-30"), ("2023-10-31")))
DISTRIBUTED BY HASH(`id`)
PROPERTIES (
"replication_num" = "1",
"dynamic_partition.enable" = "false",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.time_zone" = "Asia/Shanghai",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "1",
"dynamic_partition.history_partition_num" = "0",
"in_memory" = "false",
"enable_persistent_index" = "false",
"replicated_storage" = "true",
"compression" = "LZ4"
);
-- View: test_view
-- Create View: 
CREATE VIEW `test_view` (`day`, `id`, `amount`, `insert_time`) AS SELECT `test`.`test_table`.`day`, `test`.`test_table`.`id`,`test`.`test_table`.`amount`, `test`.`test_table`.`insert_time`
FROM `test`.`test_table`
WHERE `test`.`test_table`.`day` >= '2023-11-07' ;

未实现:

  • 备份MV

  • 备份UDF

  • 备份用户角色和grant信息。

  • 备份Catalog的创建语句。

以上代码使用go版本为1.21.4,其他版本可能会有些不同,更多关于go备份StarRocks建表语句的资料请关注脚本之家其它相关文章!

相关文章

  • Go语言等待组sync.WaitGrou的使用示例

    Go语言等待组sync.WaitGrou的使用示例

    本文主要介绍了Go语言等待组sync.WaitGrou的使用示例,sync.WaitGroup只有3个方法,Add(),Done(),Wait(),下面就来具体的介绍一下如何使用,感兴趣的可以了解一下
    2024-08-08
  • golang开发go包依赖管理godep使用教程

    golang开发go包依赖管理godep使用教程

    这篇文章主要为大家介绍了golang开发go包依赖管理godep使用教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • Go Run, Go Build, Go Install的区别

    Go Run, Go Build, Go Install的区别

    本文深入探讨Go语言中gorun、gobuild和goinstall三个常用命令的功能区别和适用场景,文中通过具体代码示例,详细解释了各命令的使用方式及其应用场景,帮助开发者高效利用这些工具
    2024-10-10
  • Golang Defer关键字特定操作详解

    Golang Defer关键字特定操作详解

    defer是Go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源、关闭数据库连接、断开socket连接、解锁一个加锁的资源,这篇文章主要介绍了golang中的defer函数理解,需要的朋友可以参考下
    2023-03-03
  • golang调用蓝兔支付实现网上支付功能

    golang调用蓝兔支付实现网上支付功能

    支付宝、微信的网上支付需要营业执照个人无法直接使用,如果个人需要实现网上支付功能,目前大部分应该是都是依赖第三方聚合支付来实现,本文就来介绍一下如何调用蓝兔支付实现网上支付功能,有需要的可以参考下
    2023-09-09
  • golang http使用踩过的坑与填坑指南

    golang http使用踩过的坑与填坑指南

    这篇文章主要介绍了golang http使用踩过的坑与填坑指南,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go语言基础学习教程

    Go语言基础学习教程

    这篇文章主要介绍了Go语言基础知识,包括基本语法、语句、数组等的定义与用法,需要的朋友可以参考下
    2016-07-07
  • Go语言切片前或中间插入项与内置copy()函数详解

    Go语言切片前或中间插入项与内置copy()函数详解

    这篇文章主要介绍了Go语言切片前或中间插入项与内置copy()函数详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结

    Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结

    这篇文章主要介绍了Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结,本文直接给出操作代码,同时对代码加上了详细注释,需要的朋友可以参考下
    2014-11-11
  • golang中实现graphql请求的方法

    golang中实现graphql请求的方法

    这篇文章主要介绍了如何在golang中实现graphql请求,在本文中,我们介绍了如何使用gqlgen来构建GraphQL服务,需要的朋友可以参考下
    2023-04-04

最新评论