Có an toàn để hủy truy vấn PostgreSQL ALTER TABLE đang chờ khóa không?


10

Chúng tôi đã bắt đầu một ALTER TABLEtruy vấn cách đây nhiều giờ và chỉ gần đây mới nhận ra (thông qua pg_stat_activity) rằng nó đang chờ khóa. Chúng tôi đã phát hiện ra truy vấn khác đang giữ một khóa trên bàn mà chúng tôi muốn thay đổi và không để nó đi.

Truy vấn của chúng tôi là một truy vấn "đơn giản" (thay đổi kiểu dữ liệu cột), nhưng nó đang chạy trên một bảng lớn.

Thay vì giết quá trình đang giữ khóa, chúng tôi quyết định chúng tôi thà giết ALTER TABLE.

Chúng tôi không gói gọn ALTER TABLEtrong một giao dịch.

Theo tôi hiểu, thực tế là truy vấn của chúng tôi đang chờ khóa có nghĩa là nó luôn chờ khóa và nó không bao giờ thay đổi bất cứ điều gì.

Điều này có đúng không? Có an toàn cho chúng tôi để hoàn toàn hủy bỏ ALTER TABLEtruy vấn của chúng tôi ? Hoặc có thể là truy vấn đã sửa đổi một cái gì đó và hủy bỏ nó sẽ khiến cơ sở dữ liệu của chúng ta ở trạng thái nửa chừng?

PS: Kế hoạch là hủy bỏ nó bằng cách sử dụng SELECT pg_cancel_backend(pid);. Nếu đây là một ý tưởng tồi, xin vui lòng cho tôi biết.


1
Nên hủy bỏ BẢNG THAY ĐỔI. PostgreSQL có DDL giao dịch và bạn nên ở trạng thái tương tự như khi bạn chưa chạy ALTER TABLE.
Josh Kupershmidt 6/2/2015

Vì vậy, khi bạn nói rằng PostgreSQL có DDL giao dịch, điều đó có nghĩa là bất kỳ truy vấn thay đổi lược đồ nào về cơ bản được chạy bên trong một giao dịch?
JMTyler

1
Trong trường hợp của bạn, ALTER TABLE là "về cơ bản được chạy trong một giao dịch", vì bạn đã nói "Chúng tôi không bao gồm ALTER TABLE trong một giao dịch." Nếu bạn muốn mặc dù, bạn có thể viết BEGIN; THAY ĐỔI foo ...; Thanh ALTER TABLE ...; Vân vân. ; CAM KẾT; - đó là tính năng giết người thực sự của PostgreSQL có DDL giao dịch. Nhưng đối với tình huống trước mắt của bạn, vâng, ALTER TABLE có thể bị hủy một cách an toàn và sẽ được khôi phục lại như thể nó không bao giờ xảy ra.
Josh Kupershmidt 6/2/2015

Cảm ơn bạn rất nhiều vì đã trả lời nhanh chóng của bạn! Đây là thông tin rất tốt. Bạn có thể đăng nó như một câu trả lời để tôi có thể đánh dấu nó là chấp nhận không?
JMTyler 6/2/2015

Câu trả lời:


13

Theo tôi hiểu, thực tế là truy vấn của chúng tôi đang chờ khóa có nghĩa là nó luôn chờ khóa và nó không bao giờ thay đổi bất cứ điều gì.

Phải - nếu bạn thấy pg_stat_activity.waiting là "đúng" đối với ALTER TABLE, điều đó gần như chắc chắn có nghĩa là nó kiên nhẫn chờ khóa ACCESS EXCLUSIVE trên bảng mục tiêu và công việc thực sự của nó (viết lại bảng nếu cần, thay đổi danh mục , xây dựng lại các chỉ mục, v.v.) chưa bắt đầu.

Có an toàn cho chúng tôi để hủy bỏ hoàn toàn truy vấn ALTER TABLE của chúng tôi không? Hoặc có thể là truy vấn đã sửa đổi một cái gì đó và hủy bỏ nó sẽ khiến cơ sở dữ liệu của chúng ta ở trạng thái nửa chừng?

Hủy bỏ các truy vấn (hoặc, tương tự, khôi phục giao dịch) trong PostgreQuery không có bất kỳ nguy cơ tham nhũng cơ sở dữ liệu nào mà bạn có thể đã bị phát hiện trong một số cơ sở dữ liệu khác (ví dụ: cảnh báo đáng sợ ở cuối trang này). Đó là lý do tại sao những người không phải siêu nhân, trong các phiên bản gần đây, được sử dụng miễn phí pg_cancel_backend()pg_terminate_backend()giết các truy vấn của riêng họ đang chạy trong các phụ trợ khác - họ an toàn để sử dụng mà không phải lo lắng về tham nhũng cơ sở dữ liệu. Rốt cuộc, PostgreSQL phải sẵn sàng đối phó với mọi quá trình bị tiêu diệt, ví dụ SIGKILL từ kẻ giết người OOM, tắt máy chủ, v.v. Đó là những gì nhật ký WAL dành cho.

Bạn cũng có thể đã thấy rằng trong PostgreSQL, có thể thực hiện hầu hết các lệnh DDL được lồng trong một giao dịch (đa câu lệnh), ví dụ:

BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind

(tuyệt vời để đảm bảo rằng việc di chuyển lược đồ đi cùng nhau hoặc không hoàn toàn.) Bạn đã nói, mặc dù:

Chúng tôi không gói gọn ALTER TABLEtrong một giao dịch.

Điều đó tốt cho một lệnh duy nhất - từ các tài liệu ,

PostgreSQL thực sự coi mọi câu lệnh SQL là được thực thi trong một giao dịch. Nếu bạn không ban hành lệnh BEGIN, thì mỗi câu lệnh riêng lẻ có BEGIN ẩn và CAM KẾT (nếu thành công) được bao quanh nó. Một nhóm các báo cáo được bao quanh bởi BEGIN và CAMIT đôi khi được gọi là khối giao dịch.

Vì vậy, việc hủy bỏ điều đó ALTER TABLE, thông qua pg_cancel_backend()hoặc Ctrl-C được phát ra từ dấu nhắc psql kiểm soát, sẽ có tác động tương tự như bạn đã làm

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(mặc dù như bạn hy vọng đã thấy, việc hủy bỏ sự đắt đỏ đó ALTER TABLEcó thể lưu cơ sở dữ liệu khỏi nhiều công việc không cần thiết nếu bạn vẫn tiếp tục ROLLBACK.)


5

Để giải thích câu trả lời đúng và xuất sắc của Josh:

Có an toàn cho chúng tôi để hủy bỏ hoàn toàn truy vấn ALTER TABLE của chúng tôi không?

Đúng.

Nó sẽ an toàn ngay cả khi nó đang ở giữa viết lại bảng .

Nếu bạn muốn, bạn có thể tắt toàn bộ máy chủ PostgreSQL hoặc trên thực tế máy chạy, khởi động lại và mọi thứ sẽ ổn. DDL trong PostgreSQL là giao dịch và sự cố an toàn.

Các hoạt động DDL được ghi lại thông qua WAL và đảm bảo rằng chúng có thể được khôi phục hoặc hoàn thành sau khi phục hồi sau khi gặp sự cố hoặc hủy bỏ.


3
Chỉ cần một lưu ý về "bạn có thể tắt toàn bộ máy chủ PostgreSQL hoặc trên thực tế máy chạy, khởi động lại và mọi thứ sẽ ổn" - hoàn toàn đúng miễn là bạn có phần cứng đáng tin cậy không nói dối về fsync , wiki.postgresql.org/wiki/Reliable_Writes
Josh Kupershmidt 7/2/2015

2
@JoshKupershmidt Chắc chắn, nhưng điều đó không cụ thể đối với DDL. Nếu bạn gặp sự cố đồng bộ thì bạn sẽ không an toàn cho mọi thứ .
Craig Ringer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.