Welcome to MikeDaDev's Blog – notes on Java, backend & system design.

Explore
MikeDaDev's Blog

#database

Things I've written about #database
  • vận hành database cluster & tính Idempotent

    Script bảo trì hay nâng cấp database phân tán đang chạy thì đứt kết nối, giờ chạy lại có sao không? Bài này nói về cách tự động hoá vận hành cluster, cách thiết kế State Machine cho từng node và vì sao Idempotent là nguyên tắc SRE không được bỏ qua.

  • Discord: từ Cassandra sang ScyllaDB

    Nhìn lại chặng đường Discord lưu hàng nghìn tỷ tin nhắn: từ lúc MongoDB hết chịu nổi, qua Apache Cassandra, rồi chuyển hẳn sang ScyllaDB với mô hình thread-per-core, hết JVM GC pause, p99 latency đọc còn khoảng 15ms và số node giảm từ 177 xuống 72.

  • Figma: scale PostgreSQL với Horizontal Sharding

    Figma làm Horizontal Sharding cho PostgreSQL thế nào: nhóm bảng theo colo, hash shard key để tránh hotspot, proxy DBProxy định tuyến bằng SQL AST, shard "logic" bằng view trước khi tách vật lý, và lần failover đầu tiên chỉ mất khoảng 10 giây sẵn sàng một phần.

  • Database Sharding system design

    Lúc nào thì một node SQL không còn gánh nổi tải? Bài này nói về cách ước tính dung lượng nhanh (back-of-the-envelope), cách chọn sharding key, chuyện transaction phân tán và kinh nghiệm từ các hệ thống tài chính.

  • zero-downtime database migration

    Làm Zero-Downtime Migration cho database: ma trận lock như AccessExclusiveLock, chiến lược Expand-Contract 5 pha, Shadow Reads (dark launching), Throttled Keyset Backfill và so sánh gh-ost với pg_repack.

  • case study Shopify: Redis to MySQL

    Black Friday 2025 đạt đỉnh 5.1 triệu USD/phút, và đó cũng là mùa đầu tiên Shopify giữ chỗ tồn kho bằng MySQL thay cho Redis. Vì sao bỏ Redis, vì sao câu UPDATE trừ số lượng quen thuộc không đủ, và thiết kế một dòng cho mỗi đơn vị hàng với SKIP LOCKED chạy ra sao.

  • CDC với Debezium & cache invalidation

    Change Data Capture (CDC) với Debezium nhìn từ bên trong: PostgreSQL logical decoding (pgoutput) chạy ra sao, vì sao dual-write dính partial failure và race condition, cách dùng Outbox Event Router (SMT), chống cache stampede và canh replication slot trên production.

  • jOOQ vs Hibernate JPA

    Vì sao nhiều team làm hệ thống tài chính cân nhắc jOOQ bên cạnh Hibernate? Chi phí ngầm của ORM, Type-safe SQL của jOOQ, những chỗ Hibernate 6 đã bắt kịp, và kiến trúc Hybrid dùng cả hai.

  • acid in sql

    Nếu database SQL là cái két sắt thì ACID (Atomicity, Consistency, Isolation, Durability) là bộ khoá giữ cho mọi giao dịch an toàn. Nhờ nó, dù hệ thống sập nguồn hay gặp lỗi bất ngờ, thao tác dữ liệu hoặc chạy trọn vẹn, hoặc hoàn tác hết, dữ liệu không bao giờ rơi vào trạng thái nửa vời.

  • in sql / oracle

    tối ưu SQL trong Oracle

    Ghi chép tối ưu Oracle SQL cho Database Architect và Principal Engineer: Cost-Based Optimizer (CBO) chạy ra sao, 5 kiểu Index Access Path, Hash Join tràn PGA, cách đọc DBMS_XPLAN với ALLSTATS LAST, và cách khoá Plan bằng SQL Plan Management (SPM).

  • in sql / oracle

    oracle ROWNUM

    ROWNUM trong Oracle chạy bên trong thế nào: vì sao ROWNUM > 1 luôn ra rỗng, COUNT STOPKEY trong execution plan giúp dừng quét sớm ra sao, và nên chọn subquery ROWNUM, window function ROW_NUMBER() hay cú pháp ANSI OFFSET-FETCH của Oracle 12c+.

  • hibernate ORM

    Hibernate ORM bên trong chạy thế nào: 4 trạng thái vòng đời của Entity (Transient, Persistent, Detached, Removed), Dirty Checking tự động qua Loaded Snapshots, First-Level vs Second-Level Cache, và cách tiết kiệm bộ nhớ với @Transactional(readOnly = true).

  • Criteria API trong Hibernate

    Viết dynamic query trong Java enterprise cho đàng hoàng: Hibernate 6 SQM chạy bên dưới ra sao, JPA Metamodel Generator, Spring Data Specification, cái bẫy fetch join với N+1 và phân trang, kèm bảng so sánh Criteria API, Specification, QueryDSL và jOOQ.

  • @ManyToMany trong JPA

    @ManyToMany trong JPA/Hibernate hoạt động ra sao: vì sao Hibernate xóa sạch bảng nối rồi insert lại (Write Amplification), vì sao không thêm được thuộc tính phụ (metadata), và cách làm dùng được trên production: tách thành hai @OneToMany qua Explicit Join Entity với @EmbeddedId và @MapsId.

  • @OneToMany & @ManyToOne trong JPA

    Mấy cái bẫy hay gặp với @OneToMany và @ManyToOne trong JPA/Hibernate: EAGER ngầm, N+1 query và cách xử lý bằng EntityGraph hay BatchSize, lỗi MultipleBagFetchException do Cartesian Product, và StackOverflowError vì lỡ dùng Lombok @Data.

  • @OneToOne trong JPA

    Đào sâu quan hệ @OneToOne trong Hibernate & JPA: vì sao FetchType.LAZY "tịt" ở Non-Owning side và kéo theo N+1, cách dùng chung khoá chính với @MapsId, Bytecode Enhancement, và vì sao gắn Lombok @Data lên Entity là anti-pattern.