-
Notifications
You must be signed in to change notification settings - Fork 1
Home
MySqlBackup.NET.RawBytes — Backing Up and Restoring MySQL in C# Without Drivers or Object Conversions
For over a decade, MySqlBackup.NET (created in 2013) has provided a trusted solution for backing up and restoring MySQL databases in C#. Traditionally, it worked on top of an ADO.NET database driver:
- MySql.Data (by Oracle)
- MySqlConnector (MIT)
- Devart dotConnect for MySQL
While these connectors are essential for building standard database-driven applications, using them for a database backup tool comes with massive, unnecessary baggage:
- The MySQL server sends well-formatted, text-protocol raw bytes across the TCP socket.
- The ADO.NET connector reads these bytes and allocates .NET objects (
DateTime,string,decimal, boxed objects). - The backup tool reads the
DataReader, extracts the .NET objects, and calls.ToString()or formats them back into SQL strings. - The strings are appended into a
StringBuilderor written to disk.
From a backup engine's perspective, this conversion cycle:
Consider a single table row with three simple columns:
| Column | Data Type | Value | Text Length |
|---|---|---|---|
Col 1 |
VARCHAR |
Hello |
5 |
Col 2 |
DATETIME |
2026-07-01 10:00:00 |
19 |
Col 3 |
DECIMAL |
99.95 |
5 |
In the MySQL Client/Server text protocol (COM_QUERY), incoming cell values are transmitted as length-encoded byte slices.
The stream looks like this conceptually:
(5)Hello(19)2026-07-01 10:00:00(5)99.95
If we inspect the wire bytes at the network level for "Hello" (length prefix 0x05), here is what travels across the TCP socket:
Binary: 00000101 01001000 01100101 01101100 01101100 01101111
Hexadecimal: 05 48 65 6C 6C 6F
ASCII: 5 (len) H e l l o
Viewing all three columns in hexadecimal:
05 48 65 6C 6C 6F
5 H e l l o
13 32 30 32 36 2D 30 37 2D 30 31 20 31 30 3A 30 30 3A 30 30
19 2 0 2 6 - 0 7 - 0 1 1 0 : 0 0 : 0 0
05 39 39 2E 39 35
5 9 9 . 9 5
Notice something extraordinary? The wire bytes sent by MySQL are already perfectly formatted SQL text!
- The date
2026-07-01 10:00:00is already formatted ASCII. - The number
99.95is already ASCII digits.
Converting 99.95 to a 128-bit .NET decimal structure only to turn around and call .ToString() back into the ASCII characters '9', '9', '.' '9', '5'` is completely wasteful work.
Traditional backup libraries force every byte through the .NET type system:
MySQL Server
└─ Wire Bytes
└─ ADO.NET Driver (allocates & decodes into .NET Objects)
└─ Backup Library (calls .ToString() on every cell)
└─ StringBuilder / String allocations (high GC pressure)
└─ Output Stream / File
MySqlBackup.NET.RawBytes short-circuits this entire path:
MySQL Server
└── Wire Bytes (read directly into a reusable, connection-owned buffer)
└── Output Stream (piped straight through with zero-allocation transformations)
By speaking the MySQL protocol directly:
-
Numeric Columns (
INT,DECIMAL,DOUBLE, etc.): Raw wire bytes pass straight through to the stream without ever touching a managed numeric type. -
Text Columns: Values are escaped byte-by-byte in-place within the incoming buffer (preserving UTF-8 /
utf8mb4multibyte sequences). -
Binary Columns (
BLOB,BIT,BINARY): Encoded directly into SQL hex literals (X'...') using a small, reusable scratch buffer. -
Date & Time Columns: Zero dates (
0000-00-00), microsecond precision (0–6 digits), and negative times pass through exactly as represented by the server, eliminating culture formatting and timezone drift bugs.
Nothing is boxed, nothing is materialized into DataTable objects, and memory usage scales strictly with the largest individual row/statement, not the size of your database.
Unlike early prototypes that only supported base table exports, this modern engine provides enterprise-grade backup and restore capabilities:
- Complete Schema Support: Backs up Tables, Views, Stored Procedures, Functions, Triggers, and Scheduled Events.
-
View Dependency Graph: Automatically resolves nested view dependencies via
information_schema.VIEW_TABLE_USAGEso views restore in the correct topological order. -
InnoDB Consistent Snapshots: Uses
START TRANSACTION WITH CONSISTENT SNAPSHOTinREPEATABLE READmode for non-blocking, transactionally consistent live backups. -
Generated & Invisible Columns: Correctly includes invisible columns while automatically skipping computed
VIRTUALorSTOREDgenerated columns fromINSERTprojections. -
TLS & Hardened Auth: Full TLS encryption support (OS certificate chain validation or optional SHA-256 certificate thumbprint pinning), supporting both
mysql_native_passwordandcaching_sha2_password(including RSA key exchange). -
Stream-Centric Architecture: Export directly to any writable
Stream(e.g.FileStream,GZipStream, network pipes) and restore from any readableStream. - Zero Runtime Dependencies: Targets .NET Framework 4.8, .NET Standard 2.0, and .NET 8+ without any third-party NuGet packages.
using System;
using System.IO;
using MySqlBackup.RawBytes;
var connOptions = new ConnectionOptions
{
Host = "127.0.0.1",
Port = 3306,
User = "root",
Password = "your_password",
Database = "app_database",
UseTls = true // Enabled by default
};
using (var connection = MySqlConnection.Open(connOptions))
{
var options = new BackupOptions
{
Consistency = BackupConsistency.InnoDbSnapshot, // Consistent repeatable-read snapshot
MaxInsertBytes = 1024 * 1024, // 1 MB batched INSERTs
Views = true,
Routines = true,
Triggers = true,
Events = true
};
using (var file = File.Create("app_backup.sql"))
{
new BackupEngine(connection).Export("app_database", file, options);
}
}
Console.WriteLine("Backup complete.");The restore engine features an integrated, streaming SQL tokenizer (SqlScriptReader) that executes dumps statement-by-statement. It natively handles multi-character DELIMITER definitions, UTF-8 BOMs, conditional executable comments (/*!40101 ... */), and backslash escaping.
using System;
using System.IO;
using MySqlBackup.RawBytes;
var connOptions = new ConnectionOptions
{
Host = "127.0.0.1",
Port = 3306,
User = "root",
Password = "your_password",
Database = "target_database"
};
using (var connection = MySqlConnection.Open(connOptions))
{
var restoreOptions = new RestoreOptions
{
FailOnWarnings = true // Abort if a statement produces warnings (e.g., truncation)
};
using (var file = File.OpenRead("app_backup.sql"))
{
long executedStatements = new RestoreEngine(connection).Restore(file, restoreOptions);
Console.WriteLine($"Restored {executedStatements} statements successfully.");
}
}MySqlBackup.NET.RawBytes returns to first principles: a backup tool's fundamental job is to move raw bytes between MySQL's network stream and storage. By bypassing the ADO.NET abstraction layer, you achieve lightning-fast backups, constant low memory usage, and zero driver dependency version conflicts.