Nhân viên sửa số mà chủ không biết: vết thao tác là gì và vì sao nó hay vô dụng
6 phút đọcĐội ngũ vanhanhso

Nhật ký thao tác chỉ đáng tin khi mỗi thay đổi trong dữ liệu để lại đúng một dòng, và mỗi dòng ứng với đúng một thay đổi. Nhiều phần mềm ghi nhật ký bằng một lệnh riêng SAU khi đã sửa dữ liệu — cách đó hỏng theo hai chiều, cả hai đều im lặng: có thay đổi mà không có vết, hoặc có vết cho việc chưa từng xảy ra. Cách đóng an toàn là ghi vết trong cùng giao dịch với chính thay đổi đó.
Tình huống
Giá bán của một mặt hàng trong phần mềm hôm qua là 120.000, hôm nay là 95.000. Không ai nhận đã sửa. Phần mềm có mục "lịch sử thao tác", mở ra thì trống.
Chuyện này xảy ra không phải vì ai xoá dấu vết. Nó xảy ra vì cách phần lớn phần mềm ghi nhật ký có một khe hở, và khe hở đó không báo lỗi bao giờ — không trong lúc vận hành, không trong lúc kiểm tra, chỉ lộ ra vào đúng lúc có người cần nhật ký nhất. Bài này giải thích khe hở ấy bằng ngôn ngữ của người không làm kỹ thuật, để chủ doanh nghiệp biết phải hỏi nhà cung cấp phần mềm câu gì.
Vết thao tác trả lời câu hỏi nào?
Một vết đầy đủ trả lời năm câu: ai làm, làm gì, lúc nào, dữ liệu trước ra sao, dữ liệu sau ra sao. Với thao tác cần giải trình — huỷ chứng từ, sửa số đã chốt — thêm câu thứ sáu: vì sao.
Phần khó không nằm ở việc ghi năm trường đó. Phần khó là bảo đảm mỗi thay đổi có đúng một vết, và mỗi vết ứng với đúng một thay đổi. Không có bảo đảm ấy thì nhật ký chỉ là một danh sách gợi ý.
Khe hở nằm ở đâu?
Cách viết tự nhiên nhất là hai bước:
1. cập nhật dữ liệu nghiệp vụ
2. ghi một dòng vào bảng nhật ký
Hai bước đó có thể không cùng số phận. Giữa chúng có một khoảnh khắc mà tiến trình có thể chết, mạng có thể đứt, thao tác có thể bị huỷ giữa chừng. Hai chiều hỏng:
Chiều A — có thay đổi, không có vết. Bước 1 xong, bước 2 chưa kịp. Dữ liệu đã đổi và không ai biết ai đổi. Đây đúng là tình huống ở đầu bài, và nó là chiều nguy hiểm hơn: nó tạo ra chính cái lỗ hổng mà nhật ký sinh ra để bịt.
Chiều B — có vết, không có thay đổi. Bước 1 bị huỷ vì một lỗi ở phần sau, nhưng bước 2 đã ghi. Nhật ký khẳng định một việc chưa từng xảy ra.
⛔ Điểm chung: không có thông báo nào. Phần mềm vẫn chạy, người dùng vẫn thấy kết quả đúng, không có dòng lỗi nào. Sai lệch chỉ lộ ra khi có người ngồi đối chiếu — tức là vào đúng lúc người ta cần nhật ký đáng tin nhất.
Vì sao "thiếu một chút" lại đủ để mất giá trị?
Vì giá trị của nhật ký không phải là có nhiều dòng, mà là tin được từng dòng và tin rằng không thiếu dòng nào.
Một nhật ký thiếu 0,1% số thay đổi vẫn đúng 99,9%. Nhưng khi cần chứng minh "khoản chi này đã được duyệt bởi người có thẩm quyền", câu trả lời "trong nhật ký không có, mà nhật ký của chúng tôi đôi khi thiếu" không khác gì không có nhật ký. Một nguồn chỉ có giá trị chứng minh khi sự vắng mặt của một bản ghi cũng là một thông tin.
Chiều B tệ theo kiểu khác: nó không làm nhật ký thiếu, nó làm nhật ký sai. Một nguồn thỉnh thoảng sai thì mọi dòng trong đó đều phải kiểm lại bằng nguồn khác — tức là nó không còn là nguồn nữa.
Cách đóng an toàn
Cơ sở dữ liệu đã có sẵn công cụ cho bài này: giao dịch. Nhiều lệnh ghi trong một giao dịch thì hoặc cùng thành công, hoặc cùng bị huỷ. Không có trạng thái nửa vời.
Nên vết được ghi trong cùng giao dịch với thay đổi nghiệp vụ:
BEGIN
cập nhật dữ liệu nghiệp vụ
ghi vết vào bảng hộp thư đi
COMMIT
Cả hai cùng vào hoặc cùng không. Chiều A và chiều B biến mất — không phải vì được xử lý khéo, mà vì chúng không còn tồn tại như trạng thái khả dĩ.
Còn nếu vết cần đi tới một nơi khác để lưu tập trung, thì gửi thế nào mà không mở lại đúng khe hở vừa bịt? Câu trả lời là hộp thư đi: giao dịch chỉ ghi vào một bảng trong cùng cơ sở dữ liệu, và một tiến trình riêng đọc bảng đó rồi phát đi. Việc gửi có thể thất bại và thử lại bao nhiêu lần cũng được; nó không ảnh hưởng tới tính toàn vẹn của cặp thay đổi ↔ vết, vì cặp đó đã chốt xong từ trước.
Đây không phải phát minh — nó là một khuôn đã có tên trong tài liệu kiến trúc hệ thống. Điều đáng nói là nó phải là hạ tầng dùng chung, không phải việc từng phần tự lo. Khi mỗi phần tự ghi nhật ký theo cách riêng, sẽ có phần làm đúng và phần làm sai, và không cách nào biết phần nào là phần nào ngoài đọc từng dòng mã.
Thao tác nào phải kèm lý do?
Những thao tác mà kết quả không tự giải thích được.
Tạo một đơn hàng mới thì dữ liệu đã nói hết. Nhưng huỷ một chứng từ đã phát hành, sửa một con số thuộc kỳ đã chốt, hay duyệt vượt hạn mức — ba việc đó nhìn dữ liệu trước và sau vẫn không biết vì sao. Với chúng, trường lý do phải bắt buộc ở lúc thao tác, không phải một ô ghi chú điền sau.
"Ở lúc thao tác" là phần quan trọng. Một trường lý do có thể bỏ trống rồi bổ sung sau sẽ được điền vào lúc thuận tiện, bằng thứ dễ viết nhất — thường là "điều chỉnh theo yêu cầu".
Ba câu nên hỏi nhà cung cấp phần mềm
- Vết có ghi cả giá trị trước và sau không? Chỉ ghi "đã sửa giá" mà không ghi từ bao nhiêu sang bao nhiêu thì không đối soát được gì.
- Vết được ghi trong cùng giao dịch với thay đổi, hay bằng một lệnh riêng sau đó? Đây là câu phân biệt hai loại nhật ký ở bài này.
- Thao tác cần giải trình có bắt nhập lý do ngay lúc thao tác không?
⚠️ Nói cho rõ phạm vi: bài này mô tả tính chất của hệ thống — dữ liệu để lại vết trong cùng giao dịch với thay đổi, và không có đường ghi nào đi vòng qua nhật ký. Nó không mô tả một màn hình tra cứu hay một chức năng xuất báo cáo; những thứ đó là phần việc riêng, và mô tả chúng như đã có sẵn thì chính bài viết này đã tự phản bội điều nó đang nói.
Nếu vấn đề hiện tại chưa phải là ai sửa số, mà là chứng từ không đủ để đối soát, thì bắt đầu từ bộ hồ sơ cho sáu hoạt động tài chính.
Câu hỏi thường gặp
Làm sao biết phần mềm đang dùng có ghi vết đàng hoàng không?
Hỏi nhà cung cấp ba câu cụ thể: vết có ghi cả giá trị TRƯỚC và SAU không; vết có được ghi trong cùng giao dịch với thay đổi không; và thao tác cần giải trình như huỷ chứng từ hay sửa số đã chốt có bắt nhập lý do ngay lúc thao tác không. Ba câu này phân biệt được một nhật ký dùng để đối soát với một nhật ký chỉ để nhìn cho yên tâm.
Ghi log ra file có đủ không?
Không đủ cho mục đích đối soát. File log nằm ngoài giao dịch cơ sở dữ liệu nên không có bảo đảm nào rằng mỗi dòng log tương ứng với một thay đổi đã được ghi nhận thật. Nó vẫn hữu ích để tìm lỗi kỹ thuật, nhưng đó là mục đích khác.
Ghi vết có làm phần mềm chậm đi không?
Có, một chút, vì mỗi thay đổi ghi thêm một dòng trong cùng giao dịch. Chi phí là vài mili giây. Thứ đánh mất khi không có vết là khả năng chứng minh — với phần mềm quản trị doanh nghiệp thì đó là đánh đổi gần như luôn đáng.
Doanh nghiệp nhỏ có cần vết thao tác không?
Cần từ lúc có người thứ hai được quyền sửa dữ liệu. Khi chỉ một mình chủ nhập liệu thì vết ít giá trị. Ngay khi có nhân viên nhập đơn, sửa giá, hoặc duyệt chi, câu hỏi 'ai đã đổi con số này' bắt đầu xuất hiện — và nó chỉ trả lời được nếu hệ thống đã ghi từ trước.


