[英]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 = true
和remote 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.