2010-11-16 38 views
15

Tôi đang cố gắng ghi vào tệp nhật ký bên trong một giao dịch để nhật ký tồn tại ngay cả khi giao dịch được khôi phục.Ghi nhật ký TSQL bên trong giao dịch

đang --start

bắt đầu tran

chèn [gì đó] vào dbo.logtable

[[mã chính ở đây]]

rollback

cam

- mã kết thúc

Bạn có thể nói chỉ cần làm nhật ký trước khi giao dịch bắt đầu nhưng điều đó không dễ dàng bởi vì giao dịch bắt đầu trước khi S-Proc này chạy (tức là mã này là một phần của giao dịch lớn hơn)

Vì vậy, trong ngắn hạn, có cách viết một câu lệnh đặc biệt bên trong một giao dịch không phải là một phần của giao dịch hay không. Tôi hy vọng câu hỏi của tôi có ý nghĩa.

+0

Vui lòng xem http://stackoverflow.com/questions/3725356/suppress-transaction-in-stored-procedure –

Trả lời

12

Sử dụng biến bảng (@temp) để giữ thông tin nhật ký. Các biến bảng tồn tại một rollback giao dịch.

Xem this article.

+0

Chỉ những gì tôi định đề xuất. Tôi đã sử dụng thành công nhiều lần. – HLGEM

+0

Vấn đề với điều này là nếu bất cứ điều gì khác xảy ra như một thời gian chờ kết nối hoặc thời gian chờ thực hiện, bạn sẽ được trái với không có bản ghi. – Talon

2

Tôi làm điều này theo một trong hai cách, tùy theo nhu cầu của tôi vào thời điểm đó. Cả hai đều liên quan đến việc sử dụng một biến, mà giữ lại giá trị của họ sau một rollback.

1) Tạo giá trị DECLARE @Log varchar(max) và sử dụng: @SET @ Log = ISNULL (@ Log + ';', '') + 'Thông tin nhật ký mới của bạn ở đây' . Keep appending to this as you go through the transaction. I'll insert this into the log after the commit or the rollback as necessary. I'll usually only insert the @Log value into the real log table when there is an error (in the CATCH` block) hoặc Nếu tôi đang cố gắng gỡ lỗi một vấn đề.

2) tạo một DECLARE @LogTable table (RowID int identity(1,1) primary key, RowValue varchar(5000). Tôi chèn vào điều này khi bạn tiến hành thông qua giao dịch của bạn. Tôi thích sử dụng mệnh đề OUTPUT để chèn các ID thực tế (và các cột khác có thông báo, như 'DELETE mục 1234') của các hàng được sử dụng trong giao dịch vào bảng này. Tôi sẽ chèn bảng này vào bảng log thực tế sau khi commit hoặc rollback khi cần thiết.

+0

Cả hai đều tốt, ngoại trừ tôi không có quyền truy cập dễ dàng vào phần giao dịch. Về cơ bản tôi đang cố gắng để gỡ lỗi một chương trình được viết bằng C#. – Arvid

+1

(hãy hoàn thành điều này :-) Mã C# bắt đầu một giao dịch, sau đó gọi một s-proc, và cuối cùng nó cam kết hoặc quay trở lại giao dịch. Tôi chỉ có quyền truy cập dễ dàng vào s-proc và tôi đã hy vọng tôi có thể thực hiện một số mã gỡ lỗi ở đó có thể tồn tại một cuộn lùi – Arvid

+0

bạn có thể thử sử dụng [xp_cmdshell (Transact-SQL)] (http://msdn.microsoft.com /en-us/library/ms175046.aspx) (nhưng điều đó có thể được tắt như là một nguy cơ bảo mật) để bao gồm những điều này trong thủ tục của bạn: 'EXEC xp_cmdshell echo 'thông điệp của bạn ở đây' >> log.txt' để ghi vào một tập tin . bạn cũng có thể thử sử dụng một tham số đầu ra @ErrorInfo varchar (max) 'nơi bạn truyền lại thông tin lỗi cho chương trình C# để nó có thể ghi lại nó. –

1

Nếu giao dịch cha mẹ cuộn lại dữ liệu ghi nhật ký cũng sẽ quay lại - máy chủ SQL không hỗ trợ các giao dịch lồng nhau thích hợp. Một khả năng là sử dụng thủ tục lưu sẵn CLR để thực hiện ghi nhật ký. Điều này có thể mở kết nối riêng của nó với cơ sở dữ liệu bên ngoài giao dịch và nhập và cam kết dữ liệu nhật ký.

+0

Sử dụng thủ tục ghi nhật ký CLR là một trong những giải pháp tốt nhất. Nếu chỉ trong có thể bằng cách nào đó tự động nhận được các giá trị thực tế của các thông số sproc được gọi là với .. chúng ta luôn có thể mơ ước. –

7

Xem Logging messages during a transaction để biết giải pháp thay thế dựa trên sp_trace_generateevent không yêu cầu phạm vi @table biến (không phải lúc nào cũng có thể) hoặc khi ranh giới giao dịch nằm ngoài tầm kiểm soát.

+0

Có vẻ như điều này sẽ hiệu quả. Cảm ơn tất cả các bạn vì câu trả lời nhanh. – Arvid

0

Nếu bạn muốn bắt chước hành vi giao dịch lồng nhau, bạn có thể sử dụng các giao dịch mang tên:

begin transaction a 

create table #a (i int) 

select * from #a 
save transaction b 

create table #b (i int) 
select * from #a 
select * from #b 

rollback transaction b 

select * from #a 
rollback transaction a 

Trong SQL Server nếu bạn muốn có một ‘tiểu giao dịch’ bạn nên sử dụng save transaction xxxx mà hoạt động như một trạm kiểm soát oracle.

+3

Câu trả lời này không trả lời được câu hỏi nào cả. OP không hỏi về giao dịch phụ, hoàn toàn ngược lại. Ông muốn một số hoạt động được loại trừ bối cảnh giao dịch và cam kết ngay trong cơ sở dữ liệu. – Tipx

+0

câu trả lời của tôi là nhận xét ở trên nó - và tôi nghĩ rằng nó trả lời khá ngắn gọn –

Các vấn đề liên quan