在MySQL数据库的维护和管理过程中,数据备份和恢复是一项重要的工作。MySQL官方提供了MySqlDump工具进行数据备份,而开源社区也开发了MySqlBackup.NET这样的备份工具。本文旨在通过性能测试,对比分析这两种工具在不同环境下的表现。
MySqlBackup.NET是一个用C#编写的开源项目,它可以直接作为.NET平台项目的插件使用,支持.NET Framework、.NET Core、.NET Standard等多种.NET平台。它同样支持VB.NET和J#,因为这些语言共享CLR(公共语言运行时)。
自MySqlBackup.NET发布以来,人们一直在讨论其与MySqlDump的性能对比。为了回答这个问题,开发者决定进行一次基准测试。
基准测试在以下环境中进行:
基准测试中,MySqlDump (导出) 和 MySql.exe (导入) 通过MySqlWorkBench v8.0.26执行,而MySqlBackup则是通过一个控制台应用程序(.NET Framework 4.8)执行。
测试的数据库总大小为3.50 GB,包含约1535万条记录。需要注意的是,硬盘类型和模型、MySQL服务器与执行备份/恢复的软件应用之间的距离等因素都会对处理速度产生重大影响。
以下是备份和恢复过程中使用的工具及其所需时间:
过程 | 工具 | 时间 | 文件大小 |
---|---|---|---|
备份1 | MySqlDump | 2分36秒 | 4.66 GB |
备份2 | MySqlDump | 2分33秒 | 4.66 GB |
备份3 | MySqlDump | 2分35秒 | 4.66 GB |
备份4 | MySqlBackup.NET | 7分48秒 | 4.59 GB |
备份5 | MySqlBackup.NET | 7分46秒 | 4.59 GB |
备份6 | MySqlBackup.NET | 7分50秒 | 4.59 GB |
恢复1 | MySql.exe | 8分42秒 | - |
恢复2 | MySql.exe | 8分23秒 | - |
恢复3 | MySql.exe | 8分57秒 | - |
恢复4 | MySqlBackup.NET | 9分44秒 | - |
恢复5 | MySqlBackup.NET | 9分39秒 | - |
恢复6 | MySqlBackup.NET | 9分39秒 | - |
在MySQL中,UTF8和LATIN1是两种常用的字符集。MySqlDump在这两种字符集上的性能可能有所不同。在MySQL 8.0中,默认字符集为utf8mb4。
以下是测试中使用的字符集:
SHOW VARIABLES LIKE '%character%';
以下是测试中使用的CREATE TABLE语句:
CREATE TABLE `tableA` (
`int` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`varchar` VARCHAR(45),
`text` TEXT,
`datetime` DATETIME,
`date` DATE,
`time` TIME,
`decimal` DECIMAL(10, 5),
`tinyint` TINYINT UNSIGNED,
`timestamp` TIMESTAMP,
`char36` CHAR(36),
`binary16` BINARY(16),
`float` FLOAT,
`double` DOUBLE,
`blob` BLOB,
PRIMARY KEY (`int`)
) ENGINE = InnoDB;
以下是测试中使用的INSERT语句:
INSERT INTO `tableA` (`varchar`, `text`, `datetime`, `date`, `time`, `decimal`, `tinyint`, `timestamp`, `char36`, `binary16`, `float`, `double`, `blob`, `bool`)
VALUES (
'GtEva4ijqGoLnFvffBO3dPK1cLT9dWpQ56pzrt4vAkJr0',
'10UQ0F9MDuUM95KOcrED4GoyndiCQcWmILLh2h0uIQtm6',
'2021-09-24 20:40:12',
'2021-09-24',
'20:40:12',
3487.2398,
1,
CURRENT_TIMESTAMP,
'00000000000000000000000000000000',
0x00000000000000000000000000000000,
243.234,
456.456,
0x00000000000000000000000000000000,
1
);
以下是执行备份(MySqlBackup.NET)的控制台应用程序代码:
List<TimeSpan> lstDate = new List<TimeSpan>();
for (int i = 0; i < 3; i++)
{
int round = 1 + i;
Console.WriteLine($"round {round} started...");
DateTime datestart = DateTime.Now;
string constr = $"server=127.0.0.1;user=root;pwd=1234;database=test1;sslmode=none;default command timeout=90000000;";
using (MySqlConnection conn = new MySqlConnection(constr))
{
using (MySqlCommand cmd = new MySqlCommand())
{
conn.Open();
cmd.Connection = conn;
string filepath = System.IO.Path.Combine(Environment.CurrentDirectory, $"{round}.sql");
datestart = DateTime.Now;
cmd.CommandTimeout = 9000;
using (MySqlBackup mb = new MySqlBackup(cmd))
{
mb.ExportInfo.GetTotalRowsMode = GetTotalRowsMethod.Skip;
mb.ExportToFile(filepath);
conn.Close();
}
}
}
DateTime dateend = DateTime.Now;
var ts = dateend - datestart;
lstDate.Add(ts);
}
StringBuilder sb = new StringBuilder();
foreach (var ts in lstDate)
{
string s = $"{ts.Hours}h {ts.Minutes}m {ts.Seconds}s {ts.Milliseconds}ms";
Console.WriteLine($"{ts.Hours}h {ts.Minutes}m {ts.Seconds}s {ts.Milliseconds}ms");
sb.AppendLine(s);
}
System.IO.File.WriteAllText("report_backup.txt", sb.ToString());
以下是执行恢复(MySqlBackup.NET)的控制台应用程序代码:
List<TimeSpan> lstDate = new List<TimeSpan>();
for (int i = 0; i < 3; i++)
{
Console.WriteLine($"round {1 + i} started...");
DateTime datestart = DateTime.Now;
string dbname = "test" + (5 + i);
string constr = $"server=127.0.0.1;user=root;pwd=1234;sslmode=none;";
using (MySqlConnection conn = new MySqlConnection(constr))
{
using (MySqlCommand cmd = new MySqlCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = $"drop database if exists `{dbname}`;";
cmd.ExecuteNonQuery();
cmd.CommandText = $"create database `{dbname}`;";
cmd.ExecuteNonQuery();
cmd.CommandText = $"use `{dbname}`;";
cmd.ExecuteNonQuery();
datestart = DateTime.Now;
using (MySqlBackup mb = new MySqlBackup(cmd))
{
mb.ExportInfo.GetTotalRowsMode = GetTotalRowsMethod.Skip;
mb.ImportFromFile(@"D:\dumps\mysql_data1.sql");
conn.Close();
}
}
}
DateTime dateend = DateTime.Now;
var ts = dateend - datestart;
lstDate.Add(ts);
}
StringBuilder sb = new StringBuilder();
foreach (var ts in lstDate)
{
string s = $"{ts.Hours}h {ts.Minutes}m {ts.Seconds}s {ts.Milliseconds}ms";
Console.WriteLine($"{ts.Hours}h {ts.Minutes}m {ts.Seconds}s {ts.Milliseconds}ms");
sb.AppendLine(s);
}
System.IO.File.WriteAllText("report.txt", sb.ToString());