MySQL LONGBLOB: Storing Large Binary Data Properly

Store large files in MySQL with LONGBLOB – BLOB type sizes, the max_allowed_packet fix, insert/stream examples, and when files belong on disk instead.

MySQL Longblob

Last updated: July 2026 — rewritten for MySQL 8.x (originally written for 5.6)

The four BLOB types and their real limits

TypeMax size
TINYBLOB255 bytes
BLOB64 KB
MEDIUMBLOB16 MB
LONGBLOB4 GB
CREATE TABLE documents (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    filename VARCHAR(255) NOT NULL,
    mime_type VARCHAR(100) NOT NULL,
    content LONGBLOB NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

The error everyone hits: packet too large

Declaring LONGBLOB is not enough — inserts are capped by max_allowed_packet (default 64 MB in MySQL 8). Larger uploads fail with “Got a packet bigger than ‘max_allowed_packet’ bytes” or a silently dropped connection.

# /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
max_allowed_packet = 256M

Restart MySQL, and remember the client side has the same setting — in PHP/PDO the server value governs, but tools like mysqldump need --max-allowed-packet=256M too. Verify with:

SHOW VARIABLES LIKE 'max_allowed_packet';

Inserting from PHP the right way

Use prepared statements with the LOB parameter type rather than concatenating megabytes into a query string:

$pdo = new PDO($dsn, $user, $pass);
$stmt = $pdo->prepare(
    'INSERT INTO documents (filename, mime_type, content) VALUES (?, ?, ?)'
);
$fp = fopen('/path/report.pdf', 'rb');
$stmt->bindValue(1, 'report.pdf');
$stmt->bindValue(2, 'application/pdf');
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);
$stmt->execute();

Streaming via PDO::PARAM_LOB avoids holding the whole file in PHP memory.

Should the file be in the database at all?

Honest answer: usually not. BLOBs bloat the buffer pool, slow backups, and make replication chatty. My rule: under ~1 MB and needing transactional integrity with the row (signatures, thumbnails, generated PDFs) → BLOB is fine. Bigger or high-traffic files → store on disk or S3-style object storage and keep only the path + checksum in MySQL:

content_path VARCHAR(500), sha256 CHAR(64)

You keep referential integrity where it matters and MySQL stays fast. If you’re on Laravel, that pattern is exactly what Storage::put() + a path column gives you — see Laravel file uploads.

Comments

comments