Chia sẻ kinh nghiệm lỗi postgresql: could not locate a valid checkpoint record
Khi làm việc với postgresql và chạy một thời gian dài, có khả năng bạn gặp phải một vấn đề như sau khiến server không thể chạy:
Nguyên nhân
Trong cấu trúc thư mục của server postgres, có chứa folder pg_wal. WAL viết tắt của write-access log, có thể hiểu đơn giản là các file log mỗi khi bản ghi mới được tạo ra trong database. Bạn có thể tìm hiểu thêm về WAL tại đây
Khi tìm kiếm một bản ghi trong transaction log nhưng không tìm thấy, nó sẽ báo lỗi như trên, có thể do file bị mất hay corrupt. Cách xử lý duy nhất khi gặp là reset lại pg_wal.
Nguyên nhân file bị corrupt có thể do chạy nhiều transaction, có câu lệnh sql bị lỗi nhưng không được bắt lỗi để rollback transaction lại, dẫn đến có nhiều transaction chạy liên tục không dừng.
Hướng dẫn xử lý
Để reset lại file WAL bạn cần phải cài postgresql, có sẵn các lệnh của postgresql.
Nếu bạn đã cài sẵn trên máy, bạn có thể chạy lệnh sau:
# Hoặc pg_resetwal -f DATADIR
pg_resetwal DATADIR
DATADIR là đường dẫn trỏ đến thư mục postgresql. Ví dụ /var/lib/postgresql/data
Xong rồi bạn khởi chạy lại postgresql, như vậy bạn đã xử lý thành công
Nếu bạn chạy postgresql bằng docker container nhưng do container không khởi chạy, bạn không thể ssh vào để reset lại được. Trong trường hợp này bạn phải cài postgresql trên máy bạn rồi chạy lệnh như trên.
Cách phòng tránh
Ta thường bắt đầu chạy transaction, thực hiện các lệnh CRUD vào database, thành công xong thì commit. Nhưng trong trường hợp một câu lệnh trong transaction gặp lỗi, ta thường bỏ qua và trả ra error luôn mà quên không thực hiện rollback transaction trước. Dẫn tới càng về sau càng nhiều transaction chạy liên tục.
Để tránh lỗi này hay gặp phải, ta cần xử lý lỗi khi chạy các câu lệnh CRUD trong transaction, nếu gặp lỗi cần rollback lại ngay. Ví dụ thay đổi khi viết code nhiều người có khả năng viết như sau:
transaction = db.Begin()
err = transaction.Insert(.....)
if (err != nil) {
// Khi có lỗi không rollback transaction tại đây, cần bổ sung transaction.Rollback()
return err
}
transaction.Commit()
All rights reserved