我在本地的一个proc里有一些操作远程库的语句。并且对此想用事务,但发现超时。
proc代码如下:
/******数据传送处理进程 datatrans_proc*******/
IF EXISTS (SELECT * FROM sysobjects WHERE name='datatrans_proc')
   DROP procedure datatrans_proc
go
Create procedure datatrans_proc  
@transtime datetime,@sip varchar(100),@suser varchar(100),@suserpass varchar(100),
@logname varchar(100)
--,@iresult smallint =0 output
as  
declare @outtime varchar(19),@iRows int
declare @linkstring varchar(1000)
declare @iCount int,@outno int,@localcode char(2),@headcode char(2)
declare @sql varchar(1000)
declare @stmp varchar(1000)
BEGIN TRAN--加上这句就超时
set @sql='Data Source='+@sip+';User ID='+@suser+';Password='+@suserpass
select @outtime=isnull(convert(char(19),outtime,120),'2008-01-01 00:00:00') from datatranstime where timeno=1
delete from syslogtemp--清空系统日志临时表
delete from cardconsumetemp--靖空卡消费流水临时表
delete from membertemp--清空会员临时表
insert syslogtemp select * from syslog where opertime>=@outtime--将本地系统日志最新数据放入临时表中
insert cardconsumetemp select * from cardconsume where consumdate>=@outtime--将本地消费最新流水数据放入临时表中
insert membertemp select * from member--将本地会员表放入临时表
select @outno=isnull(1,max(outno)+1) from dataoutlog--得到数据送表的最大编号
select @localcode=storecode from storecode where localflag=1--得到本店code
select @headcode=storecode from storecode where headflag=1--得到总店code
delete dataoutlog where outno=@outno and outtime=@transtime and logonname=@logname
insert dataoutlog values(@outno,@transtime,@localcode,@headcode,'传送中',@logname)
set @stmp='insert OPENDATASOURCE(''SQLOLEDB'','''+@Sql+''').database.dbo.datainlog values('+convert(varchar(10),@outno)+','+quotename(@transtime,'''')+','+quotename(@localcode,'''')+','+quotename(@headcode,'''')+','+quotename('传送中','''')+','+quotename(@logname,'''')+')'
exec(@stmp)
set @stmp='insert OPENDATASOURCE(''SQLOLEDB'','''+@Sql+''').database.dbo.syslogtemp  select * from syslogtemp'
update dataoutlog set result='传送完毕' where outno=@outno and outtime=@transtime and logonname=@logname
update datatranstime set outtime=@transtime where timeno=1
COMMIT   TRAN 
go

解决方案 »

  1.   

    不同服务器数据库之间的数据操作--创建链接服务器 
    exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
    exec sp_addlinkedsrvlogin  'ITSV ', 'false ',null, '用户名 ', '密码 ' --查询示例 
    select * from ITSV.数据库名.dbo.表名 --导入示例 
    select * into 表 from ITSV.数据库名.dbo.表名 --以后不再使用时删除链接服务器 
    exec sp_dropserver  'ITSV ', 'droplogins ' --连接远程/局域网数据(openrowset/openquery/opendatasource) 
    --1、openrowset --查询示例 
    select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) --生成本地表 
    select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) --把本地表导入远程表 
    insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) 
    select *from 本地表 --更新本地表 
    update b 
    set b.列A=a.列A 
     from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b 
    on a.column1=b.column1 --openquery用法需要创建一个连接 --首先创建一个连接创建链接服务器 
    exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' 
    --查询 
    select * 
    FROM openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
    --把本地表导入远程表 
    insert openquery(ITSV,  'SELECT *  FROM 数据库.dbo.表名 ') 
    select * from 本地表 
    --更新本地表 
    update b 
    set b.列B=a.列B 
    FROM openquery(ITSV,  'SELECT * FROM 数据库.dbo.表名 ') as a  
    inner join 本地表 b on a.列A=b.列A --3、opendatasource/openrowset 
    SELECT   * 
    FROM   opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ' ).test.dbo.roy_ta 
    --把本地表导入远程表 
    insert opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名 
    select * from 本地表  
      

  2.   

    BUG呀,我的沙发怎么看不到呀。
      

  3.   

    老乌龟,搞个经典SQL来骗分
    SQL没收。。
      

  4.   

    没有rollback语句呀,如果中间有报错还是commit不了了吧,那事务怎么结束呀?
      

  5.   

    to 老乌龟:呵呵,你发的已经不适用于我这个问题了。
    我的问题已经很清楚了:
    在本地的一个proc里有一些操作远程库的语句。并且对此想用事务,但发现超时。 
      

  6.   

    SET XACT_ABORT ON 在执行操作前,使用这个参数设置,省略Begin Tran 等事务命令
      

  7.   

    不好意思,上面说得有些问题,看下这个例子:SET XACT_ABORT ON
    GOBEGIN TRAN
    INSERT INTO t2 VALUES (4)
    INSERT INTO t2 VALUES (5) /* Foreign key error */
    INSERT INTO t2 VALUES (6)
    COMMIT TRAN
    GO
      

  8.   

    示例
    本例在本地和远程数据库上更新作者的姓。本地和远程数据库将同时提交或同时回滚本事务。 
    说明  除非正在运行 Microsoft® SQL Server™ 的计算机上当前装有 MS DTC,否则本例会产生错误信息。关于安装 MS DTC 的更多信息,请参见 Microsoft 分布式事务处理协调器文档。USE pubs
    GO
    BEGIN DISTRIBUTED TRANSACTION
    UPDATE authors
       SET au_lname = 'McDonald' WHERE au_id = '409-56-7008'
    EXECUTE remote.pubs.dbo.changeauth_lname '409-56-7008','McDonald'
    COMMIT TRAN
    GO
      

  9.   

    详细资料可以参考联机帮助中的:BEGIN DISTRIBUTED TRANSACTION/SET XACT_ABORT
      

  10.   

    用这个好像不行啊,我在proc里加上BEGIN   DISTRIBUTED   TRANSACTION后运行还是超时。奇怪了。
    不过如果是用set xact_abort的话,怎么判断是出错或不出错呢?
      

  11.   

    用了set   xact_abort on,好象也不行啊,不能回滚。出错了,前面执行过的东东没有回滚。
    郁闷中啊。。
      

  12.   

    唉,要是不能回滚,我只能在winform的程序里用sqlcommand一句一句执行了。郁闷 。
      

  13.   

    楼主这个问题,上次有人问过类似的. 语句没什么问题,问题在于你自己的逻辑.你大至执行的是:step1:
    oprate local database {read modify tableX}step2:
    oprate reomote database (read data from local database tableX}先看没有事务处理的情况:
    step1执行后,你的tableX的更改已提交
    再执行step2,这样没有问题.加入事处理:
    step1执行完:
    tableX 的修改没有提交.
    step2执行时, tableX因为操作未提交, 表被锁定,反以它在等待 tableX的操作提交, 就限入了死等状态.我上面的 tableX 不是指一个表,而是指你本地上需要修改并且在远程操作时要读出的数据.
      

  14.   

    当然不行了,
    链接服务器的语句执行不在你的transaction范围内
      

  15.   

    SET XACT_ABORT ON
    BEGIN DISTRIBUTED TRANSACTION
    .....
      

  16.   

    具体的错误信息是什么?也看一下Event Viewer的具体出错信息还有,写一个最简单的SQL,确认MSDTC是工作的
      

  17.   

    要在一个事务中访问远程数据库,需要使用分布式事务。上面已经说得很详细了。DTC有个超时设置,默认是60秒,你也许可以试试增加这个时间。有点难找:
    控制面板 -> 管理工具 -> 组件服务(component services)
    打开这个窗口,你把第一个结点扩展开,一直到你看到“我的电脑(My Computer)”这个结点,
    右键点击这个结点,里面有好多个页,选择“选项”那个页,
    里面有个“事务超时”的设置,你会看到默认是60秒,改个大点的值试试。上面这个东西有点难找,我也找了半天。不是桌面上那个“我的电脑”  :)