【问题标题】:SQL Server Transactions how can I commit my transactionSQL Server 事务我如何提交我的事务
【发布时间】:2011-02-22 00:35:05
【问题描述】:

我有 SQL Server 2005 存储过程。有人在事务中调用我的存储过程。在我的存储过程中,我正在记录一些信息(插入表中)。当更高级别的事务回滚时,它会删除我的插入。

无论如何我可以提交我的插入并防止更高级别的回滚删除我的插入吗?

谢谢

【问题讨论】:

    标签: sql sql-server sql-server-2005


    【解决方案1】:

    即使您开始一个新事务,它也会嵌套在外部事务中。 SQL Server 保证回滚将导致未修改的数据库状态。因此,您无法在已中止的事务中插入一行。

    这是一种解决方法,它有点诡计。使用rpc out = trueremote proc transaction promotion = false 创建链接服务器。链接服务器可以指向运行您的过程的同一台服务器。然后,您可以使用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
    

    这将以日志表中的一行结束,即使事务已回滚。

    以下是创建此类链接服务器的示例代码:

    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'
    

    【讨论】:

    • @codingguy3000:发现了一个技巧,答案已编辑。这需要管理员权限
    【解决方案2】:

    事务中的任何内容都将成为该事务的一部分。如果您不希望它成为该交易的一部分,请不要将其放入其中。

    【讨论】:

    • 调用存储过程正在启动事务。所以我没有办法避免成为这个交易的一部分。
    • 你能重新设计它的工作原理吗?总的来说,这听起来像是一个糟糕的设计
    【解决方案3】:

    Oracle 中,您将为此使用自治事务,但是,SQL Server 不支持它们。

    可以声明一个表变量并从存储过程中返回它。

    表变量在ROLLBACK 中仍然存在,但是,应该修改上层代码以读取变量并永久存储其数据。

    【讨论】:

    • 正是我的建议
    【解决方案4】:

    根据权限,您可以使用 xp_cmdshell 调用 OSQL,从而创建一个完全独立的连接。尽管我从未尝试过,但您也许可以用 CLR 做类似的事情。不过,我强烈建议不要这样做。

    您最好的办法是确定您的代码和调用代码的约定 - 两者之间支持哪种合同。您可以制定一条规则,即您的代码永远不会在另一个事务中被调用(可能不是一个好主意),或者您可以对发生错误时调用代码的责任提出要求。

    【讨论】:

      猜你喜欢
      • 2018-04-27
      • 2015-07-27
      • 2019-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多