欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go數(shù)據(jù)庫遷移的實(shí)現(xiàn)步驟

 更新時間:2023年07月12日 14:41:14   作者:IguoChan  
本文主要介紹了Go數(shù)據(jù)庫遷移的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

0. 簡介

本文將介紹兩個Go生態(tài)中常見的數(shù)據(jù)庫遷移工具——golang-migrategormigrate。

1. golang-migrate

golang-migrate的官方Github鏈接。它提供了客戶端的方式使用,也可以使用Go SDK調(diào)用的方式使用。其各種安裝方式詳見鏈接。

對于每次遷移而言,都需要有一個遷移文件,遷移文件需要命名為{number}_xxx.up.sql以及{number}_xxx.down.sql,其中{number}是數(shù)字,可以使用migrate create命令產(chǎn)生,如下,-seq表示按順序產(chǎn)生文件:

migrate create -ext sql -dir ./migration_files -seq init_schema 

{number}將會是從1開始的遞增的數(shù)字。如下,默認(rèn)按照時間格式產(chǎn)生,-tz可以設(shè)置時區(qū):

migrate create -ext sql -dir ./migration_files -tz Asia/Shanghai init_schema 

{number}將會是上海時區(qū)的時間格式。反正不管是什么格式,golang-migration按照從小到大的順序依次執(zhí)行。

在實(shí)際運(yùn)行時,遷移時順序運(yùn)行{number}_xxx.up.sql文件,回滾時倒序運(yùn)行{number}_xxx.down.sql。

1.1 通過migrate命令操作

1.1.1 創(chuàng)建sql文件

初始化數(shù)據(jù)庫

我們可以通過安裝migrate工具,然后通過指令進(jìn)行操作如下,生成20230616164949_init.up.sql20230616164949_init.down.sql文件:

$ migrate create -ext sql -dir ./migration_files -tz Asia/Shanghai init       
xxx/migration_files/20230616164949_init.up.sql
xxx/migration_files/20230616164949_init.down.sql

20230616164949_init.up.sql中填寫:

-- ----------------------------
-- Table structure for person
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `age` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

20230616164949_init.down.sql中填寫:

DROP TABLE IF EXISTS `person`; 

新增一列

然后我們給person表新增一個性別gender列,先使用命令創(chuàng)建sql文件:

$ migrate create -ext sql -dir ./migration_files -tz Asia/Shanghai add_gender
xxx/migration_files/20230616165624_add_gender.up.sql
xxx/migration_files/20230616165624_add_gender.down.sql

20230616165624_add_gender.up.sql

ALTER TABLE `person` ADD COLUMN `gender` BIGINT(20) DEFAULT NULL AFTER `age`; 

20230616165624_add_gender.down.sql

ALTER TABLE `person` DROP COLUMN `gender`; 

新增name為index

接下來,我們?yōu)?code>name列創(chuàng)建一個索引,同樣需要用命令創(chuàng)建sql文件:

$ migrate create -ext sql -dir ./migration_files -tz Asia/Shanghai add_index_name                                                                          
xxx/migration_files/20230619104829_add_index_name.up.sql
xxx/migration_files/20230619104829_add_index_name.down.sql

20230619104829_add_index_name.up.sql

ALTER TABLE `person` ADD INDEX `idx_name`(`name`); 

20230619104829_add_index_name.down.sql

ALTER TABLE `person` DROP INDEX `idx_name`; 

此時在遷移文件中有以下文件:

$ ll migration_files
total 48
-rw-r--r--  1 chenyiguo  staff    30B Jun 16 16:55 20230616164949_init.down.sql
-rw-r--r--  1 chenyiguo  staff   396B Jun 16 16:55 20230616164949_init.up.sql
-rw-r--r--  1 chenyiguo  staff    42B Jun 16 17:02 20230616165624_add_gender.down.sql
-rw-r--r--  1 chenyiguo  staff    77B Jun 16 17:01 20230616165624_add_gender.up.sql
-rw-r--r--  1 chenyiguo  staff    43B Jun 19 10:57 20230619104829_add_index_name.down.sql
-rw-r--r--  1 chenyiguo  staff    50B Jun 19 10:57 20230619104829_add_index_name.up.sql

1.1.2 進(jìn)行遷移

一步遷移

我們可以使用如下指令每次執(zhí)行一步遷移:

$ migrate --path ./migration_files --database="mysql://root:IBHojwND.yo@tcp(10.117.49.6:13306)/migration_test?charset=utf8mb4&parseTime=true" -verbose up 1
2023/06/19 11:01:28 Start buffering 20230616164949/u init
2023/06/19 11:01:28 Read and execute 20230616164949/u init
2023/06/19 11:01:28 Finished 20230616164949/u init (read 133.166833ms, ran 286.737042ms)
2023/06/19 11:01:28 Finished after 566.083083ms
2023/06/19 11:01:28 Closing source and database

然后查看表person:

MariaDB [migration_test]> DESC `person`;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(256)        | YES  |     | NULL    |                |
| age   | bigint(20)          | YES  |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.001 sec)

這時候,會發(fā)現(xiàn)數(shù)據(jù)庫會生成一個名為schema_migrations的表,可以看到其只有兩列,其中第一列version表示現(xiàn)階段的版本,比如以上我們只是執(zhí)行了遷移的第一步,所以版本是20230616164949;第二列是dirty,0表示正常,1表示被出錯了,一般而言需要手動處理。

MariaDB [migration_test]> SELECT * FROM `schema_migrations`;
+----------------+-------+
| version        | dirty |
+----------------+-------+
| 20230616164949 |     0 |
+----------------+-------+
1 row in set (0.001 sec)

同樣的,我們可以使用以下指令回滾這一次操作:

$ migrate --path ./migration_files --database="mysql://root:IBHojwND.yo@tcp(10.117.49.6:13306)/migration_test?charset=utf8mb4&parseTime=true" -verbose down 1
2023/06/19 11:12:57 Start buffering 20230616164949/d init
2023/06/19 11:12:57 Read and execute 20230616164949/d init
2023/06/19 11:12:58 Finished 20230616164949/d init (read 238.931375ms, ran 167.683125ms)
2023/06/19 11:12:58 Finished after 552.185792ms
2023/06/19 11:12:58 Closing source and database

可以發(fā)現(xiàn)操作被回滾,整個數(shù)據(jù)庫只保留了schema_migrations表,執(zhí)行了20230616164949_init.down.sql中的指令,person表被刪除了。

整體升級

$ migrate --path ./migration_files --database="mysql://root:IBHojwND.yo@tcp(10.117.49.6:13306)/migration_test?charset=utf8mb4&parseTime=true" -verbose up    
2023/06/19 11:14:52 Start buffering 20230616164949/u init
2023/06/19 11:14:52 Start buffering 20230616165624/u add_gender
2023/06/19 11:14:52 Start buffering 20230619104829/u add_index_name
2023/06/19 11:14:53 Read and execute 20230616164949/u init
2023/06/19 11:14:53 Finished 20230616164949/u init (read 143.943417ms, ran 167.257042ms)
2023/06/19 11:14:53 Read and execute 20230616165624/u add_gender
2023/06/19 11:14:53 Finished 20230616165624/u add_gender (read 463.350333ms, ran 304.728208ms)
2023/06/19 11:14:53 Read and execute 20230619104829/u add_index_name
2023/06/19 11:14:54 Finished 20230619104829/u add_index_name (read 987.893333ms, ran 227.057417ms)
2023/06/19 11:14:54 Finished after 1.391094s
2023/06/19 11:14:54 Closing source and database

這時候可以發(fā)現(xiàn),person表的所有改動都被付諸實(shí)現(xiàn):

MariaDB [migration_test]> DESC `person`;
+--------+---------------------+------+-----+---------+----------------+
| Field  | Type                | Null | Key | Default | Extra          |
+--------+---------------------+------+-----+---------+----------------+
| id     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name   | varchar(256)        | YES  | MUL | NULL    |                |
| age    | bigint(20)          | YES  |     | NULL    |                |
| gender | bigint(20)          | YES  |     | NULL    |                |
+--------+---------------------+------+-----+---------+----------------+
4 rows in set (0.001 sec)

schema_migrations表里的數(shù)據(jù)版本變成了最新的20230619104829,可以發(fā)現(xiàn),此表中并沒有存儲歷史版本。

MariaDB [migration_test]> SELECT * FROM `schema_migrations`;
+----------------+-------+
| version        | dirty |
+----------------+-------+
| 20230619104829 |     0 |
+----------------+-------+
1 row in set (0.000 sec)

同樣,也可以使用down來回滾整個表。

當(dāng)然,golang-migrate還有一些其他的操作,大家可以使用migrate -help命令學(xué)習(xí)。

1.2 通過Go SDK實(shí)現(xiàn)

除了以上通過命令的方式使用golang-migrate,也可以使用其Go SDK的方式運(yùn)用于Go project中。

sql文件的創(chuàng)建這里就不贅述了,當(dāng)然可以為了方便,使用以下的shell文件簡化創(chuàng)建sql的流程:

#!/bin/bash
read -p "Please input sql change tag: " tag
if [ x"${tag}" = x ]; then
  echo "Please input sql change tag!!!"
  exit 1
fi
# TIMEZONE是時區(qū)的環(huán)境變量,默認(rèn) Asia/Shanghai
if [ x"${TIMEZONE}" = x ]; then
  echo "Not set TIMEZONE, set default Asia/Shanghai"
  TIMEZONE="Asia/Shanghai"
fi
migrate create -ext sql -dir ./migration_files -tz "${TIMEZONE}" ${tag}

1.2.1 代碼實(shí)現(xiàn)

package main
import (
   "context"
   "database/sql"
   "errors"
   "fmt"
   "github.com/golang-migrate/migrate/v4"
   "github.com/sirupsen/logrus"
   "os"
   "time"
   _ "github.com/go-sql-driver/mysql"
   _ "github.com/golang-migrate/migrate/v4/database/mysql"
   _ "github.com/golang-migrate/migrate/v4/source/file"
)
const (
   dbUser     = "DB_USER"
   dbPassWord = "DEVOPS_INFRA_PASSWORD"
   dbUrl      = "DB_URL"
)
var (
   username = "root"
   password = "IBHojwND.yo"
   hostname = "10.117.49.6:13306"
   dbname   = "migration_test"
   errUpFailed = errors.New("migration up failed")
)
func dsn(dbName string) string {
   return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true", username, password, hostname, dbName)
}
func createDBIfNotExist() error {
   db, err := sql.Open("mysql", dsn(""))
   if err != nil {
      logrus.Errorf("opening DB err : %+v\n", err)
      return err
   }
   defer db.Close()
   ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   defer cancel()
   res, err := db.ExecContext(ctx, "CREATE DATABASE IF NOT EXISTS "+dbname)
   if err != nil {
      logrus.Errorf("creating DB err: %+v\n", err)
      return err
   }
   no, err := res.RowsAffected()
   if err != nil {
      logrus.Errorf("affected rows err: %+v", err)
      return err
   }
   logrus.Infof("rows affected %d\n", no)
   return nil
}
func migration() (e error) {
   // 新建migrate對象
   m, err := migrate.New("file://migration_files", "mysql://"+dsn(dbname))
   if err != nil {
      logrus.Errorf("new migrate err: %+v", err)
      return err
   }
   // 進(jìn)行up操作
   err = m.Up()
   version, dirty, _ := m.Version()
   if err == nil || err == migrate.ErrNoChange {
      logrus.Infof("migrate up success, version: %+v, dirty: %+v", version, dirty)
      return
   }
   logrus.Errorf("migrate up failed, version: %+v, dirty: %+v, err: %+v", version, dirty, err)
   // 只要up沒有成功,后續(xù)都是失敗
   e = errUpFailed
   // 如果up失敗,嘗試回滾一步
   version, dirty, _ = m.Version()
   err = m.Steps(-1)
   if err == nil || err == os.ErrNotExist {
      logrus.Infof("migrate down -1 success, version: %+v, dirty: %+v", version, dirty)
      return
   }
   logrus.Errorf("migrate down -1 failed, version: %+v, dirty: %+v, err: %+v", version, dirty, err)
   // 如果回滾失敗,判斷是不是因?yàn)閐irty
   er, ok := err.(migrate.ErrDirty)
   if !ok {
      // 不是dirty錯誤
      return
   }
   // 是dirty錯誤,那我們強(qiáng)制設(shè)置version,再利用這個版本進(jìn)行回滾
   err = m.Force(er.Version)
   if err != nil {
      logrus.Printf("migrate force %+v err: %+v", er.Version, err)
      return
   }
   err = m.Steps(-1)
   if err == nil || err == os.ErrNotExist {
      logrus.Printf("migrate down -1 after force success, version: %+v, dirty: %+v", version, dirty)
      return
   }
   logrus.Printf("migrate down -1 after force failed, version: %+v, dirty: %+v, err: %+v", version, dirty, err)
   return
}
func main() {
   // 如果數(shù)據(jù)庫不存在則創(chuàng)建數(shù)據(jù)庫
   err := createDBIfNotExist()
   if err != nil {
      os.Exit(1)
   }
   // migration操作
   err = migration()
   if err != nil {
      os.Exit(1)
   }
}

這樣,程序執(zhí)行后,就能達(dá)到和命令執(zhí)行一樣的效果,實(shí)現(xiàn)數(shù)據(jù)庫的遷移。

2. gormigrate

當(dāng)然,如果我們使用的是gorm,那么推薦使用gromigrate,gorm本身提供了AutoMigrate以及相應(yīng)的Migrator的DDL接口,但是其更著重于ORM層面的功能,在ORM Schema Version Control(數(shù)據(jù)庫版本控制)方面有所欠缺。而gromigrate就是一個輕量化的Schema Migration Helper(遷移助手),基于GORM AutoMigrateMigrator進(jìn)行封裝,用于彌補(bǔ)這一塊的缺失。

golang-migrate不同的是,AutoMigrate會根據(jù)程序中數(shù)據(jù)結(jié)構(gòu)的變化來改變表結(jié)構(gòu),無需自己寫sql文件,我們仿照上述例子,來實(shí)現(xiàn)一遍。

2.1 InitSchema

應(yīng)用于初始化沒有表的場景,可以通過InitSchema函數(shù)實(shí)現(xiàn)注冊函數(shù),注意,這里的注冊函數(shù)只有初始化函數(shù),沒有Rollback操作。

package main
import (
   "context"
   "database/sql"
   "fmt"
   "log"
   "time"
   "github.com/go-gormigrate/gormigrate/v2"
   "gorm.io/driver/mysql"
   "gorm.io/gorm"
   "gorm.io/gorm/schema"
)
type Person struct {
   ID   int64  `gorm:"autoIncrement:true;primaryKey;column:id;type:bigint(20);not null"`
   Name string `gorm:"column:name;type:varchar(64);not null;comment:'姓名'"`
   Age  int    `gorm:"column:age;type:int(11);not null;comment:'年齡'"`
}
const (
   username = "root"
   password = "IBHojwND.yo"
   hostname = "10.117.49.6:13306"
   dbname   = "migration_test"
)
func dsn(dbName string) string {
   return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true", username, password, hostname, dbName)
}
func createDBIfNotExist() error {
   db, err := sql.Open("mysql", dsn(""))
   if err != nil {
      log.Printf("Error %s when opening DB\n", err)
      return err
   }
   defer db.Close()
   ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
   defer cancelfunc()
   res, err := db.ExecContext(ctx, "CREATE DATABASE IF NOT EXISTS "+dbname)
   if err != nil {
      log.Printf("Error %s when creating DB\n", err)
      return err
   }
   no, err := res.RowsAffected()
   if err != nil {
      log.Printf("Error %s when fetching rows", err)
      return err
   }
   log.Printf("rows affected %d\n", no)
   return nil
}
func initScheme(db *gorm.DB) {
   m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{})
   m.InitSchema(func(db *gorm.DB) error {
      err := db.AutoMigrate(
         &Person{},
      )
      if err != nil {
         panic(err)
      }
      return nil
   })
   err := m.Migrate()
   if err != nil {
      panic(err)
   }
}
func main() {
   err := createDBIfNotExist()
   if err != nil {
      panic(err)
   }
   db, err := gorm.Open(mysql.New(mysql.Config{
      DSN:                       dsn(dbname), // DSN data source name
      DefaultStringSize:         256,         // string 類型字段的默認(rèn)長度
      DisableDatetimePrecision:  true,        // 禁用 datetime 精度,MySQL 5.6 之前的數(shù)據(jù)庫不支持
      DontSupportRenameIndex:    true,        // 重命名索引時采用刪除并新建的方式,MySQL 5.7 之前的數(shù)據(jù)庫和 MariaDB 不支持重命名索引
      DontSupportRenameColumn:   true,        // 用 `change` 重命名列,MySQL 8 之前的數(shù)據(jù)庫和 MariaDB 不支持重命名列
      SkipInitializeWithVersion: false,       // 根據(jù)當(dāng)前 MySQL 版本自動配置
   }), &gorm.Config{
      NamingStrategy: &schema.NamingStrategy{
         TablePrefix:   "",
         SingularTable: true,
      },
      //SkipDefaultTransaction: true, // 開啟提高性能,https://gorm.io/docs/transactions.html
   })
   if err != nil {
      panic(err)
   }
   initScheme(db)
}

可以看到,此時的Person結(jié)構(gòu)體:

type Person struct {
   ID   int64  `gorm:"autoIncrement:true;primaryKey;column:id;type:bigint(20);not null"`
   Name string `gorm:"column:name;type:varchar(64);not null;comment:'姓名'"`
   Age  int    `gorm:"column:age;type:int(11);not null;comment:'年齡'"`
}

然后在可以看到生成了兩個表:

MariaDB [migration_test6]> SHOW TABLES;
+---------------------------+
| Tables_in_migration_test6 |
+---------------------------+
| migrations                |
| person                    |
+---------------------------+
2 rows in set (0.000 sec)

其中,person是我們生成的表,其結(jié)構(gòu)和Person結(jié)構(gòu)體一致

MariaDB [migration_test6]> DESC `person`;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| name  | varchar(64) | NO   |     | NULL    |                |
| age   | int(11)     | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.001 sec)

migrations表是遷移版本記錄表,可以發(fā)現(xiàn)其只有一列,記錄的就是版本號,InitSchema成功后版本號是SCHEMA_INIT。

MariaDB [migration_test6]> SELECT * FROM `migrations`;
+-------------+
| id          |
+-------------+
| SCHEMA_INIT |
+-------------+
1 row in set (0.000 sec)

2.2 增量遷移

需要注意的是,當(dāng)使用InitSchema+增量遷移的時候,不能使用同一個實(shí)例對象。

2.2.1 新增一列

比如接下來,我們將Person結(jié)構(gòu)體新增一個屬性Gender表示性別:

type Person struct {
   ID     int64  `gorm:"autoIncrement:true;primaryKey;column:id;type:bigint(20);not null"`
   Name   string `gorm:"column:name;type:varchar(64);not null;comment:'姓名'"`
   Age    int    `gorm:"column:age;type:int(11);not null;comment:'年齡'"`
   Gender int    `gorm:"column:gender;type:int(11);not null;comment:'性別:0-未知,1-男性,2-女性'"`
}

其實(shí)這時候調(diào)用gorm.AutoMigrate就已經(jīng)能夠自動創(chuàng)建列了,但是為了版本的管理,我們建立以下的版本管理:

func migration(db *gorm.DB) {
   m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
      {
         ID: "20230616165624",
         Migrate: func(tx *gorm.DB) error {
            return tx.AutoMigrate(&Person{})
         },
         Rollback: func(tx *gorm.DB) error { return tx.Migrator().DropColumn("person", "gender") },
      },
   })
   if err := m.Migrate(); err != nil {
      log.Fatalf("Could not migrate: %v", err)
   }
   log.Printf("Migration did run successfully")
}

然后在main函數(shù)最后加上migration(db)

func main() {
   ...
   // 初始化
   initScheme(db)
   // 增量遷移
   migration(db)
}

執(zhí)行完之后,person表的結(jié)構(gòu)變?yōu)?/p>

MariaDB [migration_test6]> DESC `person`;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id     | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| name   | varchar(64) | NO   |     | NULL    |                |
| age    | int(11)     | NO   |     | NULL    |                |
| gender | int(11)     | NO   |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
4 rows in set (0.001 sec)

然后會發(fā)現(xiàn)migrations表里變?yōu)閮蓷l:

MariaDB [migration_test6]> SELECT * FROM `migrations`;
+----------------+
| id             |
+----------------+
| 20230616165624 |
| SCHEMA_INIT    |
+----------------+
2 rows in set (0.000 sec)

2.2.2 新增name為index

同樣的,首先修改Person結(jié)構(gòu)體,給Name列加上了名為idx_name的索引:

type Person struct {
   ID     int64  `gorm:"autoIncrement:true;primaryKey;column:id;type:bigint(20);not null"`
   Name   string `gorm:"index:idx_name;column:name;type:varchar(64);not null;comment:'姓名'"`
   Age    int    `gorm:"column:age;type:int(11);not null;comment:'年齡'"`
   Gender int    `gorm:"column:gender;type:int(11);not null;comment:'性別:0-未知,1-男性,2-女性'"`
}

然后新增版本:

func migration(db *gorm.DB) {
   m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
      {
         ID: "20230616165624",
         Migrate: func(tx *gorm.DB) error {
            return tx.AutoMigrate(&Person{})
         },
         Rollback: func(tx *gorm.DB) error { return tx.Migrator().DropColumn("person", "gender") },
      },
      {
         ID: "20230619104829",
         Migrate: func(tx *gorm.DB) error {
            return tx.AutoMigrate(&Person{})
         },
         Rollback: func(tx *gorm.DB) error { return tx.Migrator().DropIndex("person", "idx_name") },
      },
   })
   if err := m.Migrate(); err != nil {
      log.Fatalf("Could not migrate: %v", err)
   }
   log.Printf("Migration did run successfully")
}

執(zhí)行完會發(fā)現(xiàn),person表結(jié)構(gòu)如下:

MariaDB [migration_test6]> DESC `person`;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id     | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| name   | varchar(64) | NO   | MUL | NULL    |                |
| age    | int(11)     | NO   |     | NULL    |                |
| gender | int(11)     | NO   |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
4 rows in set (0.001 sec)

migrations表里會新增一個版本:

MariaDB [migration_test6]> SELECT * FROM `migrations`;
+----------------+
| id             |
+----------------+
| 20230616165624 |
| 20230619104829 |
| SCHEMA_INIT    |
+----------------+
3 rows in set (0.000 sec)

2.2.3 加聯(lián)合索引

假如我們希望加一個名為idx_gender_name的聯(lián)合索引,使用gendername列作為索引,那么需要修改Person結(jié)構(gòu)體如下,一定要在每個相關(guān)字段上標(biāo)注聯(lián)合索引idx_gender_name,并且需要按照先后順序利用priority確定優(yōu)先級,數(shù)字越低,優(yōu)先級越高。

type Person struct {
   ID     int64  `gorm:"autoIncrement:true;primaryKey;column:id;type:bigint(20);not null"`
   Name   string `gorm:"index:idx_name;index:idx_gender_name,priority:2;column:name;type:varchar(64);not null;comment:''姓名''"` // '姓名'
   Age    int    `gorm:"column:age;type:int(11);not null;comment:''年齡''"`                                                      // '年齡'
   Gender int    `gorm:"index:idx_gender_name,priority:1;column:gender;type:int(11);not null;comment:''性別:0-未知,1-男性,2-女性''"`   // '性別:0-未知,1-男性,2-女性'
}

然后同樣加上版本規(guī)劃:

{
   ID: "20230619112345",
   Migrate: func(tx *gorm.DB) error {
      return tx.AutoMigrate(&Person{})
   },
   Rollback: func(tx *gorm.DB) error { return tx.Migrator().DropIndex("person", "idx_gender_name") },
},

可以發(fā)現(xiàn)person的索引如下:

MariaDB [migration_test6]> SHOW INDEX FROM `person`;
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| person |          0 | PRIMARY         |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| person |          1 | idx_name        |            1 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| person |          1 | idx_gender_name |            1 | gender      | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| person |          1 | idx_gender_name |            2 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.000 sec)

可以發(fā)現(xiàn),gormigrate可以實(shí)現(xiàn)數(shù)據(jù)庫的版本遷移,并且是對Go語言友好的。在微服務(wù)中,如果數(shù)據(jù)庫版本管理不是很復(fù)雜,且使用的是gorm組件,那么可以使用gormigrate。

3. 參考文獻(xiàn)

在 Golang 利用 golang-migrate 實(shí)現(xiàn) database migration

Golang后端學(xué)習(xí)筆記 — 3.使用Golang編寫和執(zhí)行數(shù)據(jù)庫遷移

對比 11 個 Go 數(shù)據(jù)庫遷移(migration)工具

Go 語言編程 — gormigrate GORM 的數(shù)據(jù)庫遷移助手

到此這篇關(guān)于Go數(shù)據(jù)庫遷移的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Go數(shù)據(jù)庫遷移的實(shí)現(xiàn)步驟內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn)

    Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn)

    本文主要介紹了Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • golang 字符串切片去重實(shí)例

    golang 字符串切片去重實(shí)例

    這篇文章主要介紹了golang 字符串切片去重實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go Asynq異步任務(wù)處理的實(shí)現(xiàn)

    Go Asynq異步任務(wù)處理的實(shí)現(xiàn)

    Asynq是一個新興的異步任務(wù)處理解決方案,它提供了輕量級的、易于使用的API,本文主要介紹了Go Asynq異步任務(wù)處理的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-06-06
  • goland 設(shè)置注釋模板的過程圖文詳解

    goland 設(shè)置注釋模板的過程圖文詳解

    這篇文章主要介紹了goland 設(shè)置注釋模板的過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-12-12
  • golang 如何通過反射創(chuàng)建新對象

    golang 如何通過反射創(chuàng)建新對象

    這篇文章主要介紹了golang 通過反射創(chuàng)建新對象的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • go語言實(shí)現(xiàn)順序存儲的棧

    go語言實(shí)現(xiàn)順序存儲的棧

    這篇文章主要介紹了go語言實(shí)現(xiàn)順序存儲的棧,實(shí)例分析了Go語言實(shí)現(xiàn)順序存儲的棧的原理與各種常見的操作技巧,需要的朋友可以參考下
    2015-03-03
  • go語言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐

    go語言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐

    MQTT是一個基于客戶端-服務(wù)器的消息發(fā)布/訂閱傳輸協(xié)議。本文主要介紹了go語言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 深入淺出Golang中的sync.Pool

    深入淺出Golang中的sync.Pool

    sync.Pool是可伸縮的,也是并發(fā)安全的,其大小僅受限于內(nèi)存大小。本文主要為大家介紹一下Golang中sync.Pool的原理與使用,感興趣的小伙伴可以了解一下
    2023-03-03
  • Golang Printf,Sprintf,Fprintf 格式化詳解

    Golang Printf,Sprintf,Fprintf 格式化詳解

    這篇文章主要介紹了Golang Printf,Sprintf,Fprintf 格式化詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • RabbitMQ延時消息隊(duì)列在golang中的使用詳解

    RabbitMQ延時消息隊(duì)列在golang中的使用詳解

    延時隊(duì)列常使用在某些業(yè)務(wù)場景,使用延時隊(duì)列可以簡化系統(tǒng)的設(shè)計(jì)和開發(fā)、提高系統(tǒng)的可靠性和可用性、提高系統(tǒng)的性能,下面我們就來看看如何在golang中使用RabbitMQ的延時消息隊(duì)列吧
    2023-11-11

最新評論