Tôi gặp sự cố tương tự với The current transaction cannot be committed and cannot support operations that write to the log file, nhưng tôi có một câu hỏi tiếp theo.Lỗi giao dịch SQL: Giao dịch hiện tại không thể được cam kết và không thể hỗ trợ các thao tác ghi vào tệp nhật ký
Câu trả lời có tham chiếu Using TRY...CATCH in Transact-SQL, mà tôi sẽ trở lại trong một giây ...
Mã của tôi (di truyền, tất nhiên) có dạng đơn giản:
SET NOCOUNT ON
SET XACT_ABORT ON
CREATE TABLE #tmp
SET @transaction = 'insert_backtest_results'
BEGIN TRANSACTION @transaction
BEGIN TRY
--do some bulk insert stuff into #tmp
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'bulk insert error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
'; check backtestfiles$ directory for error files ' +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -666
END CATCH
BEGIN TRY
EXEC usp_other_stuff_1 @whatever
EXEC usp_other_stuff_2 @whatever
-- a LOT of "normal" logic here... inserts, updates, etc...
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -777
END CATCH
RETURN 0
Tôi nghĩ tôi có đủ thông tin để chỉ chơi với nó và tìm ra bản thân mình ... tiếc là tái tạo lỗi là chứng minh damn gần không thể. Vì vậy, tôi hy vọng rằng yêu cầu ở đây sẽ giúp làm rõ sự hiểu biết của tôi về vấn đề và giải pháp.
thủ tục lưu trữ này là, không liên tục, ném lỗi như thế này một:
error importing results for backtest 9649 error_number: 3930 error_message: The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. error_severity: 16 error_state 1 error_line: 217
Vì vậy, rõ ràng là lỗi xuất phát từ khối catch 2
Dựa trên những gì tôi đã đọc trong Using TRY...CATCH in Transact-SQL, tôi nghĩ rằng những gì đang xảy ra là khi trường hợp ngoại lệ bị ném, việc sử dụng XACT_ABORT
sẽ khiến giao dịch bị "chấm dứt và quay lại" ... và sau đó dòng đầu tiên của BEGIN CATCH
đang cố gắng quay trở lại một cách mù quáng.
Tôi không biết tại sao nhà phát triển ban đầu bật XACT_ABORT
, vì vậy tôi nghĩ giải pháp tốt hơn (thay vì xóa) sẽ sử dụng XACT_STATE()
để chỉ quay lại nếu có giao dịch (<>0
). Điều đó có hợp lý không? Tui bỏ lỡ điều gì vậy?
Ngoài ra, việc đề cập đến việc đăng nhập vào thông báo lỗi khiến tôi tự hỏi: Có vấn đề gì khác, có khả năng với cấu hình không? Việc chúng tôi sử dụng RAISEERROR()
trong trường hợp này có góp phần vào vấn đề này không? Điều đó có được đăng nhập hay không, trong một số trường hợp không thể đăng nhập, vì thông báo lỗi ám chỉ đến?
Mẫu của bạn giả định các giao dịch bên trong khối thử; chúng tôi có nhiều khối thử bên trong 1 giao dịch. –
@Adam: Đó là về cách bạn xử lý 'XACT_STATE' và các giao dịch trong khối CATCH. Bạn có thể có nhiều khối thử trong một giao dịch bằng cách sử dụng mẫu rất này. Ý tưởng là hiểu cách giao dịch và khối catch tương tác, và như một phần thưởng bạn cũng nhận được việc xử lý các giao dịch lồng nhau và các điểm lưu trữ, rất hữu ích trong xử lý hàng loạt, vì nó cho khả năng tiếp tục phần còn lại của lô ngay cả khi mục nhập không thành công. –
Tôi đã đi trước và gói câu lệnh rollback trong một 'if XACT_STATE() <> 0', nhưng chỉ có thời gian sẽ cho biết nếu nó giải quyết nó cho chúng ta. Đoán tôi sẽ tiếp tục và chấp nhận câu trả lời của bạn ngay bây giờ. –