Giới thiệu
Gần đây, một đồng nghiệp của tôi đã đến gặp tôi trong tuyệt vọng vì anh ấy đã đưa ra một tuyên bố cập nhật mà không có mệnh đề WHERE trên bảng ứng dụng chính. Những tác động từ giao diện người dùng sẽ rất nghiêm trọng, vì vậy anh ấy đã trực tiếp đến gặp tôi vì anh ấy cần giúp đỡ khẩn cấp để xoay chuyển tình thế bằng mọi cách trước khi các email và sự leo thang bắt đầu đổ về.
Khi xem xét tình hình, chúng tôi nhận thấy rằng các thay đổi chưa được áp dụng trong cơ sở dữ liệu thứ cấp. Trong hầu hết các trường hợp, độ trễ giữa cơ sở dữ liệu chính và phụ của chúng tôi là 20 phút (chúng tôi có một chút lo lắng để tránh các vấn đề về hiệu suất). Vì đồng nghiệp của tôi đã yêu cầu trợ giúp ngay sau khi nhận ra lỗi, chúng tôi đã có thể khôi phục dữ liệu từ cơ sở dữ liệu thứ cấp. Tôi đã mô tả giá trị của sự chậm trễ như vậy trong bài viết này .
Đánh giá tình huống
Tình huống tôi mô tả ở trên không phải là hiếm. Một trong những lý do tại sao điều này xảy ra với người dùng SQL Server thông thường là SQL Server sử dụng cái được gọi là Giao dịch ngầm định. Giao dịch ngầm định bị TẮT theo mặc định, có nghĩa là SQL Server không mong đợi bạn đưa ra câu lệnh GIAO DỊCH COMMIT ở cuối mỗi câu lệnh. Trên thực tế, mỗi câu lệnh được cam kết tự động. Điều này thuận tiện và giúp tránh các trường hợp trong đó các phiên chưa được cam kết sẽ khóa tài nguyên và ảnh hưởng đến hiệu suất. Brent Ozar cung cấp thêm chi tiết về tác động của IMPLICIT TRANSACTIONS =ON.
Tuy nhiên, một nhược điểm nhỏ của cấu hình này (IMPLICIT TRANSACTIONS =OFF) là người dùng không có cơ hội để suy nghĩ lại một câu lệnh và đưa ra một ROLLBACK rất phổ biến trong Oracle. Hình 1 cho thấy các tùy chọn truy vấn ANSI có sẵn trong SQL Server Management Studio.
Hình. 1 mặc định ANSI trong SQL Server Management Studio
Sử dụng các Giao dịch Ngầm định
Về bản chất, vấn đề mà chúng ta gặp phải trong cấu hình mặc định này hoặc công cụ khách mong muốn nhất của chúng ta là chúng ta không thể QUAY LẠI khi chúng ta thực thi một câu lệnh SQL. Chúng tôi có thể tránh được điều này bằng cách bật GIAO DỊCH GỢI Ý trong phiên của chúng tôi. Điều này sẽ cho chúng tôi cơ hội để QUAY LẠI các giao dịch nếu chúng tôi cần. Hình 2 và Hình 4 cho chúng ta thấy rằng chúng ta chỉ có thể bật cài đặt này cho một phiên, mặc dù điều này không làm giảm nguy cơ phiên người dùng chặn người khác nếu không đưa ra ROLLBACK hoặc COMMIT.
Hình. BẬT 2 GIAO DỊCH IMPLICIT trong một phiên
- Liệt kê 1:CẬP NHẬT Bảng TAB2 với IMPLICIT_TRANSACTIONS ONSET IMPLICIT_TRANSACTIONS ONDECLARE @IMPLICIT_TRANSACTIONS VARCHAR (3) ='OFF'; IF ((2 &@@ OPTIONS) =2) SET @IMPLICIT_TRANSACTIONS ='BẬT'; CHỌN @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS; SỬ DỤNG KTrainGOSELECT * TỪ Tab2; GOUPDATE TAB2SET countryCode ='SA' - WHERE fname ='Joyce'; GOSELECT * FROM Tab2; ĐI
Hình. Đã cập nhật 3 tất cả các hàng
Để minh họa cách giải quyết được mô tả ở đây, hãy xem mã SQL trong Liệt kê 1. Hãy giả sử rằng một người dùng SQL Server thông thường, một nhà phát triển cơ sở, đã được cung cấp một bộ tập lệnh để thực thi trong các điều kiện nhất định . Trong tập lệnh, mệnh đề WHERE đã được chú thích bởi vì người ta mong đợi rằng mỗi lần họ thực thi tập lệnh này, họ nên thay đổi vị từ. Tất nhiên, đây là một trường hợp sử dụng đơn giản và rủi ro có thể được giải quyết theo một số cách, nhưng chúng tôi chỉ muốn cho thấy khả năng thực hiện QUAY LẠI.
Nhớ lại rằng chúng ta đã bật IMPLICIT TRANSACTION, vì vậy khi chúng ta thực hiện câu lệnh này, SQL Server sẽ yêu cầu chúng ta COMMIT hoặc ROLLBACK giao dịch. Ý định của nhà phát triển là cập nhật Mã quốc gia của Joyce Afam sang ‘SA’ kể từ khi cô ấy nhập cư đến Nam Phi. Hình 3 cho chúng ta thấy rằng nhà phát triển trong khi cố gắng thực hiện việc này, đã vô tình cập nhật tất cả các hàng có giá trị SA là countryCode . Họ nhận thấy điều này và đưa ra BẢN LĂN.
Hình. 4 Phát hành ROLLBACK
Hình. 5 GIAO DỊCH IMPLICIT BẬT trong một phiên khác
Tuy nhiên, trong phiên khác mà chúng tôi chưa bật GIAO DỊCH GỢI Ý, chúng tôi nhận thấy rằng nhà phát triển không thể khôi phục lỗi của họ. Họ không thể đưa ra ROLLBACK thành công trong trường hợp này. Quá trình khôi phục sau đó sẽ yêu cầu khôi phục dữ liệu.
Hình. 6 Không thể ROLLBACK nếu không BẬT GIAO DỊCH IMPLICIT
Sử dụng các Giao dịch Rõ ràng
Một cách tiếp cận khác để đạt được hiệu quả tương tự là đưa DML vào một giao dịch bằng cách nêu rõ BEGIN TRAN. Một lần nữa, điều rất quan trọng là phải hoàn thành giao dịch - bằng cách sử dụng COMMIT hoặc ROLLBACK. Trong khuôn khổ cuộc thảo luận này, chúng tôi đưa ra một ROLLBACK vì chúng tôi nhận thấy rằng có lỗi trong mã.
- Liệt kê 2:CẬP NHẬT Bảng TAB2 với Giao dịch rõ ràngBEGIN TRAN GOUSE KTrainGOSELECT * FROM Tab2; GOUPDATE TAB2SET countryCode ='GH' - WHERE fname ='Joyce'; GOSELECT * FROM Tab2; GOROLLBACK; CHỌN * TỪ Tab2; ĐI - Liệt kê 3:Tuyên bố CẬP NHẬT đã sửa chữaKết luận
Trong bài viết này, chúng tôi đã đề cập ngắn gọn về một giải pháp tốt để tạo cơ hội cho ROLLBACK và do đó giảm thiểu lỗi người dùng do sai DML. Chúng tôi cũng đã nêu rõ một rủi ro chính của phương pháp này, đó là việc vô tình chặn. DBA có thể bắt đầu điều tra về sự hiện diện có thể có của rủi ro này bằng cách truy vấn sys.dm_tran_session_transactions, sys.dm_tran_locks và các đối tượng quản lý động tương tự.
Tài liệu tham khảo
Khắc phục Mất dữ liệu bằng Vận chuyển nhật ký với Khôi phục bị trì hoãn
Đặt các giao dịch ngầm định
Đặt các giao dịch ngầm thành ý tưởng xấu
DMV cho các giao dịch