分布式查询和分布式事务
Microsoft® SQL Server™ 允许创建与称为链接服务器的 OLE DB 数据源的链接。在链接到 OLE DB 数据源之后,可以: 从 OLE DB 数据源引用行集,作为 Transact-SQL 语句中的表。
将命令传递给 OLE DB 数据源,并包含结果行集,作为 Transact-SQL 语句中的表。 
每个分布式查询都可以引用多个链接的服务器,而且可以对每个链接的服务器分别执行更新或读取操作。单个分布式查询可以对某些链接的服务器执行读取操作,并且对其它链接的服务器执行更新操作。通常情况下,每当某个事务可能更新多个链接服务器中的数据时,Microsoft SQL Server 都要求相应的 OLE DB 提供程序支持分布式事务。因此,链接服务器上所支持的查询类型取决于 OLE DB 提供程序中对事务的支持级别。OLE DB 为事务管理定义了两个可选的接口: ITransactionLocal 支持 OLE DB 数据源中的本地事务。
ITransactionJoin 允许提供程序联结包含其它资源管理器的分布式事务。 
所有支持 ITransactionJoin 的提供程序也都支持 ITransactionLocal。如果在连接是自动提交模式时执行分布式查询,则应用以下规则: 对于不支持 ItransactionLocal 的提供程序,只允许执行读取操作。
对于支持 ITransactionLocal 的提供程序,允许执行所有更新操作。 
主控 SQL Server 会自动调用每个参与更新操作的链接的服务器中的 ITransactionLocal,以启动本地事务,并在语句执行成功时提交或在语句执行失败时回滚。如果分布式查询是针对分布式分区视图或者是在连接为显式或隐性事务时执行,则应用下列规则: 对于不支持 ITransactionJoin 的提供程序,只允许执行读取操作。不支持任何事务或只支持 ITransactionLocal 的提供程序不能参与更新操作。
如果 SET XACT_ABORT 设置为 ON,则对于支持 ITransactionJoin 的任意提供程序都允许执行所有的更新操作。主控 SQL Server 会自动调用每个参与更新操作的链接服务器中的 ITransactionJoin,以便在分布式事务中登记该服务器。然后当主控服务器表示要提交或回滚事务时,MS DTC 将提交或者回滚。
如果 SET XACT_ABORT 设置为 OFF,则链接服务器还必须支持嵌套事务,才能对其执行更新操作。当会话已经有一个现有事务时,如果提供程序支持调用 ITransactionLocal::StartTransaction,则支持嵌套事务。这使 SQL Server 得以回滚分布式查询中的单个语句,而不是回滚整个事务。 
上述规则意味着提供程序的下列限制不支持嵌套事务:仅在 XACT_ABORT 选项设置为 ON 时,分布式事务中才允许更新操作。

解决方案 »

  1.   

    1. 分布式查询构架:
    分布式查询访问存储在本地或者远程计算机上的多个异构的数据源中的数据。SQL Server允许创建与称为链接服务器的 OLE DB 数据源的链接。在链接到 OLE DB 数据源之后,可以从 OLE DB 数据源引用行集,作为 Transact-SQL 语句中的表,也可以将命令传递给 OLE DB 数据源,并包含结果行集,作为 Transact-SQL 语句中的表。每个分布式查询都可以引用多个链接的服务器,而且可以对每个链接的服务器分别执行更新或读取操作。单个分布式查询可以对某些链接的服务器执行读取操作,并且对其它链接的服务器执行更新操作。
    链接服务器泛指OLE DB数据源(OLE DB能够访问的数据文件),他类似一个服务器,SQL Server通过一个相应OLE DB提供者来管理该数据源。OLE DB提供者是一个动态链接库文件,服务器通过它实现对指定OLE DB数据源的访问。
      

  2.   

    2.访问远程数据
    可以使用两种技术从SQL Server中访问OLE DB数据源:
    l 特别查询:
    访问远程数据时,当你不期望重复地访问一个耗时太长的数据源时,可以编写一个使用OPENROWSET或者OPENDATASOURCE函数的特别查询。
    OPENROWSET:
    包含访问OLE DB数据源中的远程数据所需的全部连接信息。当访问链接服务器中的表时,这种方法是一种替代方法,并且是一种使用OLE DB连接并访问远程数据的一次性的、特殊的方法。可以在查询的FROM子句中像引用表名那样引用OPENROWSET函数。依据OLE DB提供程序的能力,还可以将OPENROWSET函数引用为INSERT、UPDATE或DELETE语句的目标表。尽管查询可能返回多个结果集,然而OPENROWSET只返回第一个。
    语法:
    OPENROWSET ( 'provider_name'
        , { 'datasource' ; 'user_id' ; 'password'
            | 'provider_string' }
        , { [ catalog.] [ schema.] object
            | 'query' } 
    )
    参数:
    1)'provider_name':字符串,它代表在注册表中指定的OLE DB提供程序的友好名。provider_name没有默认值。
    2)'datasource':字符串常量,它对应着某个特定的OLE DB数据源。datasource是将被传递到提供程序IDBProperties接口以初始化提供程序的DBPROP_INIT_DATASOURCE属性。通常,这个字符串包含数据库文件的名称、数据库服务器的名称,或者提供程序能理解的用于查找数据库的名称。
    3)'user_id':字符串常量,它是传递到指定OLE DB提供程序的用户名。user_id为连接指定安全上下文,并将它作为DBPROP_AUTH_USERID属性传递进来以初始化提供程序。
    4)'password':字符串常量,它是将被传递到OLE DB提供程序的用户密码。当初始化提供程序时,将password作为DBPROP_AUTH_PASSWORD属性传递进来。
    5)'provider_string':提供程序特定的连接字符串,将它作为DBPROP_INIT_ PROVIDERSTRING属性传递进来以初始化OLE DB提供程序。通常provider_string封装初始化提供程序所需的所有连接信息。
    6)Catalog:目录或数据库的名称,其中驻留着指定的对象。
    7)Schema:架构的名称或指定对象的对象所有者名称。
    8)Object:对象名称,它唯一地标识出将要操作的对象。
    9)'query':是字符串常量,发送到提供程序并由提供程序执行。SQL Server不处理该查询,但处理由提供程序返回的查询结果(直接传递查询)。对于有些提供程序,它们并没有通过表名而是通过命令语言表现自己的表格格式数据,那么将直接传递查询用于这些提供程序是非常有用的。只要查询提供程序支持OLE DB Command对象及其强制接口,那么在远程服务器上就支持直接传递查询。
    例16.1:利用OPENROWSET函数直接查询服务器s31上的pubs数据库中的titles表。
    USE pubs
    GO
    SELECT a.*
    FROM OPENROWSET('SQLOLEDB','s31';'sa';'',
        'SELECT * FROM pubs.dbo.titles' )
      AS a
    GOOPENDATASOURCE:
    不使用链接的服务器名,而提供特殊的链接信息,并将其作为四部分对象名的一部分。
    语法:
    OPENDATASOURCE ( provider_name, init_string )
    参数:
    1)provider_name:注册为用于访问数据源的OLE DB提供程序的PROGID的名称。provider_name的数据类型为char,没有默认值。
    2)init_string:连接字符串,这些字符串将要传递给目标提供程序的IDataInitialize接口。提供程序字符串语法是以关键字值对为基础的,这些关键字值对由分号隔开,例如:"keyword1=value; keyword2=value."
    例16.2:利用OPENDATASOURCE函数直接查询服务器s37中的northwind数据库中的employees表
    SELECT   *
    FROM      
    OPENDATASOURCE('SQLOLEDB',
                'Data Source=s37;User ID=sa;Password='
               ).Northwind.dbo.Categories
    l 链接服务器查询:
    你可以使用一个连接服务器和一个四部分(four-part)对象名称来重复地访问远程数据。一个连接服务器是一个在引用时预先注册到本地SQL Server的OLE DB数据源,本地服务器明白在哪儿寻找数据和对象。在提供跨服务器链接和预先知道某数据源是可用的查询时,使用链接服务器是一种有效的方法。
    3.指定在哪儿处理分布式查询
    在你要查询一个OLE DB数据源时,你可以指定是在本地的服务器上查询还是在远程服务器上查询。
    l 本地SQL Server
    对链接服务器来说,默认情况下,SQL Server在本地处理分布式查询。
    l 远程OLE DB数据源(远程查询)
    可以使用带链接服务器的OPENQUERY函数来指定处理查询在远程服务器上发生。这叫做远程查询(Pass-Through),当使用OPENROWSET函数在一个远程数据源上执行一个特别查询时,查询将被远程地处理。
    4.验证链接设置
    在任何时候产生分布式查询时,都必须保证ANSI_NULLS和ANSI_WARNINGS选项都打开了。如果使用ODBC或者SQL查询分析器产生分布式查询,这些选项的默认值为打开的。如果使用osql命令行工具,则必须要明确地设置这些选项为打开状态。