3

我正在尝试在开发过程中自动化我的数据库恢复,在 SQL Server 2008 上使用 TSQL,使用带有 pyodbc 的 sqlalchemy 作为传输。

我正在执行的命令是:

"""创建数据库数据库名称

恢复数据库 dbname FROM DISK='C:\Backups\dbname.bak' WITH REPLACE,MOVE 'dbname_data' TO 'C:\Databases\dbname_data.mdf',MOVE 'dbname_log' TO 'C:\Databases\dbname_log.ldf' """

不幸的是,在 SQL Management Studio 中,代码运行后,我看到数据库仍处于“正在恢复...”状态。

如果我通过管理工作室恢复,它可以工作。如果我使用子进程调用“sqlcmd”,它可以工作。pymssql 在身份验证方面存在问题,甚至没有那么远。

可能出了什么问题?

4

4 回答 4

4

BACKUP 和 RESTORE 语句异步运行,因此在继续执行其余代码之前它们不会终止。

使用http://ryepup.unwashedmeme.com/blog/2010/08/26/making-sql-server-backups-using-python-and-pyodbc/中所述的while语句为我解决了这个问题:

# setup your DB connection, cursor, etc
cur.execute('BACKUP DATABASE ? TO DISK=?', 
            ['test', r'd:\temp\test.bak'])
while cur.nextset():
    pass
于 2013-02-08T13:33:25.000 回答
2

执行以下操作无法重现直接从 pyodbc(没有 sqlalchemy)恢复的问题:

connection = pyodbc.connect(connection_string) # ensure autocommit is set to `True` in connection string
cursor = connection.cursor()
affected = cursor.execute("""CREATE DATABASE test
RESTORE DATABASE test FROM DISK = 'D:\\test.bak' WITH REPLACE, MOVE 'test_data' TO 'D:\\test_data.mdf', MOVE 'test_log' to 'D:\\test_log.ldf' """)
while cursor.nextset():
    pass

一些需要澄清的问题:

  • 使用 sqlalchemy 进行还原的代码是什么?
  • 正在使用哪个版本的 SQL Server ODBC 驱动程序?
  • SQL Server 日志中是否有任何与还原相关的消息?

感谢geographikaCursor.nextset()示例!

于 2010-11-24T20:05:07.007 回答
1

对于 SQL Alchemy 用户,感谢 geographika 的回答:我最终使用了连接池中的“原始”DBAPI连接

它与 geographika 的解决方案完全相同,但有一些额外的部分:

import sqlalchemy as sa
driver = 'SQL+Server'
name = 'servername'
sql_engine_str = 'mssql+pyodbc://'\
                     + name\
                     + '/'\
                     + 'master'\
                     + '?driver='\
                     + driver
engine = sa.create_engine(sql_engine_str, connect_args={'autocommit': True})

connection = engine.raw_connection()
try:
  cursor = connection.cursor()
  sql_cmd = """
        RESTORE DATABASE [test]
        FROM DISK = N'...\\test.bak'
        WITH FILE = 1,
         MOVE N'test'
         TO N'...\\test_Primary.mdf',
         MOVE N'test_log'
         TO N'...\\test_log.ldf',
         RECOVERY,
         NOUNLOAD,
         STATS = 5,
         REPLACE
        """
  cursor.execute(sql_cmd)
  while cursor.nextset():
       pass
except Exception as e:
  logger.error(str(e), exc_info=True)
于 2018-01-19T23:07:36.573 回答
0

五件事用相同的症状解决了我的问题。

  1. 发现我的 test.bak 文件包含错误的 mdf 和 ldf 文件:

    >>> cursor.execute(r"RESTORE FILELISTONLY FROM DISK = 'test.bak'").fetchall()    
    [(u'WRONGNAME', u'C:\\Program Files\\Microsoft SQL ...),
    (u'WRONGNAME_log', u'C:\\Program Files\\Microsoft SQL ...)]
    
  2. 创建了一个新的 bak 文件并确保设置了copy-only backup选项

  3. 为我的连接设置自动提交选项。

    connection = pyodbc.connect(connection_string, autocommit=True)
    
  4. 仅将 connection.cursor 用于单个 RESTORE 命令,仅用于其他命令

  5. 更正了我的 RESTORE 命令中的test_dataMOVE test(由@beargle 提供)。

    affected = cursor.execute("""RESTORE DATABASE test FROM DISK = 'test.bak' WITH REPLACE, MOVE 'test' TO 'C:\\test.mdf', MOVE 'test_log' to 'C:\\test_log.ldf' """)
    
于 2014-01-08T22:30:01.140 回答