Skip to content
ITFROMZERO - Share tobe shared!
  • Window
    • Software
    • Windows 10
  • Linux
    • Centos
    • Ubuntu
    • MonitoringHệ thống giám sát trên Linux
  • Virtualization
    • VMware
    • Docker
  • Database
    • MySQL
    • Cassandra
  • Dev
    • Git
    • Python
  • Hardware
  • Tiếng Việt
    • Tiếng Việt
    • English
    • 日本語
  • Window
    • Software
    • Windows 10
  • Linux
    • Centos
    • Ubuntu
    • MonitoringHệ thống giám sát trên Linux
  • Virtualization
    • VMware
    • Docker
  • Database
    • MySQL
    • Cassandra
  • Dev
    • Git
    • Python
  • Hardware
  • Tiếng Việt
    • Tiếng Việt
    • English
    • 日本語
  • Facebook
Posted inMySQL

Xử lý lỗi treo MySQL do Metadata Locking: Đừng để một lệnh ALTER làm sập hệ thống

Posted by By IT From Zero Tháng 8 16, 2026
MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

Table of Contents

Toggle
  • Bối cảnh: Khi lệnh ALTER TABLE biến thành “cơn ác mộng” production
  • Tái hiện lỗi Metadata Locking trong 3 bước
    • Bước 1: Chuẩn bị dữ liệu
    • Bước 2: Tạo một transaction “treo” (Session 1)
    • Bước 3: Chạy lệnh ALTER (Session 2)
  • Cơ chế hoạt động: Tại sao MySQL lại hành xử như vậy?
  • Cách “cứu net” khi Database bị treo
    • 1. Tìm kiếm bằng SHOW PROCESSLIST
    • 2. Dùng Performance Schema để tìm “thủ phạm”
    • 3. Giải cứu nhanh với bảng sys
  • Kinh nghiệm thực chiến: Phòng bệnh hơn chữa bệnh

Bối cảnh: Khi lệnh ALTER TABLE biến thành “cơn ác mộng” production

Tưởng tượng bạn vừa chạy một lệnh ALTER TABLE để thêm cột status vào bảng orders. Trên môi trường staging, lệnh này chạy mất chưa đến 1 giây. Nhưng ngay khi bạn nhấn Enter trên production, Slack bắt đầu nổ thông báo lỗi 504 Gateway Timeout. CPU database nhảy vọt lên 90%, và mọi truy vấn vào bảng orders bỗng dưng đứng hình.

Mình từng nếm trái đắng này với một database MySQL 8.0 nặng khoảng 50GB, chứa hơn 40 triệu record. Thủ phạm không phải là khóa dòng (row lock) thông thường, mà là Metadata Locking (MDL). Đây là cơ chế bảo vệ cấu trúc bảng của MySQL. Khi có một transaction đang đọc dữ liệu, MySQL sẽ chặn mọi thay đổi schema để đảm bảo tính nhất quán.

Nút thắt nằm ở đây: Chỉ cần một lệnh SELECT chạy ngầm quá lâu hoặc một transaction “quên” commit, lệnh ALTER TABLE của bạn sẽ phải xếp hàng chờ. Tệ hơn, lệnh ALTER này lại đứng chắn đầu hàng, khiến tất cả các truy vấn SELECT, INSERT đến sau cũng bị treo theo. Kết quả là toàn bộ ứng dụng bị tê liệt.

Tái hiện lỗi Metadata Locking trong 3 bước

Để trị được bệnh, chúng ta cần hiểu cách nó phát tác. Bạn có thể mô phỏng tình huống này ngay trên máy cá nhân với hai cửa sổ terminal.

Bước 1: Chuẩn bị dữ liệu

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
) ENGINE=InnoDB;

INSERT INTO users (name) VALUES ('An'), ('Bình'), ('Chi');

Bước 2: Tạo một transaction “treo” (Session 1)

Mở session đầu tiên, bắt đầu một transaction nhưng tuyệt đối không COMMIT.

START TRANSACTION;
SELECT * FROM users WHERE id = 1; 
-- Giữ nguyên session này, đừng tắt cũng đừng gõ thêm gì.

Bước 3: Chạy lệnh ALTER (Session 2)

Tại cửa sổ thứ hai, hãy thử thêm một cột mới.

ALTER TABLE users ADD COLUMN email VARCHAR(255);

Lúc này, Session 2 sẽ đứng im. Nếu bạn mở thêm Session 3 và chạy một lệnh SELECT đơn giản, nó cũng sẽ bị treo. Chào mừng bạn đến với thế giới của Metadata Locking.

Cơ chế hoạt động: Tại sao MySQL lại hành xử như vậy?

Từ bản 5.5.3, MySQL dùng MDL để quản lý quyền truy cập vào cấu trúc bảng. Có hai loại khóa bạn cần phân biệt:

  • Shared Metadata Lock (SU): Kích hoạt khi bạn đọc hoặc ghi dữ liệu (SELECT, INSERT…). Nhiều người có thể giữ khóa này cùng lúc.
  • Exclusive Metadata Lock (X): Kích hoạt khi thay đổi cấu trúc (ALTER, DROP…). Chỉ duy nhất một người được giữ khóa này.

Trong ví dụ trên, Session 1 đang giữ Shared Lock. Session 2 muốn lấy Exclusive Lock nên phải xếp hàng chờ. Oái oăm là khi Exclusive Lock đang chờ, nó sẽ ưu tiên chặn luôn tất cả các Shared Lock mới. Đây chính là hiệu ứng domino khiến hệ thống sập nhanh chóng.

Một sai lầm phổ biến là để giá trị lock_wait_timeout mặc định. MySQL để con số này là 31,536,000 giây (tức là 1 năm!). Điều này nghĩa là lệnh ALTER sẽ đợi đến khi nào server sập thì thôi. Mình khuyên bạn nên hạ xuống khoảng 60 giây.

-- Kiểm tra cấu hình hiện tại
SHOW VARIABLES LIKE 'lock_wait_timeout';

-- Giới hạn thời gian chờ xuống 60s để bảo vệ hệ thống
SET SESSION lock_wait_timeout = 60;

Cách “cứu net” khi Database bị treo

Khi thấy hệ thống bắt đầu chậm, đừng vội restart MySQL. Việc này chỉ làm mọi chuyện tệ hơn vì quá trình recovery sau khi crash sẽ rất lâu.

1. Tìm kiếm bằng SHOW PROCESSLIST

Kiểm tra xem có bao nhiêu connection đang ở trạng thái Waiting for table metadata lock.

SHOW FULL PROCESSLIST;

Lưu ý: Lệnh này chỉ cho thấy ai đang đợi, không chỉ ra được ai là người đang giữ khóa.

2. Dùng Performance Schema để tìm “thủ phạm”

Trên MySQL 5.7 trở lên, đây là công cụ mạnh mẽ nhất. Trước hết, hãy bật giám sát MDL:

UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES' 
WHERE NAME = 'wait/lock/metadata/sql/mdl';

Sau đó, chạy query này để tìm chính xác ID của thread đang chặn mọi thứ:

SELECT 
    OBJECT_NAME, LOCK_TYPE, LOCK_STATUS, THREAD_ID, PROCESSLIST_ID
FROM performance_schema.metadata_locks
WHERE LOCK_STATUS = 'GRANTED';

3. Giải cứu nhanh với bảng sys

Nếu bạn lười gõ query dài, bảng sys có sẵn một view rất trực quan:

SELECT * FROM sys.schema_table_lock_waits;

Nhìn vào cột blocking_pid, tìm ID đó và KILL nó ngay lập tức để giải phóng bảng:

-- Ví dụ PID tìm được là 456
KILL 456;

Kinh nghiệm thực chiến: Phòng bệnh hơn chữa bệnh

Sau nhiều lần xử lý sự cố trên các hệ thống lớn, mình rút ra 4 quy tắc vàng:

  • Dùng công cụ Online Schema Change: Với bảng trên 10GB, đừng bao giờ dùng ALTER TABLE trực tiếp. Hãy dùng pt-online-schema-change của Percona hoặc gh-ost của GitHub. Chúng tạo bảng tạm và copy dữ liệu dần dần, không gây khóa bảng lâu.
  • Kiểm tra transaction dài: Trước khi migration, hãy kiểm tra xem có cronjob hay report nào đang chạy không. Một lệnh SELECT kéo dài 10 phút sẽ là ngòi nổ cho MDL lock.
  • Chọn giờ thấp điểm: Dù công cụ có tốt đến đâu, hãy thực hiện vào lúc ít traffic nhất (thường là 2-3 giờ sáng).
  • Thiết lập timeout ngắn: Luôn set lock_wait_timeout cho session chạy ALTER. Thà để lệnh migration thất bại còn hơn để nó làm treo cả website.

Xử lý Metadata Lock đòi hỏi sự bình tĩnh. Khi thấy hàng trăm kết nối bị treo, hãy nhớ: tìm đúng ID giữ khóa và xử lý nó, thay vì hoảng loạn restart server.

Share:
Tags:
DatabaseDevOpsMetadata LockingMySQLperformance tuning
Last updated on Tháng 8 16, 2026

Post navigation

Previous Post
Artificial Intelligence tutorial - IT technology blog Xây dựng AI Agent tự động nghiên cứu thị trường với Browser-use và LangChain
Next Post
Làm chủ lnav: Kỹ thuật xem và phân tích log real-time đỉnh cao trên Linux Monitoring tutorial - IT technology blog
Bài viết mới
  • Tự viết Seccomp Profile cho Docker: Siết chặt System Calls từ Dev đến Prod
  • Real-time không cần Message Broker: Tận dụng LISTEN và NOTIFY trong PostgreSQL kết hợp WebSocket
  • Hướng dẫn cài đặt Traefik v3 trên Fedora Server với Podman: Tự động hóa SSL và Routing
  • Tối ưu độ trễ và xử lý triệt để Bufferbloat trên Linux bằng CAKE và FQ-CoDel
  • Hướng Dẫn Tự Động Hóa Database Schema Migration MySQL Với Liquibase và CI/CD
Bài viết cùng chủ đề
  • Hướng Dẫn Tự Động Hóa Database Schema Migration MySQL Với Liquibase và CI/CD
  • Bảo Mật Nâng Cao MySQL 8: Làm Chủ Roles (RBAC) Và Cơ Chế Caching_sha2_password Thực Chiến
  • Hướng dẫn quản lý High Availability cho MySQL với Orchestrator: Tự động vẽ topology và failover an toàn lúc 2h sáng
  • Hướng dẫn cấu hình Change Data Capture (CDC) trong MySQL với Debezium và Apache Kafka
  • Tối ưu hóa phân mảnh bảng MySQL InnoDB: Cách dùng OPTIMIZE TABLE thu hồi ổ đĩa
  • Hướng dẫn cấu hình MySQL High Availability với Keepalived và HAProxy: Tự động chuyển đổi Virtual IP (VIP)
  • Tích hợp MySQL với Elasticsearch qua Logstash: Xây dựng pipeline đồng bộ dữ liệu tự động
  • Hướng dẫn sử dụng Flyway quản lý Schema Migration và Version Control cho MySQL trong CI/CD
  • Triển khai MySQL NDB Cluster: Giải pháp Database “Zero Downtime” cho hệ thống Uptime 99.999%
  • Migrate PostgreSQL sang MySQL: Kinh nghiệm “xương máu” và quy trình thực chiến
Copyright 2026 — ITFROMZERO. All rights reserved.
Privacy Policy | Terms of Service | Contact: [email protected] DMCA.com Protection Status
Scroll to Top