Cách sửa nhanh (TL;DR)
Hãy coi EXECABORT như việc Redis nhấn phanh trước khi xảy ra sự cố. Lỗi này xảy ra do bạn đã cố gắng đưa một lệnh bị lỗi vào hàng đợi bên trong khối MULTI. Redis sẽ đánh dấu giao dịch là "dirty" (bẩn) và từ chối thực thi toàn bộ khi bạn gọi lệnh EXEC.
Để khắc phục ngay lập tức:
- Kiểm tra lại các lệnh bạn đã nhập giữa
MULTIvàEXECxem có lỗi đánh máy hoặc thiếu đối số không. - Kiểm tra xem máy chủ của bạn có chạm giới hạn
maxmemory(OOM) hay không. - Xem nhật ký ứng dụng để tìm các ngoại lệ (exception) được ném ra trước khi lệnh
exec()thực sự được gửi đi.
Giải mã lỗi EXECABORT
Redis xử lý sai sót theo hai cách khác nhau. Hiểu rõ sự khác biệt là chìa khóa để gỡ lỗi.
- Lỗi hàng đợi (Queuing Errors - EXECABORT): Những lỗi này xảy ra khi bạn vẫn đang thêm lệnh vào danh sách. Nếu bạn gõ sai tên lệnh hoặc cung cấp ba đối số trong khi cần bốn, Redis sẽ phát hiện sớm. Kể từ phiên bản 2.6.5, máy chủ sẽ ghi nhớ thất bại này và hủy bỏ toàn bộ loạt lệnh để bảo vệ dữ liệu của bạn.
- Lỗi thực thi (Execution Errors): Những lỗi này chỉ xảy ra sau khi bạn gọi lệnh
EXEC. Một ví dụ là cố gắngINCRmột key đang chứa một list. Trong trường hợp này, Redis vẫn chạy mọi lệnh khác trong giao dịch bất kể có một lệnh đơn lẻ bị lỗi.
Khi bạn thấy EXECABORT, bạn đang gặp phải lỗi hàng đợi. Redis đang chọn giải pháp an toàn bằng cách từ chối thực thi một đoạn mã bị hỏng một phần.
Nguyên nhân phổ biến và giải pháp
Trường hợp 1: Lỗi cú pháp đơn giản
Chín trên mười trường hợp, nguyên nhân là do lỗi đánh máy đơn giản. Nếu bạn truyền sai số lượng đối số, Redis sẽ nhận diện sự không khớp ngay trong giai đoạn MULTI.
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET user:100 "John"
QUEUED
127.0.0.1:6379(TX)> HSET user:101 field1 # Lỗi: Thiếu giá trị thực tế
(error) ERR wrong number of arguments for 'hset' command
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
Cách sửa: Kiểm tra kỹ cấu trúc (signature) lệnh của bạn. Nếu bạn đang sử dụng các thư viện client như redis-py hoặc ioredis, hãy đảm bảo logic của bạn không truyền null hoặc undefined vào nơi mong đợi một chuỗi.
Trường hợp 2: Chạm giới hạn bộ nhớ (OOM)
Nếu instance Redis của bạn có giới hạn maxmemory—ví dụ 512MB—và hiện đang ở mức 511.9MB, một lệnh ghi có thể thất bại. Nếu một lệnh ghi thất bại bên trong khối MULTI vì máy chủ đã đầy, toàn bộ giao dịch sẽ bị hủy.
Cách sửa: Chạy lệnh INFO memory để xem mức sử dụng hiện tại của bạn. Nếu used_memory_human đang mấp mé giới hạn maxmemory, bạn có ba lựa chọn:
- Tăng giá trị
maxmemorytrong tệpredis.conf. - Chuyển sang chính sách thu hồi (eviction policy) quyết liệt như
allkeys-lru. - Tự tay dọn dẹp các key cũ hoặc dữ liệu đã hết hạn để giải phóng không gian.
Trường hợp 3: Lệnh không tồn tại
Sử dụng một lệnh không tồn tại hoặc không khả dụng trong phiên bản Redis hiện tại sẽ gây ra lỗi hàng đợi ngay lập tức.
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> GSET mykey "value" # Lỗi đánh máy: Bạn định dùng SET
(error) ERR unknown command 'GSET'
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
Cách sửa: Kiểm tra chính tả của bạn. Điều này thường xảy ra với các nhà phát triển chuyển từ Redis 7.x về một môi trường cũ hơn (như instance AWS ElastiCache cũ), nơi các tính năng mới như Streams (XADD) có thể chưa tồn tại.
Vai trò của WATCH
Trong khi WATCH thường trả về kết quả (nil) nếu một key thay đổi, nó hoạt động song song với các khối lệnh này. Nếu bạn gặp lỗi cú pháp và lỗi WATCH, EXECABORT sẽ chiếm ưu tiên. Hàng đợi vốn đã không hợp lệ ngay từ đầu, nên Redis thậm chí không buồn kiểm tra xem các key đang được theo dõi có bị thay đổi hay không.
Cách xác nhận lỗi đã được khắc phục
Kiểm tra logic của bạn bằng một bài test thủ công nhanh trong Redis CLI. Một giao dịch ổn định sẽ hiển thị một chuỗi các phản hồi QUEUED rõ ràng:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET health_check "up"
QUEUED
127.0.0.1:6379(TX)> INCR total_requests
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (integer) 1
Nếu bạn thấy một danh sách các kết quả được đánh số, nghĩa là mọi thứ đã ổn. Nếu lỗi vẫn tiếp diễn trên môi trường production, hãy kiểm tra nhật ký hệ thống tại /var/log/redis/redis-server.log. Đôi khi, các lỗi lưu nền (RDB) hoặc vấn đề về đĩa cũng có thể khiến Redis từ chối các lệnh ghi và hủy bỏ giao dịch.

