Thứ Ba, 7 tháng 4, 2026

Alter bảng treo trong PostgreSQL

--Khi ALTER TABLE ... RENAME bị treo trong PostgreSQL, gần như chắc chắn là câu lệnh này đang chờ lock trên bảng app_data.request_his.

--Với ALTER TABLE, PostgreSQL cần ACCESS EXCLUSIVE lock, nên chỉ cần có session khác đang:

SELECT lâu,
INSERT/UPDATE/DELETE,
hoặc tệ hơn là idle in transaction

thì lệnh rename có thể bị chờ.

--Làm theo thứ tự này:
--1) Xác định session ALTER TABLE của anh đang bị block
SELECT
    pid,
    usename,
    application_name,
    client_addr,
    state,
    wait_event_type,
    wait_event,
    xact_start,
    query_start,
    now() - query_start AS running_time,
    query
FROM pg_stat_activity
WHERE query ILIKE '%ALTER TABLE app_data.request_his%'
  AND state <> 'idle';

Nếu thấy:

wait_event_type = Lock
state = active

thì đúng là đang bị session khác giữ lock.

--2) Xác định PID nào đang chặn nó
SELECT
    a.pid AS blocked_pid,
    pg_blocking_pids(a.pid) AS blocking_pids,
    a.usename,
    a.application_name,
    a.client_addr,
    a.state,
    a.wait_event_type,
    a.wait_event,
    a.query_start,
    now() - a.query_start AS blocked_for,
    a.query
FROM pg_stat_activity a
WHERE a.query ILIKE '%ALTER TABLE app_data.request_his%'
  AND a.state <> 'idle';

Nếu blocking_pids trả về như {12345,23456} thì đó là các session đang chặn.

--3) Xem chi tiết session đang giữ lock trên bảng app_data.request_his
--17183
SELECT
    a.pid,
    a.usename,
    a.application_name,
    a.client_addr,
    a.state,
    a.xact_start,
    a.query_start,
    now() - a.query_start AS running_time,
    l.locktype,
    l.mode,
    l.granted,
    a.wait_event_type,
    a.wait_event,
    a.query
FROM pg_locks l
JOIN pg_stat_activity a ON a.pid = l.pid
JOIN pg_class c ON c.oid = l.relation
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'app_data'
  AND c.relname  in ('request_his','request_his_log')
ORDER BY l.granted DESC, a.query_start;

--Câu này giúp anh thấy:
--PID nào đang giữ lock
--lock mode gì
--đã granted hay đang chờ
--câu SQL nào đang chạy

--4) Câu lệnh chuẩn để xem blocked ↔ blocker rõ nhất
--Câu này dễ dùng nhất trong thực chiến:
WITH blocked AS (
    SELECT
        a.pid AS blocked_pid,
        a.usename AS blocked_user,
        a.application_name AS blocked_app,
        a.client_addr AS blocked_client,
        a.query_start AS blocked_query_start,
        now() - a.query_start AS blocked_duration,
        a.query AS blocked_query,
        unnest(pg_blocking_pids(a.pid)) AS blocker_pid
    FROM pg_stat_activity a
    WHERE a.query ILIKE '%ALTER TABLE app_data.request_his%'
      AND a.state <> 'idle'
)
SELECT
    b.blocked_pid,
    b.blocked_user,
    b.blocked_app,
    b.blocked_client,
    b.blocked_query_start,
    b.blocked_duration,
    b.blocked_query,
    a.pid AS blocker_pid,
    a.usename AS blocker_user,
    a.application_name AS blocker_app,
    a.client_addr AS blocker_client,
    a.state AS blocker_state,
    a.xact_start AS blocker_xact_start,
    now() - a.query_start AS blocker_running_time,
    a.wait_event_type AS blocker_wait_type,
    a.wait_event AS blocker_wait_event,
    a.query AS blocker_query
FROM blocked b
JOIN pg_stat_activity a ON a.pid = b.blocker_pid
ORDER BY b.blocked_duration DESC, a.query_start;

--Kill như thế nào cho an toàn
--Ưu tiên 1: cancel trước
--Nếu blocker đang chạy query bình thường, thử hủy query trước:
SELECT pg_cancel_backend(<blocker_pid>);

Ví dụ:
SELECT pg_cancel_backend(17183);

--Cách này chỉ dừng câu SQL đang chạy, session vẫn còn kết nối.

--Ưu tiên 2: terminate nếu cancel không ăn
--Nếu session là:
--idle in transaction
--hoặc query treo lâu
--hoặc ứng dụng không nhả lock
--thì terminate:

SELECT pg_terminate_backend(<blocker_pid>);

--Ví dụ:

SELECT pg_terminate_backend(12345);

--Cách này đá hẳn session ra khỏi DB, transaction sẽ rollback và lock được giải phóng.

--Khuyến nghị thực tế
--Trường hợp 1: blocker là idle in transaction
--Kill luôn thường hợp lý:

SELECT
    pid,
    usename,
    application_name,
    client_addr,
    state,
    xact_start,
    now() - xact_start AS xact_age,
    query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;

--Nếu thấy nó giữ bảng request_his, thường nên pg_terminate_backend(pid).

--Trường hợp 2: blocker là query SELECT đang chạy
--Có thể dùng:

SELECT pg_cancel_backend(pid);

--nếu app cho phép retry.

--Trường hợp 3: blocker là job batch / app transaction lớn
--Cần cân nhắc trước khi kill, vì có thể rollback lâu.
--Bộ lệnh tôi khuyên anh chạy ngay
--B1. Xem session rename đang bị block
SELECT
    pid,
    state,
    wait_event_type,
    wait_event,
    query_start,
    now() - query_start AS running_time,
    pg_blocking_pids(pid) AS blocking_pids,
    query
FROM pg_stat_activity
WHERE query ILIKE '%ALTER TABLE app_data.request_his%'
  AND state <> 'idle';

--B2. Xem chi tiết blocker
SELECT
    pid,
    usename,
    application_name,
    client_addr,
    state,
    xact_start,
    query_start,
    now() - query_start AS running_time,
    wait_event_type,
    wait_event,
    query
FROM pg_stat_activity
WHERE pid IN (
    SELECT unnest(pg_blocking_pids(pid))
    FROM pg_stat_activity
    WHERE query ILIKE '%ALTER TABLE app_data.request_his%'
      AND state <> 'idle'
);

--B3. Nếu xác định blocker an toàn để kill
SELECT pg_cancel_backend(<pid>);

--Nếu không nhả:
SELECT pg_terminate_backend(<pid>);

--Nếu lệnh rename vẫn không xong
--Có thể vì blocker không phải relation lock trực tiếp mà là chain lock.
--Khi đó chạy câu full này để xem toàn bộ session động:

SELECT
    pid,
    usename,
    application_name,
    client_addr,
    state,
    xact_start,
    query_start,
    now() - query_start AS running_time,
    wait_event_type,
    wait_event,
    query
FROM pg_stat_activity
WHERE datname = current_database()
ORDER BY xact_start NULLS LAST, query_start;

--Tìm các session:
--idle in transaction
--chạy rất lâu
--app batch lâu
--hoặc query đụng app_data.request_his
--Lưu ý rất quan trọng

--Không kill bừa nếu PID đó là:

--replication worker
--autovacuum quan trọng
--session ứng dụng nghiệp vụ đang xử lý giao dịch lớn

--Hãy ưu tiên kill session:

idle in transaction
query thử nghiệm
session tool/admin bị treo

Anh chạy 2 câu này trước là đủ để tìm thủ phạm:

SELECT
    pid,
    state,
    wait_event_type,
    wait_event,
    query_start,
    now() - query_start AS running_time,
    pg_blocking_pids(pid) AS blocking_pids,
    query
FROM pg_stat_activity
WHERE query ILIKE '%ALTER TABLE app_data.request_his%'
  AND state <> 'idle';
SELECT
    pid,
    usename,
    application_name,
    client_addr,
    state,
    xact_start,
    query_start,
    now() - query_start AS running_time,
    wait_event_type,
    wait_event,
    query
FROM pg_stat_activity
WHERE pid IN (
    SELECT unnest(pg_blocking_pids(pid))
    FROM pg_stat_activity
    WHERE query ILIKE '%ALTER TABLE app_data.request_his%'
      AND state <> 'idle'
);

Sau đó lấy PID ra rồi:

SELECT pg_terminate_backend(<pid>);

=============================
TƯ VẤN: Click Here hoặc Hotline/Zalo 090.29.12.888
=============================
Website không chứa bất kỳ quảng cáo nào, mọi đóng góp để duy trì phát triển cho website (donation) xin vui lòng gửi về STK 90.2142.8888 - Ngân hàng Vietcombank Thăng Long - TRAN VAN BINH
=============================
Nếu bạn không muốn bị AI thay thế và tiết kiệm 3-5 NĂM trên con đường trở thành DBA chuyên nghiệp hay làm chủ Database thì hãy đăng ký ngay KHOÁ HỌC ORACLE DATABASE A-Z ENTERPRISE, được Coaching trực tiếp từ tôi với toàn bộ bí kíp thực chiến, thủ tục, quy trình của gần 20 năm kinh nghiệm (mà bạn sẽ KHÔNG THỂ tìm kiếm trên Internet/Google) từ đó giúp bạn dễ dàng quản trị mọi hệ thống Core tại Việt Nam và trên thế giới, đỗ OCP.
- CÁCH ĐĂNG KÝ: Gõ (.) hoặc để lại số điện thoại hoặc inbox https://m.me/tranvanbinh.vn hoặc Hotline/Zalo 090.29.12.888
- Chi tiết tham khảo:
https://bit.ly/oaz_w
=============================
2 khóa học online qua video giúp bạn nhanh chóng có những kiến thức nền tảng về Linux, Oracle, học mọi nơi, chỉ cần có Internet/4G:
- Oracle cơ bản: https://bit.ly/admin_1200
- Linux: https://bit.ly/linux_1200
=============================
KẾT NỐI VỚI CHUYÊN GIA TRẦN VĂN BÌNH:
📧 Mail: binhoracle@gmail.com
☎️ Mobile/Zalo: 0902912888
👨 Facebook: https://www.facebook.com/BinhOracleMaster
👨 Inbox Messenger: https://m.me/101036604657441 (profile)
👨 Fanpage: https://www.facebook.com/tranvanbinh.vn
👨 Inbox Fanpage: https://m.me/tranvanbinh.vn
👨👩 Group FB: https://www.facebook.com/groups/DBAVietNam
👨 Website: https://www.tranvanbinh.vn
👨 Blogger: https://tranvanbinhmaster.blogspot.com
🎬 Youtube: https://www.youtube.com/@binhguru
👨 Tiktok: https://www.tiktok.com/@binhguru
👨 Linkin: https://www.linkedin.com/in/binhoracle
👨 Twitter: https://twitter.com/binhguru
👨 Podcast: https://www.podbean.com/pu/pbblog-eskre-5f82d6
👨 Địa chỉ: Tòa nhà Sun Square - 21 Lê Đức Thọ - Phường Mỹ Đình 1 - Quận Nam Từ Liêm - TP.Hà Nội

=============================
cơ sở dữ liệu, cơ sở dữ liệu quốc gia, database, AI, trí tuệ nhân tạo, artificial intelligence, machine learning, deep learning, LLM, ChatGPT, DeepSeek, Grok, oracle tutorial, học oracle database, Tự học Oracle, Tài liệu Oracle 12c tiếng Việt, Hướng dẫn sử dụng Oracle Database, Oracle SQL cơ bản, Oracle SQL là gì, Khóa học Oracle Hà Nội, Học chứng chỉ Oracle ở đầu, Khóa học Oracle online,sql tutorial, khóa học pl/sql tutorial, học dba, học dba ở việt nam, khóa học dba, khóa học dba sql, tài liệu học dba oracle, Khóa học Oracle online, học oracle sql, học oracle ở đâu tphcm, học oracle bắt đầu từ đâu, học oracle ở hà nội, oracle database tutorial, oracle database 12c, oracle database là gì, oracle database 11g, oracle download, oracle database 19c/21c/23c/23ai, oracle dba tutorial, oracle tunning, sql tunning , oracle 12c, oracle multitenant, Container Databases (CDB), Pluggable Databases (PDB), oracle cloud, oracle security, oracle fga, audit_trail,oracle RAC, ASM, oracle dataguard, oracle goldengate, mview, oracle exadata, oracle oca, oracle ocp, oracle ocm , oracle weblogic, postgresql tutorial, mysql tutorial, mariadb tutorial, ms sql server tutorial, nosql, mongodb tutorial, oci, cloud, middleware tutorial, docker, k8s, micro service, hoc solaris tutorial, hoc linux tutorial, hoc aix tutorial, unix tutorial, securecrt, xshell, mobaxterm, putty

ĐỌC NHIỀU

Trần Văn Bình - Oracle Database Master