如何在不使用Transactions的情况下在pymssql中执行跨服务器存储过程?

时间:2015-10-26 14:04:45

标签: python sql-server pymssql

我正在尝试从一台服务器向另一台服务器插入数据(使用存储过程)。这是服务器架构的限制,我不得不解决它。

话虽这么说,我在serverA上有一个存储过程,它通常可以连接到serverB并且可以正常执行操作,因为这两个服务器是链接的。

问题是pymssql使用了事务,因此我不断收到此错误:

File "pymssql.pyx", line 465, in pymssql.Cursor.execute (pymssql.c:7190) pymssql.OperationalError: (7391, b'The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "ServerB" was unable to begin a distributed transaction. DB-Lib error message 20018, severity 16: General SQL Server error: Check messages from the SQL Server.)

当我在服务器上用BEGIN TRAN作为存储过程的前言时,我看到同样的错误,所以我得出的结论是因为pymssql使用了事务,我可能无法进行交叉-server分布式事务。

以下是代码:

def databasedata(start, end):
    startday = datetime.datetime.strptime(str(start), '%m/%d/%Y')
    endday = datetime.datetime.strptime(str(end), '%m/%d/%Y')
    conn = pymssql.connect(  user=os.getenv('SQLUSER'),
                             password=os.getenv('SQLP'),
                             server='serverA',
                             database=os.getenv('SQLDB'))
    cursor = conn.cursor()
    cursor.execute(' select day from dbo.valid_days '
                   'where day between %s and %s',
                   (startday, endday)
                   )
    days = cursor.fetchall()
    for day in days:
        date = ('%s-%s-%s' % day[0].timetuple()[:3])
        cursor.execute('exec [hooper].[dbo].[cross_server_generation] %s', date)
        conn.commit()


if __name__ == '__main__':
    (firstday, secondday) = (sys.argv[1], sys.argv[2])
    databasedata(firstday, secondday)

1 个答案:

答案 0 :(得分:0)

我没有使用pymssql,而是选择通过subprocess将其作为子程序运行。

import subprocess

def databasedata(start, end):
    startday = datetime.datetime.strptime(str(start), '%m/%d/%Y')
    endday = datetime.datetime.strptime(str(end), '%m/%d/%Y')
    conn = pymssql.connect(  user=os.getenv('SQLUSER'),
                         password=os.getenv('SQLP'),
                         server='serverA',
                         database=os.getenv('SQLDB'))
    cursor = conn.cursor()
    cursor.execute(' select day from dbo.valid_days '
                   'where day between %s and %s',
                   (startday, endday)
                   )
    days = cursor.fetchall()
    cursor.close()

    for day in days:
        date = ('%s-%s-%s' % day[0].timetuple()[:3])
        statement = 'exec [hooper].[dbo].[cross_server_generation] \'%s\'' % date
        subprocess.call(["sqlcmd", "-S", sqlserver, "-Q", statement])


if __name__ == '__main__':
    (firstday, secondday) = (sys.argv[1], sys.argv[2])
    databasedata(firstday, secondday)