Sebagian data memang bukan teks: hash password, token sesi acak, checksum file, hingga isi file gambar itu sendiri. Untuk data mentah seperti itu MySQL menyediakan keluarga tipe biner — BINARY, VARBINARY, dan BLOB — yang menyimpan byte apa adanya tanpa character set maupun collation. Pada Chapter ini kita akan membandingkan BINARY dengan VARBINARY lewat padding byte nol yang khas, memakai HEX() dan UNHEX() untuk melihat byte yang tersimpan, lalu mempraktikkan pola penyimpanan hash yang dipakai aplikasi nyata.
BINARY vs VARBINARY #
BINARY(n) menyimpan n byte dengan panjang tetap — bila isinya lebih pendek, MySQL menambahkan byte nol (0x00) hingga penuh. VARBINARY(n) menyimpan byte dengan panjang variabel maksimal n tanpa penambahan apa pun. Keduanya adalah kembaran CHAR/VARCHAR, hanya saja isinya byte mentah yang tidak ditafsirkan sebagai karakter. Karena byte nol tidak bisa kita ketik di terminal, kita bekerja memakai fungsi UNHEX() untuk membangun byte dari teks heksadesimal dan HEX() untuk membacanya kembali:
DROP DATABASE IF EXISTS belajar_tipe;
CREATE DATABASE belajar_tipe;
USE belajar_tipe;Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Database changedCREATE TABLE sesi (
id INT,
kode BINARY(8),
token VARBINARY(16)
);
INSERT INTO sesi VALUES (1, UNHEX('DEADBEEF'), UNHEX('CAFEBABE'));
SELECT id,
HEX(kode) AS byte_kode,
HEX(token) AS byte_token,
LENGTH(kode) AS panjang_kode,
LENGTH(token) AS panjang_token
FROM sesi;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
+------+------------------+------------+--------------+---------------+
| id | byte_kode | byte_token | panjang_kode | panjang_token |
+------+------------------+------------+--------------+---------------+
| 1 | DEADBEEF00000000 | CAFEBABE | 8 | 4 |
+------+------------------+------------+--------------+---------------+
1 row in set (0.00 sec)Mari kita bedah hasilnya. Kita memasukkan 4 byte DEADBEEF ke kode BINARY(8) dan 4 byte CAFEBABE ke token VARBINARY(16). Pembacaan HEX() memperlihatkan perbedaan perlakuan: kode tampil sebagai DEADBEEF00000000 — empat byte nol ditambahkan hingga penuh 8 byte — sedangkan token tampil CAFEBABE tanpa tambahan apa pun. Kolom LENGTH mengonfirmasi: 8 byte versus 4 byte. Padding byte nol pada BINARY ini sejajar dengan padding spasi pada CHAR, hanya saja byte nol tidak pernah dipangkas saat dibaca — apa yang tersimpan, itulah yang keluar.
Padding ini punya konsekuensi pada pembanding. Nilai BINARY(8) berisi DEADBEEF00000000 tidak sama dengan 4 byte polos DEADBEEF:
SELECT HEX(kode) = 'DEADBEEF00000000' AS sama_dengan_padding,
HEX(kode) = 'DEADBEEF' AS sama_tanpa_padding
FROM sesi;Output yang Dihasilkan:
+---------------------+--------------------+
| sama_dengan_padding | sama_tanpa_padding |
+---------------------+--------------------+
| 1 | 0 |
+---------------------+--------------------+
1 row in set (0.00 sec)Pembanding pertama menghasilkan 1 karena kedua sisi memang 8 byte identik, sedangkan pembanding kedua menghasilkan 0 — byte nol penambat dihitung sebagai bagian dari data. Inilah alasan VARBINARY jauh lebih umum dipakai untuk token dan identifier acak: panjang isinya bervariasi dan kita tidak ingin byte nol ikut menyusup ke pembanding. BINARY(n) lebih cocok untuk data yang memang selalu berukuran tetap, misalnya hash yang selalu 32 byte.
HEX dan UNHEX sebagai Kacamata #
Dua fungsi ini menjadi pasangan wajib saat bekerja dengan data biner. UNHEX('DEADBEEF') membaca teks heksadesimal dua karakter per byte dan menghasilkan 4 byte mentah; HEX() melakukan kebalikannya dengan deterministik penuh — input yang sama selalu menghasilkan byte yang sama, dan byte yang sama selalu tampil sebagai teks heksadesimal yang sama. Berkat sifat deterministik itu, HEX() aman dipakai untuk memverifikasi isi kolom biner dalam pengujian maupun audit, dan teks heksadesimal menjadi format pengiriman data biner yang lazim (misalnya pada log dan dump).
Sebagai bonus, HEX() juga bisa dipakai untuk melihat representasi byte dari teks biasa. Misalnya HEX('A') menghasilkan 41 (kode ASCII huruf A) — trik yang berguna saat menyelidiki perbedaan halus seperti karakter tersembunyi di data teks.
Keluarga BLOB untuk Data Besar #
Untuk data biner yang bisa besar — gambar, lampiran, dump — keluarga BLOB (Binary Large Object) menyediakan wadah dengan batas yang sama persis dengan keluarga TEXT:
| Tipe | Ukuran maksimal | Contoh pemakaian |
|---|---|---|
TINYBLOB | 255 byte | checksum kecil, flag biner |
BLOB | 65.535 byte | token panjang, gambar kecil |
MEDIUMBLOB | 16.777.215 byte | foto, dokumen PDF |
LONGBLOB | 4.294.967.295 byte | video, berkas besar |
BLOB pada dasarnya adalah VARBINARY tanpa panjang maksimal yang kita tentukan — isinya disimpan variabel sesuai ukuran aslinya. Pola pemakaian paling umum di aplikasi: menyimpan hash password. Fungsi SHA2(teks, 256) menghasilkan hash 64 karakter heksadesimal; dengan UNHEX() kita memampatkannya menjadi 32 byte yang tepat muat di BINARY(32):
CREATE TABLE pengguna (
id INT,
nama VARCHAR(40),
password_hash BINARY(32)
);
INSERT INTO pengguna VALUES
(1, 'Budi', UNHEX(SHA2('rahasia-latihan', 256))),
(2, 'Siti', UNHEX(SHA2('sandi-belajar', 256)));
SELECT id, nama, HEX(password_hash) AS hash_tersimpan FROM pengguna ORDER BY id;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
+------+------+------------------------------------------------------------------+
| id | nama | hash_tersimpan |
+------+------+------------------------------------------------------------------+
| 1 | Budi | 0650DBB2B511B784B2464D6EFA4B132755739FD49598212D29C364732A909293 |
| 2 | Siti | 444FDEEC3865CC301D0FC34A149CC6F13991ACF0892BF8FCC2E574797BDB0F8B |
+------+------+------------------------------------------------------------------+
2 rows in set (0.00 sec)Hash setiap pengguna tersimpan sebagai 32 byte biner dan dibaca kembali sebagai 64 karakter heksadesimal — panjang kolom password_hash yang tepat membuat UNHEX(SHA2(...)) selalu muat tanpa padding. Pola ini hemat setengah ruang dibanding menyimpan teks heksadesimal di CHAR(64), dan pada tabel berjuta baris penghematannya nyata terasa. Untuk verifikasi login, aplikasi cukup menghitung SHA2() dari sandi yang dimasukkan lalu membandingkan UNHEX()-nya dengan kolom ini.
Terakhir, kita bereskan database latihan:
DROP DATABASE belajar_tipe;Output yang Dihasilkan:
Query OK, 2 rows affected (0.00 sec)Referensi #
- The BINARY and VARBINARY Types — MySQL 8.4 Reference Manual
- The BLOB and TEXT Types — MySQL 8.4 Reference Manual
- Data Type Storage Requirements — MySQL 8.4 Reference Manual
Seluruh keluarga tipe data kini sudah kita jelajahi satu per satu. Pertanyaan yang tersisa bersifat praktis: ketika mendesain tabel nyata, tipe mana yang dipilih untuk setiap kolom? Chapter berikutnya merangkum semuanya menjadi kerangka keputusan yang siap dipakai.