The zero-dependency successor to MySqlBackup.NET.
A pure-C# MySQL backup & restore engine that speaks the MySQL wire protocol directly β
no MySql.Data, no Connector/NET, no external process. Just bytes on a socket.
The original MySqlBackup.NET has been trusted by the C# community for over a decade to back up and restore MySQL databases. It is excellent β but it is built on top of a MySQL ADO.NET driver (MySql.Data / Connector/NET). That means:
- Every value the server sends is materialized into a
DataReader, boxed into a.NETobject, converted to a string, then re-escaped back into SQL text. The bytes make a round trip through the type system they never needed to take. - You inherit the driver's version constraints, its bugs, its breaking changes, and its memory profile.
- Large tables mean large allocations: a row becomes objects, objects become strings, strings become a
StringBuilder, and the GC pays for all of it.
MySqlBackup.NET.RawBytes throws that whole layer away.
It implements the MySQL client/server protocol itself β handshake, authentication, COM_QUERY, result-set framing, length-encoded integers β and reads raw result bytes straight off the TCP stream into a pooled buffer, transforming them into SQL dump text in a single forward pass. Nothing is boxed. Nothing is converted to a string unless it has to be. For a backup tool, where the job is literally "move bytes from the server into a file," this is the architecture the problem always wanted.
| π Zero dependencies | No MySql.Data, no Connector/NET, no mysqldump.exe. The entire client lives in a handful of .cs files under Wire/. |
| π§ True streaming | Rows are read one wire-packet at a time and written immediately. A 10 GB table dumps in roughly constant memory. |
| β»οΈ Allocation-free hot path | Row buffers are rented from ArrayPool<byte>. Cell values are written directly from the packet buffer β numeric raw, binary as 0xβ¦ hex, text quoted/escaped in place. No byte[][] accumulation, no per-row garbage. |
| π Modern auth built in | mysql_native_password and caching_sha2_password (MySQL 8 default), including the RSA-OAEP public-key full-auth exchange β implemented from scratch, no driver required. |
| π Correct by construction | UTF-8 / utf8mb4 throughout (δΈη π round-trips exactly), UTC TIMESTAMP handling, binary/BLOB/BIT/GEOMETRY as hex, mysqldump-compatible header/footer SET blocks. |
| π Streaming restore too | The restore engine parses a .sql dump from any Stream and executes it statement-by-statement over the same raw connection β quote-, comment-, and /*! β¦ */-aware, without loading the file into memory. |
| π€ mysqldump-compatible output | Dumps restore cleanly via the mysql CLI, and dumps produced by mysqldump / classic MySqlBackup.NET restore cleanly here. |
| π― Verified round-trips | CHECKSUM TABLE is byte-identical between source and restored databases across Unicode, emoji, NULLs, blobs, and large multi-batch tables. |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your application β
βββββββββββββββββ¬βββββββββββββββββββββββββββ¬βββββββββββββββββββ
β β
StreamingDumpEngine StreamingRestoreEngine
(server bytes ββΊ SQL text) (SQL text ββΊ server bytes)
β β
βββββββββββββ¬βββββββββββββββ
β
Wire/ (the from-scratch MySQL client)
ββββββββββββββ¬ββββββββββββ¬βββββββββββββ¬βββββββββββββββββββ
β MySqlConn β Packet β Handshake β ResultSet / β
β (connect/ β (framing, β (native + β ColumnDef β
β auth/query)β lenenc) β sha2 auth) β (type decoding) β
ββββββββββββββ΄ββββββββββββ΄βββββββββββββ΄βββββββββββββββββββ
β
raw TCP socket
β
MySQL server
The library is split into two namespaces:
Wire/β a minimal, self-contained MySQL protocol client. Packet framing with multi-packet (0xFFFFFF) reassembly, length-encoded integers, the v10 handshake, both auth plugins, and result-set parsing with fullenum_field_typesknowledge for emission decisions.Dump/β the engines that turn result bytes into SQL and back:StreamingDumpEngineβ the flagship. A packet-driven state machine that never accumulates rows.StreamingRestoreEngineβ a byte-level SQL tokenizer that streams statements to the server.SqlEscapeβ byte-level mysqldump-convention value escaping.
using MySqlBackup.NET.RawBytes.Wire;
using MySqlBackup.NET.RawBytes.Dump;
using (var conn = new MySqlConn())
{
conn.Open("127.0.0.1", 3306, "root", "password", "my_database");
var engine = new StreamingDumpEngine(conn, conn.RawStream)
{
// All options default to mysqldump-like behaviour
InsertLineBreakBetweenInserts = false, // combined multi-row INSERTs
WriteComments = false, // set true for -- comment blocks
MaxInsertBytes = 512 * 1024
};
using (var file = File.Create("my_database.sql"))
engine.DumpDatabase("my_database", file);
}using (var conn = new MySqlConn())
{
conn.Open("127.0.0.1", 3306, "root", "password", "my_database");
var restore = new StreamingRestoreEngine(conn, conn.RawStream)
{
OnStatementError = (code, msg) =>
{
Console.Error.WriteLine($"MySQL error {code}: {msg}");
return true; // continue past errors; return false to abort
}
};
using (var file = File.OpenRead("my_database.sql"))
restore.RestoreDatabase(file);
}That's the whole API surface for the common case: open, dump, done.
Both the streaming and buffered engines expose the same option surface, mirroring ExportInformations from the classic library so migration is painless.
| Option | Default | Effect |
|---|---|---|
DropTable |
true |
Emit DROP TABLE IF EXISTS before each table |
CreateTable |
true |
Emit CREATE TABLE IF NOT EXISTS β¦ |
DumpRows |
true |
Emit row data as INSERT statements |
InsertLineBreakBetweenInserts |
false |
false β combined one-line batches; true β one value-tuple per line |
MaxInsertBytes |
512 KB |
Soft cap that splits a table's data into multiple INSERT batches |
WriteComments |
false |
Emit human-readable -- Definition of β¦ comment blocks |
RecordDumpTime |
true |
When comments are on, write the -- Dump created on β¦ line (turn off for byte-reproducible dumps) |
RemoveAutoIncrement |
false |
Strip AUTO_INCREMENT=N from CREATE TABLE |
RemoveTableCharset |
false |
Strip DEFAULT CHARSET / CHARACTER SET / COLLATE from CREATE TABLE |
Headers / Footers |
mysqldump block | Session SET boilerplate (charset save, SET NAMES utf8mb4, UTC, FK/UNIQUE off, restore) |
-- InsertLineBreakBetweenInserts = false (default, COMBINED)
INSERT INTO `t` (`a`, `b`) VALUES (1,2), (3,4), (5,6);
-- InsertLineBreakBetweenInserts = true (SPLIT)
INSERT INTO `t` (`a`, `b`) VALUES
(1,2),
(3,4),
(5,6);Every cell is written from the raw wire bytes using the column's declared type β no intermediate string:
- Numeric columns (
INT,DECIMAL,DOUBLE,YEAR, β¦) β the server already sends ASCII digits in the text protocol, so the bytes are piped straight through, unquoted. - Binary columns (
BLOB,BIT,GEOMETRY, binaryCHAR/VARCHARvia charset63) β hex-encoded in place as0xDEADBEEF. - Text columns β wrapped in
'β¦'with mysqldump-convention escaping ('β'', plus\\ \0 \n \r \Z) applied byte-by-byte. Because the escape bytes never collide with UTF-8 continuation bytes, this is both correct and fast forutf8mb4. - NULL β the literal
NULL.
TIMESTAMP correctness is handled at the session level: the engine sets TIME_ZONE='+00:00' before reading rows (matching the UTC line in the header block) and restores the original zone afterward, so timestamps round-trip without shifting between servers.
- Servers: MySQL 5.7, MySQL 8.x (including the
caching_sha2_passworddefault), and MariaDB. - Frameworks: .NET Framework 4.8 and .NET 8+ (the wire layer uses only
System.*primitives;ArrayPool/Spancome fromSystem.Buffers). - Output: compatible with the
mysqlCLI and interoperable with dumps frommysqldumpand the original MySqlBackup.NET.
The classic library wraps a MySqlCommand/MySqlConnection you supply. This one is the connection, so you drop the driver entirely:
// Before β classic MySqlBackup.NET (requires MySql.Data)
using (var conn = new MySqlConnection(connString))
using (var cmd = new MySqlCommand())
using (var mb = new MySqlBackup(cmd))
{
cmd.Connection = conn;
conn.Open();
mb.ExportToFile("dump.sql");
}
// After β MySqlBackup.NET.RawBytes (no driver at all)
using (var conn = new MySqlConn())
{
conn.Open("127.0.0.1", 3306, "root", "password", "db");
new StreamingDumpEngine(conn, conn.RawStream).DumpDatabase("db", File.Create("dump.sql"));
}Option names (InsertLineBreakBetweenInserts, RemoveAutoIncrement, header/footer blocks, β¦) are intentionally kept aligned with ExportInformations so existing configuration maps over directly.
Wire/
MySqlConn.cs Connect, authenticate, run queries; exposes RawStream
Packet.cs Wire framing, length-encoded int/string read & write
Handshake.cs v10 handshake + native & caching_sha2 auth (incl. RSA)
Capabilities.cs Client/server capability flags
ResultSet.cs Column-def parsing, type decoding, buffered result reads
Dump/
StreamingDumpEngine.cs Packet-driven, allocation-free dump state machine
StreamingRestoreEngine.cs Streaming SQL restore engine
SqlEscape.cs Byte-level value escaping
A console test harness (Program.cs) drives the engines through a dozen option scenarios and writes the results to dumps/NN_*.sql for inspection and round-trip verification. The harness is not the product β it is a demonstration and regression check for the engines above.
- Single-call convenience facade (
MySqlBackup.Export(...)/.Import(...)) - TLS connection support
- Per-table and per-row progress events on the public surface
- Optional gzip output stream wrapper
- NuGet packaging for .NET Framework + .NET 8 multi-target
Inspired by and intended as the spiritual successor to the long-serving MySqlBackup.NET by a generation of contributors who made reliable MySQL backups easy for C# developers. This project carries that mission forward with a leaner, driver-free core.
This project is released into the public domain under The Unlicense. You are free to copy, modify, publish, use, compile, sell, or distribute it, for any purpose, commercial or non-commercial, with or without attribution. See LICENSE.
Built for the global C# & MySQL community. Contributions, issues, and benchmarks welcome.