Generate UUID in MySQL
MySQL has built-in UUID support since 5.x. UUID() generates a v1 UUID. MySQL 8.0+ adds UUID_TO_BIN() for efficient BINARY(16) storage and BIN_TO_UUID() for retrieval.
Quick Reference
| Function | Version | MySQL | Use Case |
|---|---|---|---|
| UUID() | v1 | 5.x+ | Quick generation — returns VARCHAR(36) |
| UUID_TO_BIN(UUID(), 1) | v1 (reordered) | 8.0+ | Efficient storage — BINARY(16), time-bit reordered |
| BIN_TO_UUID(id, 1) | any | 8.0+ | Convert BINARY(16) back to UUID string |
| DEFAULT (UUID_TO_BIN(UUID(), 1)) | v1 | 8.0+ | Auto-generate UUID on INSERT |
Primary Implementation
-- ── Generate a UUID ──────────────────────────────────────────
SELECT UUID();
-- → 6ccd780c-baba-1026-9564-0040f4311e29 (v1, VARCHAR)
-- ── Best practice: store as BINARY(16) ───────────────────────
-- UUID_TO_BIN(uuid, 1) reorders the time bits for better index locality
-- The second argument (1) enables "swap_flag" — moves the time-high bits
-- to the front, making sequential UUIDs sort correctly in B-tree indexes
CREATE TABLE orders (
id BINARY(16) NOT NULL DEFAULT (UUID_TO_BIN(UUID(), 1)),
customer VARCHAR(100) NOT NULL,
total DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
-- ── Insert without specifying ID (auto-generated) ────────────
INSERT INTO orders (customer, total) VALUES ('Alice', 99.99);
-- ── Insert with explicit UUID ─────────────────────────────────
INSERT INTO orders (id, customer, total)
VALUES (UUID_TO_BIN(UUID(), 1), 'Bob', 149.99);
-- ── Query — convert BINARY(16) back to UUID string ───────────
SELECT BIN_TO_UUID(id, 1) AS id, customer, total
FROM orders;
-- ── Find by UUID string ───────────────────────────────────────
SELECT BIN_TO_UUID(id, 1) AS id, customer
FROM orders
WHERE id = UUID_TO_BIN('6ccd780c-baba-1026-9564-0040f4311e29', 1);
All Approaches
Simple VARCHAR(36) — MySQL 5.x compatible
-- Simple approach — works on MySQL 5.x
-- Downside: VARCHAR(36) uses 36 bytes vs 16 bytes for BINARY(16)
-- Also causes B-tree index fragmentation with random UUIDs
CREATE TABLE users (
id VARCHAR(36) NOT NULL DEFAULT (UUID()),
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
SELECT id, name FROM users;
BINARY(16) with swap_flag — MySQL 8.0+ recommended
-- BINARY(16) with swap_flag=1 — best for high-insert-rate tables
-- swap_flag reorders time bits so sequential UUIDs are adjacent in the index
-- This eliminates B-tree page splits and dramatically improves INSERT performance
CREATE TABLE events (
id BINARY(16) NOT NULL DEFAULT (UUID_TO_BIN(UUID(), 1)),
event_type VARCHAR(50) NOT NULL,
payload JSON,
created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
INDEX idx_created (created_at)
);
-- Generate UUID in application and pass it in
-- (recommended for idempotent inserts)
INSERT INTO events (id, event_type, payload)
VALUES (UUID_TO_BIN('6ccd780c-baba-1026-9564-0040f4311e29', 1), 'order.created', '{"orderId": 42}');
-- Read back as UUID string
SELECT BIN_TO_UUID(id, 1) AS id, event_type, created_at
FROM events
ORDER BY created_at DESC
LIMIT 10;
Stored procedure — generate and return UUID
DELIMITER $$
CREATE PROCEDURE create_order(
IN p_customer VARCHAR(100),
IN p_total DECIMAL(10,2),
OUT p_id VARCHAR(36)
)
BEGIN
SET p_id = UUID();
INSERT INTO orders (id, customer, total)
VALUES (UUID_TO_BIN(p_id, 1), p_customer, p_total);
END$$
DELIMITER ;
-- Call the procedure
CALL create_order('Alice', 99.99, @order_id);
SELECT @order_id AS created_order_id;
Common Mistakes
Storing UUIDs as VARCHAR(36) in high-traffic tables
VARCHAR(36) uses 36 bytes per row vs 16 bytes for BINARY(16). More importantly, random UUIDs as primary keys cause B-tree index fragmentation — every INSERT goes to a random page, causing constant page splits and poor cache utilization. Use BINARY(16) with UUID_TO_BIN(UUID(), 1).
Forgetting the swap_flag argument in UUID_TO_BIN()
UUID_TO_BIN(UUID()) without the second argument stores the UUID as-is — random bytes, no time ordering. Use UUID_TO_BIN(UUID(), 1) to reorder the time bits for sequential inserts.
Using UUID() in WHERE clauses without UUID_TO_BIN()
If your id column is BINARY(16), you must convert the string in your WHERE clause: WHERE id = UUID_TO_BIN('...', 1). Comparing a BINARY(16) column to a plain string will not use the index.
How It Works
MySQL's UUID() generates a version 1 UUID — it encodes the current timestamp (100-nanosecond intervals since Oct 15, 1582) plus a random node ID. It is unique across time and space but leaks timing information.
UUID_TO_BIN(uuid, 1) converts the 36-char string to 16 bytes and reorders the time components so that UUIDs generated close together are stored adjacent in the B-tree index — dramatically improving INSERT performance on large tables.
Output Formats
UUID()
6ccd780c-baba-1026-9564-0040f4311e29
UUID_TO_BIN(UUID(), 1)
BINARY(16) — 16 bytes
BIN_TO_UUID(id, 1)
6ccd780c-baba-1026-9564-0040f4311e29
Best Practices
Use BINARY(16) with UUID_TO_BIN(UUID(), 1) for production tables.
Generate UUIDs in your application layer for idempotent inserts — pass them to MySQL rather than relying on DEFAULT (UUID()).
Always use BIN_TO_UUID(id, 1) in SELECT queries to return human-readable UUIDs.
Performance
BINARY(16) with swap_flag=1 gives near-sequential insert performance — comparable to auto-increment integers. Without the swap flag, random UUIDs cause severe B-tree fragmentation on tables with millions of rows.
Index size: BINARY(16) = 16 bytes vs VARCHAR(36) = 36 bytes — 55% smaller indexes, better cache utilization.
Version Requirements
UUID()MySQL 5.x+UUID_TO_BIN()MySQL 8.0+BIN_TO_UUID()MySQL 8.0+DEFAULT (UUID_TO_BIN(...))MySQL 8.0.13+Security
MySQL's UUID() generates a v1 UUID — it encodes the server's MAC address and timestamp. This leaks server identity and timing information.
For security-sensitive IDs (session tokens, API keys), generate UUID v4 in your application layer using a CSPRNG and pass it to MySQL — don't rely on UUID().