Skip to content

Commit 9fa0667

Browse files
ylgeekerzhangzhw8
authored andcommitted
feat(mysql): dbbackup支持rocksdb备份数据导入 #6991
1 parent 6c5f87b commit 9fa0667

File tree

9 files changed

+425
-61
lines changed

9 files changed

+425
-61
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ pre-*-bkcodeai
1111

1212
bkcodeai.json
1313
package-lock.json
14-
14+
*.swp
1515
### PreCI ###
16-
.codecc
16+
.codecc

dbm-services/mysql/db-tools/mysql-dbbackup/cmd/subcmd_load.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func loadData(cnf *config.BackupConfig, backupType string) error {
7777

7878
metaInfo, err := backupexe.ParseJsonFile(indexPath)
7979
if err != nil {
80+
logger.Log.Errorf("can not parse index file:%s, errmsg:%s", indexPath, err)
8081
return err
8182
}
8283
if backupType != "" && metaInfo.BackupType != backupType {

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/cst/const.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const (
1717
)
1818

1919
const (
20-
StorageEnginRocksdb = "rocksdb"
20+
StorageEngineRocksdb = "rocksdb"
2121
)
2222

2323
// backup role: dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/mysql.go

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func BuildDumper(cnf *config.BackupConfig, storageEngine string) (dumper Dumper,
6767
return nil, err
6868
}
6969

70-
if cst.StorageEnginRocksdb == storageEngine {
70+
if cst.StorageEngineRocksdb == storageEngine {
7171
dumper = &PhysicalRocksdbDumper{
7272
cfg: cnf,
7373
}

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_physical_rocksdb.go

Lines changed: 82 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,33 @@ import (
1919
"dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util"
2020
)
2121

22+
// PhysicalRocksdbDumper physical rocksdb dumper
2223
type PhysicalRocksdbDumper struct {
2324
cfg *config.BackupConfig
25+
backupLogfile string
2426
dbbackupHome string
2527
checkpointDir string
2628
mysqlVersion string
2729
isOfficial bool
2830
rocksdbCmd string
2931
storageEngine string
32+
mysqlRole string
33+
masterHost string
34+
masterPort int
3035
backupStartTime time.Time
3136
backupEndTime time.Time
3237
}
3338

39+
// buildArgs construct the instruction parameters for data recovery.
3440
func (p *PhysicalRocksdbDumper) buildArgs() []string {
3541

3642
targetPath := filepath.Join(p.cfg.Public.BackupDir, p.cfg.Public.TargetName())
3743

3844
args := []string{
39-
fmt.Sprintf("--host=%s", p.cfg.Public.MysqlHost),
40-
fmt.Sprintf("--port=%d", p.cfg.Public.MysqlPort),
4145
fmt.Sprintf("--user=%s", p.cfg.Public.MysqlUser),
4246
fmt.Sprintf("--password=%s", p.cfg.Public.MysqlPasswd),
47+
fmt.Sprintf("--host=%s", p.cfg.Public.MysqlHost),
48+
fmt.Sprintf("--port=%d", p.cfg.Public.MysqlPort),
4349
fmt.Sprintf("--checkpoint_dir=%s", p.checkpointDir),
4450
fmt.Sprintf("--backup_dir=%s", targetPath),
4551
"--stream=disabled",
@@ -56,6 +62,7 @@ func (p *PhysicalRocksdbDumper) buildArgs() []string {
5662
return args
5763
}
5864

65+
// initConfig init config
5966
func (p *PhysicalRocksdbDumper) initConfig(mysqlVersion string) error {
6067
if p.cfg == nil {
6168
return errors.New("rocksdb physical dumper config missed")
@@ -68,55 +75,80 @@ func (p *PhysicalRocksdbDumper) initConfig(mysqlVersion string) error {
6875
}
6976

7077
p.dbbackupHome = filepath.Dir(cmdPath)
71-
db, err := mysqlconn.InitConn(&p.cfg.Public)
7278

79+
// connect to the mysql and obtain the base information
80+
db, err := mysqlconn.InitConn(&p.cfg.Public)
7381
if err != nil {
82+
logger.Log.Errorf("can not connect to the mysql, host:%s, port:%d, errmsg:%s",
83+
p.cfg.Public.MysqlHost, p.cfg.Public.MysqlPort, err)
7484
return err
7585
}
7686

87+
defer func() {
88+
_ = db.Close()
89+
}()
90+
7791
p.mysqlVersion, p.isOfficial = util.VersionParser(mysqlVersion)
7892
p.storageEngine, err = mysqlconn.GetStorageEngine(db)
7993

8094
if err != nil {
95+
logger.Log.Errorf("can not get the storage engine from the mysql, host:%s, port:%d, errmsg:%s",
96+
p.cfg.Public.MysqlHost, p.cfg.Public.MysqlPort, err)
8197
return err
8298
}
99+
100+
// keep the storage engine name is lower
83101
p.storageEngine = strings.ToLower(p.storageEngine)
102+
p.mysqlRole = strings.ToLower(p.cfg.Public.MysqlRole)
84103

85-
defer func() {
86-
_ = db.Close()
87-
}()
104+
// if the current node is slave, obtain the master ip and port
105+
if p.mysqlRole == cst.RoleSlave || p.mysqlRole == cst.RoleRepeater {
106+
p.masterHost, p.masterPort, err = mysqlconn.ShowMysqlSlaveStatus(db)
107+
if err != nil {
108+
logger.Log.Errorf("can not get the master host and port from the mysql, host:%s, port:%d, errmsg:%s",
109+
p.cfg.Public.MysqlHost, p.cfg.Public.MysqlPort, err)
110+
return err
111+
}
112+
}
88113

89-
p.checkpointDir = fmt.Sprintf("%s/MyRocks_checkpoint", p.cfg.Public.BackupDir)
90-
p.rocksdbCmd = "/bin/" + cst.ToolMyrocksHotbackup
114+
// set the base config
115+
p.checkpointDir = filepath.Join(p.cfg.Public.BackupDir, "MyRocks_checkpoint")
116+
p.rocksdbCmd = filepath.Join("bin", cst.ToolMyrocksHotbackup)
91117
BackupTool = cst.ToolMyrocksHotbackup
92118
return nil
93119
}
94120

121+
// Execute Perform data recovery operations.
95122
func (p *PhysicalRocksdbDumper) Execute(enableTimeOut bool) error {
96123
p.backupStartTime = time.Now()
97124
defer func() {
98125
p.backupEndTime = time.Now()
99126
}()
100127

101-
if p.storageEngine != cst.StorageEnginRocksdb {
102-
err := fmt.Errorf("%s engine not support", p.storageEngine)
128+
// the storage engine must be rocksdb
129+
if p.storageEngine != cst.StorageEngineRocksdb {
130+
err := fmt.Errorf("unsupported engine:%s, host:%s, port:%d", p.storageEngine,
131+
p.cfg.Public.MysqlHost, p.cfg.Public.MysqlPort)
103132
logger.Log.Error(err)
104133
return err
105134
}
106135

136+
// pre-created checkpoint dir
107137
_, err := os.Stat(p.checkpointDir)
108138
if os.IsNotExist(err) {
139+
logger.Log.Infof("the checkpoint does not exist, will create it. checkpoint:%s", p.checkpointDir)
109140
err = os.MkdirAll(p.checkpointDir, 0755)
110141
}
111142

112143
if err != nil {
113-
logger.Log.Errorf("failed to create checkpoint(%s), err-msg:%s", p.checkpointDir, err)
144+
logger.Log.Errorf("can not create the checkpoint:%s, errmsg:%s", p.checkpointDir, err)
114145
return err
115146
}
116147

117148
binPath := filepath.Join(p.dbbackupHome, p.rocksdbCmd)
118149
args := p.buildArgs()
119150

151+
// perform the dump operation
120152
var cmd *exec.Cmd
121153
backupCmd := fmt.Sprintf(`%s %s`, binPath, strings.Join(args, " "))
122154

@@ -134,60 +166,50 @@ func (p *PhysicalRocksdbDumper) Execute(enableTimeOut bool) error {
134166
cmd = exec.Command("sh", "-c", backupCmd)
135167
}
136168

137-
backuplogFilename := fmt.Sprintf("%s_backup_%d_%d.log", p.storageEngine, p.cfg.Public.MysqlPort, int(time.Now().Weekday()))
138-
rocksdbBackuplogFilename := filepath.Join(p.dbbackupHome, "logs", backuplogFilename)
169+
// create a dumper log file to store the log of the dumper command
170+
p.backupLogfile = fmt.Sprintf("dumper_%s_%s_%d_%d.log", p.storageEngine,
171+
cst.ToolMyrocksHotbackup, p.cfg.Public.MysqlPort, int(time.Now().Weekday()))
172+
173+
p.backupLogfile = filepath.Join(p.dbbackupHome, "logs", p.backupLogfile)
139174

140-
outFile, err := os.Create(rocksdbBackuplogFilename)
175+
// pre-created dump log file
176+
outFile, err := os.Create(p.backupLogfile)
141177

142178
if err != nil {
143-
logger.Log.Error("create log file failed: ", err)
179+
logger.Log.Errorf("can not create the dumper log file, file name:%s, errmsg:%s", p.backupLogfile, err)
144180
return err
145181
}
146182

147183
defer func() {
148184
_ = outFile.Close()
149185
}()
150186

187+
// redirect standard output and error messages to a file
151188
cmd.Stdout = outFile
152189
cmd.Stderr = outFile
153-
logger.Log.Info("rocksdb backup command: ", cmd.String())
154190

191+
// perform the dump command
155192
err = cmd.Run()
156193
if err != nil {
157-
logger.Log.Error("run rocksdb physical backup failed: ", err)
194+
logger.Log.Errorf("can not run the rocksdb physical dumper command:%s, engine:%s, errmsg:%s",
195+
backupCmd, p.storageEngine, err)
158196
return err
159197
}
160198

199+
logger.Log.Infof("dump rocksdb success, command:%s", cmd.String())
161200
return nil
162201
}
163202

203+
// PrepareBackupMetaInfo generate the metadata of database backup
164204
func (p *PhysicalRocksdbDumper) PrepareBackupMetaInfo(cnf *config.BackupConfig) (*dbareport.IndexContent, error) {
165-
db, err := mysqlconn.InitConn(&cnf.Public)
166-
if err != nil {
167-
return nil, errors.WithMessage(err, "IndexContent")
168-
}
169-
170-
defer func() {
171-
_ = db.Close()
172-
}()
173-
174-
storageEngine, err := mysqlconn.GetStorageEngine(db)
175-
if err != nil {
176-
return nil, err
177-
}
178-
179-
storageEngine = strings.ToLower(storageEngine)
180-
181-
if storageEngine != "rocksdb" {
182-
logger.Log.Errorf("unknown storage engine(%s)", storageEngine)
183-
return nil, nil
184-
}
185205

206+
// parse the binglog position
186207
xtrabackupBinlogInfoFileName := filepath.Join(cnf.Public.BackupDir, cnf.Public.TargetName(), "xtrabackup_binlog_info")
187208
xtrabackupSlaveInfoFileName := filepath.Join(cnf.Public.BackupDir, cnf.Public.TargetName(), "xtrabackup_slave_info")
188209

189210
tmpFileName := filepath.Join(cnf.Public.BackupDir, cnf.Public.TargetName(), "tmp_dbbackup_go.txt")
190211

212+
// obtain the qpress command path
191213
exepath, err := os.Executable()
192214
if err != nil {
193215
return nil, err
@@ -200,30 +222,38 @@ func (p *PhysicalRocksdbDumper) PrepareBackupMetaInfo(cnf *config.BackupConfig)
200222
BinlogInfo: dbareport.BinlogStatusInfo{},
201223
}
202224

203-
if masterStatus, err := parseXtraBinlogInfo(qpressPath, xtrabackupBinlogInfoFileName, tmpFileName); err != nil {
225+
// parse the binlog
226+
masterStatus, err := parseXtraBinlogInfo(qpressPath, xtrabackupBinlogInfoFileName, tmpFileName)
227+
if err != nil {
228+
logger.Log.Errorf("do not parse xtrabackup binlog file, file name:%s, errmsg:%s",
229+
xtrabackupBinlogInfoFileName, err)
204230
return nil, err
205-
} else {
206-
metaInfo.BinlogInfo.ShowMasterStatus = masterStatus
207-
metaInfo.BinlogInfo.ShowMasterStatus.MasterHost = cnf.Public.MysqlHost
208-
metaInfo.BinlogInfo.ShowMasterStatus.MasterPort = cnf.Public.MysqlPort
209231
}
210232

211-
if mysqlRole := strings.ToLower(cnf.Public.MysqlRole); mysqlRole == cst.RoleSlave || mysqlRole == cst.RoleRepeater {
212-
if slaveStatus, err := parseXtraSlaveInfo(qpressPath, xtrabackupSlaveInfoFileName, tmpFileName); err != nil {
233+
// save the master node status
234+
metaInfo.BinlogInfo.ShowMasterStatus = masterStatus
235+
metaInfo.BinlogInfo.ShowMasterStatus.MasterHost = cnf.Public.MysqlHost
236+
metaInfo.BinlogInfo.ShowMasterStatus.MasterPort = cnf.Public.MysqlPort
237+
238+
// parse the information of the master node
239+
if p.mysqlRole == cst.RoleSlave || p.mysqlRole == cst.RoleRepeater {
240+
slaveStatus, err := parseXtraSlaveInfo(qpressPath, xtrabackupSlaveInfoFileName, tmpFileName)
241+
242+
if err != nil {
243+
logger.Log.Errorf("do not parse xtrabackup slave information, xtrabackup file:%s, errmsg:%s",
244+
xtrabackupSlaveInfoFileName, err)
213245
return nil, err
214-
} else {
215-
metaInfo.BinlogInfo.ShowSlaveStatus = slaveStatus
216-
masterHost, masterPort, err := mysqlconn.ShowMysqlSlaveStatus(db)
217-
if err != nil {
218-
return nil, err
219-
}
220-
metaInfo.BinlogInfo.ShowSlaveStatus.MasterHost = masterHost
221-
metaInfo.BinlogInfo.ShowSlaveStatus.MasterPort = masterPort
222246
}
247+
248+
metaInfo.BinlogInfo.ShowSlaveStatus = slaveStatus
249+
metaInfo.BinlogInfo.ShowSlaveStatus.MasterHost = p.masterHost
250+
metaInfo.BinlogInfo.ShowSlaveStatus.MasterPort = p.masterPort
223251
}
224252

253+
// teh mark indicating whether the update is a full backup or not
225254
metaInfo.JudgeIsFullBackup(&cnf.Public)
226255
if err = os.Remove(tmpFileName); err != nil {
256+
logger.Log.Errorf("do not delete the tmp file, file name:%s, errmsg:%s", tmpFileName, err)
227257
return &metaInfo, err
228258
}
229259

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_load.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package backupexe
33
import (
44
"dbm-services/mysql/db-tools/mysql-dbbackup/pkg/config"
55
"dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport"
6+
"strings"
67
)
78

89
// ExecuteLoad execute load backup command
@@ -11,7 +12,8 @@ func ExecuteLoad(cnf *config.BackupConfig, indexFileContent *dbareport.IndexCont
1112
return envErr
1213
}
1314

14-
loader, err := BuildLoader(cnf, indexFileContent.BackupType, indexFileContent.BackupTool)
15+
backupStorageEngine := strings.ToLower(indexFileContent.StorageEngine)
16+
loader, err := BuildLoader(cnf, indexFileContent.BackupType, indexFileContent.BackupTool, backupStorageEngine)
1517
if err != nil {
1618
return err
1719
}

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/grant.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func BackupGrant(cfg *config.Public) error {
2525

2626
rows, err := db.Query("select user, host from mysql.user where user not in ('ADMIN','yw','dba_bak_all_sel')")
2727
if err != nil {
28-
logger.Log.Error("can't send query to Mysql server %v\n", err)
28+
logger.Log.Errorf("can't send query to Mysql server %v\n", err)
2929
return err
3030
}
3131
defer rows.Close()

dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ type Loader interface {
1818
}
1919

2020
// BuildLoader TODO
21-
func BuildLoader(cnf *config.BackupConfig, backupType string, backupTool string) (loader Loader, err error) {
21+
func BuildLoader(cnf *config.BackupConfig, backupType string, backupTool string, storageEngine string) (loader Loader, err error) {
22+
2223
if strings.ToLower(backupType) == cst.BackupLogical {
2324
if backupTool == cst.ToolMysqldump {
2425
// mysqldump 共用 LogicalLoad 参数
@@ -46,8 +47,15 @@ func BuildLoader(cnf *config.BackupConfig, backupType string, backupTool string)
4647
if err := validate.GoValidateStruct(cnf.PhysicalLoad, false, false); err != nil {
4748
return nil, err
4849
}
49-
loader = &PhysicalLoader{
50-
cnf: cnf,
50+
51+
if cst.StorageEngineRocksdb == storageEngine {
52+
loader = &PhysicalRocksdbLoader{
53+
cfg: cnf,
54+
}
55+
} else {
56+
loader = &PhysicalLoader{
57+
cnf: cnf,
58+
}
5159
}
5260
} else {
5361
logger.Log.Error(fmt.Sprintf("Unknown BackupType: %s", backupType))

0 commit comments

Comments
 (0)