【问题标题】:How to backup a database by pyodbc如何通过pyodbc备份数据库
【发布时间】:2013-11-19 08:53:28
【问题描述】:

备份语句在使用 pyodbc 游标执行时不能在事务中使用。似乎 pyodbc 在默认事务中执行查询。 我也尝试过使用自动提交模式或在备份语句之前添加提交语句。这两个都不行。

#can't execute the backup statement in transaction
cur.execute("backup database database_name to disk = 'backup_path'")
#not working too
cur.execute("commit;backup database database_name to disk = 'backup_path'")

是否可以通过pyodbc执行备份语句?提前致谢!

-----添加了附加信息--------------------------- --------------------------------

备份操作被封装在一个函数中,例如:

def backupdb(con, name, save_path):
    # with autocommit mode, should be pyodbc.connect(con, autocommit=True)
    con = pyodbc.connect(con) 
    query = "backup database %s to disk = '%s'" % (name, save_path)
    cur = con.cursor()
    cur.execute(query)
    cur.commit()
    con.close()

如果函数被以下代码调用,

backupdb('DRIVER={SQL Server};SERVER=.\sqlexpress;DATABASE=master;Trusted_Connection=yes',
             'DatabaseName',
             'd:\\DatabaseName.bak')

那么异常将是:

File "C:/Documents and Settings/Administrator/Desktop/bakdb.py", line 14, in <module>'d:\\DatabaseName.bak')
File "C:/Documents and Settings/Administrator/Desktop/bakdb.py", line 7, in backupdb cur.execute(query)
ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot perform a backup or restore operation within a transaction. (3021) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]BACKUP DATABASE is terminating abnormally. (3013)')

打开关键字autocommit=True,该函数将静默运行,但备份文件夹中没有生成备份文件。

【问题讨论】:

  • 在执行备份之前您是否厌倦了cur.autocommit = True?还提供有关数据库的更多信息并向我们显示错误消息。
  • @MichałNiklas,附加信息已添加,谢谢。

标签: python database backup pyodbc


【解决方案1】:

假设您使用的是 SQL Server,请在建立连接时指定 autocommit=True

>>> import pyodbc
>>> connection = pyodbc.connect(driver='{SQL Server Native Client 11.0}', 
                                server='InstanceName', database='master', 
                                trusted_connection='yes', autocommit=True)
>>> backup = "BACKUP DATABASE [AdventureWorks] TO DISK = N'AdventureWorks.bak'"
>>> cursor = connection.cursor().execute(backup)
>>> connection.close()

这是使用 pyodbc 3.0.7Python 3.3.2。我相信对于旧版本的 pyodbc,您需要使用 Cursor.nextset() 来创建备份文件。例如:

>>> import pyodbc
>>> connection = pyodbc.connect(driver='{SQL Server Native Client 11.0}', 
                                server='InstanceName', database='master', 
                                trusted_connection='yes', autocommit=True)
>>> backup = "E:\AdventureWorks.bak"
>>> sql = "BACKUP DATABASE [AdventureWorks] TO DISK = N'{0}'".format(backup)
>>> cursor = connection.cursor().execute(sql)
>>> while cursor.nextset():
>>>    pass
>>> connection.close()

值得注意的是,我不必使用 Cursor.nextset() 来使用当前版本的 pyodbc 和 SQL Server 2008 R2 创建备份文件。

【讨论】:

  • pyodbc版本是pyodbc-3.0.7.win32-py2.7,python环境是py2.7,我在XP中用SQL Express 2005在备份脚本上运行。你的第一个代码sn -ps 将触发我在问题中提到的异常。我会尝试第二个。
  • @Erxin 请使用记录的实际异常文本编辑您的问题
  • 添加异常详情和代码sn-ps。谢谢你的帮助。 :)
  • @Erxin 您在发布的示例中没有使用autocommit=True。将此添加到连接实例化中,它将起作用。
  • 对我来说,当不使用while cursor.nextset(): pass 时,我的备份会运行,但不会报告失败,也不会保留任何备份文件。这些线条使它起作用。类似这个问题:github.com/mkleehammer/pyodbc/issues/471
【解决方案2】:

几个小时后,我找到了解决方案。它必须在没有 MASTER 的情况下执行,必须终止其他会话,DB 必须设置为 OFFLINE,然后 RESTORE,然后再次设置为 ONLINE。

def backup_and_restore():
server = 'localhost,1433'
database = 'myDB'
username = 'SA'
password = 'password'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE=MASTER;UID='+username+';PWD='+ password)
cnxn.autocommit = True

def execute(cmd):
    cursor = cnxn.cursor()
    cursor.execute(cmd)
    while cursor.nextset():
        pass
    cursor.close()

execute("BACKUP DATABASE [myDB] TO DISK = N'/usr/src/app/myDB.bak'")
# do something .......
execute("ALTER DATABASE [myDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;")
execute("ALTER DATABASE [myDB] SET OFFLINE;")
execute("RESTORE DATABASE [myDB] FROM DISK = N'/usr/src/app/myDB.bak' WITH REPLACE")
execute("ALTER DATABASE [myDB] SET ONLINE;")
execute("ALTER DATABASE [myDB] SET MULTI_USER;")

【讨论】:

  • 为什么您在备份数据库后立即恢复它?
  • 我们需要以某种方式在真实数据库上运行高级测试(每个测试应该是独立的,因此每个测试的数据库应该是“相同的”)。欢迎其他选择:-)
猜你喜欢
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多