在 SQL Server 2008 上使用 sqlalchemy 等待数据库恢复完成

发布于 2024-10-03 21:56:24 字数 496 浏览 11 评论 0原文

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

我正在执行的命令是:

"""CREATE DATABASE dbname

Restore database 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 在身份验证方面存在问题,甚至还没有做到这一点。

可能出了什么问题?

I'm trying to automate my db restores during development, using TSQL on SQL Server 2008, using sqlalchemy with pyodbc as a transport.

The command I'm executing is:

"""CREATE DATABASE dbname

restore database 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'"""

Unfortunately, the in SQL Management Studio, after the code has run, I see that the DB remains in state "Restoring...".

If I restore through management studio, it works. If I use subprocess to call "sqlcmd", it works. pymssql has problems with authentication and doesnt even get that far.

What might be going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

楠木可依 2024-10-10 21:56:24

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

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

# setup your DB connection, cursor, etc
cur.execute('BACKUP DATABASE ? TO DISK=?', 
            ['test', r'd:\temp\test.bak'])
while cur.nextset():
    pass

The BACKUP and RESTORE statements run asynchronously so they don't terminate before moving on to the rest of the code.

Using a while statement as described at http://ryepup.unwashedmeme.com/blog/2010/08/26/making-sql-server-backups-using-python-and-pyodbc/ solved this for me:

# setup your DB connection, cursor, etc
cur.execute('BACKUP DATABASE ? TO DISK=?', 
            ['test', r'd:\temp\test.bak'])
while cur.nextset():
    pass
薄情伤 2024-10-10 21:56:24

无法重现直接从 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 日志中是否有与还原相关的消息?

感谢 geographika 提供的Cursor.nextset() 示例!

Unable to reproduce the problem restoring directly from pyodbc (without sqlalchemy) doing the following:

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

Some questions that need clarification:

  • What is the code in use to do the restore using sqlalchemy?
  • What version of the SQL Server ODBC driver is in use?
  • Are there any messages in the SQL Server log related to the restore?

Thanks to geographika for the Cursor.nextset() example!

沩ん囻菔务 2024-10-10 21:56:24

对于 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)

For SQL Alchemy users, and thanks to geographika for the answer: I ended up using the “raw” DBAPI connection from the connection pool.

It is exactly as geographika's solution but with a few additional pieces:

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)
回忆躺在深渊里 2024-10-10 21:56:24

五件事解决了我的问题,具有相同的症状。

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

    <前><代码>>>> cursor.execute(r"从磁盘恢复文件列表 = 'test.bak'").fetchall()
    [(u'WRONGNAME', u'C:\\Program Files\\Microsoft SQL ...),
    (u'WRONGNAME_log', u'C:\\Program Files\\Microsoft SQL ...)]

  2. 创建了一个新的 bak 文件并确保设置仅复制备份选项< /p>

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

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

  5. test_data MOVE更正为在我的 RESTORE 命令中进行测试(由 @beargle 提供)。

    affected=cursor.execute("""从磁盘恢复数据库测试='test.bak'并替换,将'test'移动到'C:\\test.mdf',将'test_log'移动到' C:\\test_log.ldf'""")
    

Five things fixed my problem with identical symptoms.

  1. Found that my test.bak file contained the wrong mdf and ldf files:

    >>> 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. Created a new bak file and made sure to set the copy-only backup option

  3. Set the autocommit option for my connection.

    connection = pyodbc.connect(connection_string, autocommit=True)
    
  4. Used the connection.cursor only for a single RESTORE command and nothing else

  5. Corrected the test_data MOVE to test in my RESTORE command (courtesy of @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' """)
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文