简体   繁体   English

SQL Server事务如何提交我的事务

[英]SQL Server Transactions how can I commit my transaction

I have SQL Server 2005 stored procedure. 我有SQL Server 2005存储过程。 Someone one is calling my stored procedure within a transaction. 有人在事务中调用我的存储过程。 In my stored proc I'm logging some information (insert into a table). 在我的存储过程中,我正在记录一些信息(插入表中)。 When the higher level transaction rolls back it removes my insert. 当更高级别的事务回滚时,它会删除我的插入。

Is there anyway I can commit my insert and prevent the higher level rollback from removing my insert? 无论如何,我可以提交我的插入并阻止更高级别的回滚删除我的插入?

Thanks 谢谢

Even if you start a new transaction, it will be nested within the outer transaction. 即使您启动新事务,它也将嵌套在外部事务中。 SQL Server guarantees that a rollback will result in an unmodified database state. SQL Server保证回滚将导致未修改的数据库状态。 So there is no way you can insert a row inside an aborted transaction. 因此,您无法在中止的事务中插入行。

Here's a way around it, it's a bit of a trick. 这是一种绕过它的方法,这是一个小技巧。 Create a linked server with rpc out = true and remote proc transaction promotion = false . 使用rpc out = trueremote proc transaction promotion = false创建链接服务器。 The linked server can point to the same server as your procedure is running on. 链接的服务器可以指向运行过程的同一服务器。 Then, you can use execte (<query>) at <server> to execute something in a new transaction. 然后,您可以使用execte (<query>) at <server>上的execte (<query>) at <server>新事务中执行某些操作。

if OBJECT_ID('logs') is not null drop table logs
create table logs (id int primary key identity, msg varchar(max))
if OBJECT_ID('TestSp') is not null drop procedure TestSp
go
create procedure TestSp as
execute ('insert into dbo.logs (msg) values (''test message'')') at LINKEDSERVER
go
begin transaction
exec TestSp
rollback transaction
select top 10 * from logs

This will end with a row in the log table, even though the transaction was rolled back. 即使事务已回滚,这也将以日志表中的一行结束。

Here's example code to create such a linked server: 以下是创建此类链接服务器的示例代码:

IF  EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND 
        srv.name = N'LINKEDSERVER')
    EXEC master.dbo.sp_dropserver @server=N'LINKEDSERVER', 
        @droplogins='droplogins'
EXEC master.dbo.sp_addlinkedserver @server = N'LINKEDSERVER', 
    @srvproduct=N'LOCALHOST', @provider=N'SQLNCLI', @datasrc=N'LOCALHOST', 
    @catalog=N'DatabaseName'
EXEC master.dbo.sp_serveroption @server=N'LINKEDSERVER', @optname=N'rpc out', 
     @optvalue=N'true'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'LINKEDSERVER', 
    @useself=N'True', @locallogin=NULL,@rmtuser=NULL, @rmtpassword=NULL
EXEC master.dbo.sp_serveroption @server=N'LINKEDSERVER', 
    @optname=N'remote proc transaction promotion', @optvalue=N'false'

In Oracle you would use autonomous transactions for that, however, SQL Server does not support them. Oracle您将使用自治事务,但是, SQL Server不支持它们。

It is possible to declare a table variable and return it from your stored procedure. 可以声明一个表变量并从存储过程中返回它。

The table variables survive the ROLLBACK , however, the upper level code should be modified to read the variable and store its data permanently. 表变量在ROLLBACK ,但是,应修改上层代码以读取变量并永久存储其数据。

Depending on permissions, you could call out using xp_cmdshell to OSQL thereby creating an entirely separate connection. 根据权限,您可以使用xp_cmdshell调用OSQL,从而创建完全独立的连接。 You might be able to do something similar with the CLR, although I've never tried it. 您可能能够使用CLR执行类似的操作,但我从未尝试过。 However, I strongly advise against doing something like this. 但是,我强烈建议不要这样做。

Your best bet is to establish what the conventions are for your code and the calling code - what kind of a contract is supported between the two. 最好的办法是确定代码和调用代码的约定 - 两者之间支持哪种类型的契约。 You could make it a rule that your code is never called within another transaction (probably not a good idea) or you could give requirements on what the calling code is responsible for when an error occurs. 您可以规定,您的代码永远不会在另一个事务中调用(可能不是一个好主意),或者您可以在发生错误时给出调用代码负责的要求。

Anything inside of a transaction will be part of that transaction. 交易中的任何内容都将成为该交易的一部分。 If you don't want it to be part of that transaction then do not put it inside. 如果您不希望它成为该交易的一部分,那么请不要将其放入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM