在 Linux 容器中还原 SQL Server 数据库

适用于:SQL Server - Linux

本教程演示如何将 SQL Server 备份文件移动和还原到在 Docker 上运行的 SQL Server 2017 (14.x) Linux 容器映像。

本教程演示如何将 SQL Server 备份文件移动和还原到在 Docker 上运行的 SQL Server 2019 (15.x) Linux 容器映像。

本教程演示如何将 SQL Server 备份文件移动和还原到在 Docker 上运行的 SQL Server 2022 (16.x) Linux 容器映像。

  • 拉取并运行最新的 SQL Server Linux 容器映像。
  • 将 Wide World Importers 数据库文件复制到容器中。
  • 还原容器中的数据库。
  • 运行 Transact-SQL 语句来查看和修改数据库。
  • 备份修改后的数据库。

先决条件

部署选项

本部分提供环境部署选项。

sqlcmd 目前不支持在创建容器时使用 MSSQL_PID 参数。 如果使用本教程中的 sqlcmd 说明,你将使用 SQL Server 开发人员版本创建容器。 依照命令行接口 (CLI) 指令,使用所选许可证创建容器。 有关详细信息,请参阅部署并连接到 SQL Server Linux 容器

拉取并运行容器映像

  1. 打开 Linux 上的 bash 终端。

  2. 从 Microsoft 容器注册表中请求 SQL Server 2017 (14.x) Linux 容器映像。

    sudo docker pull mcr.microsoft.com/mssql/server:2017-latest
    
  3. 要通过 Docker 运行容器映像,可使用下列命令:

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql1' -p 1401:1433 \
       -v sql1data:/var/opt/mssql \
       -d mcr.microsoft.com/mssql/server:2017-latest
    

    此命令使用开发人员版创建 SQL Server 2017 (14.x) 容器(默认)。 SQL Server 端口 1433 在主机上公开为端口 1401。 可选的 -v sql1data:/var/opt/mssql 参数会创建一个名为 sql1data 的数据卷容器。 这用于保留 SQL Server 创建的数据。

    重要

    该示例在 Docker 中使用数据卷容器。 有关详细信息,请参阅 在 Docker 上配置 SQL Server 容器映像

  4. 要查看容器,请使用 docker ps 命令。

    sudo docker ps -a
    
  5. 如果 STATUS 列显示 Up 状态,则 SQL Server 正在容器中运行,并且在侦听 PORTS 列中指定的端口。 如果 SQL Server 容器的 STATUS 列显示 Exited,请参阅 SQL Server Docker 容器故障排除

$ sudo docker ps -a

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
941e1bdf8e1d        mcr.microsoft.com/mssql/server/mssql-server-linux   "/bin/sh -c /opt/m..."   About an hour ago   Up About an hour    0.0.0.0:1401->1433/tcp   sql1
  1. 打开 Linux 上的 bash 终端。

  2. 从 Microsoft 容器注册表中请求 SQL Server 2019 (15.x) Linux 容器映像。

    sudo docker pull mcr.microsoft.com/mssql/server:2019-latest
    
  3. 要通过 Docker 运行容器映像,可使用下列命令:

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql1' -p 1401:1433 \
       -v sql1data:/var/opt/mssql \
       -d mcr.microsoft.com/mssql/server:2019-latest
    

    此命令使用开发人员版创建 SQL Server 2019 (15.x) 容器(默认)。 SQL Server 端口 1433 在主机上公开为端口 1401。 可选的 -v sql1data:/var/opt/mssql 参数会创建一个名为 sql1data 的数据卷容器。 这用于保留 SQL Server 创建的数据。

    重要

    该示例在 Docker 中使用数据卷容器。 有关详细信息,请参阅 在 Docker 上配置 SQL Server 容器映像

  4. 要查看容器,请使用 docker ps 命令。

    sudo docker ps -a
    
  5. 如果 STATUS 列显示 Up 状态,则 SQL Server 正在容器中运行,并且在侦听 PORTS 列中指定的端口。 如果 SQL Server 容器的 STATUS 列显示 Exited,请参阅 SQL Server Docker 容器故障排除

    $ sudo docker ps -a
    
    CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
    941e1bdf8e1d        mcr.microsoft.com/mssql/server/mssql-server-linux   "/bin/sh -c /opt/m..."   About an hour ago   Up About an hour    0.0.0.0:1401->1433/tcp   sql1
    
  1. 打开 Linux 上的 bash 终端。

  2. 从 Microsoft 容器注册表中请求 SQL Server 2022 (16.x) Linux 容器映像。

    sudo docker pull mcr.microsoft.com/mssql/server:2022-latest
    
  3. 要通过 Docker 运行容器映像,可使用下列命令:

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql1' -p 1401:1433 \
       -v sql1data:/var/opt/mssql \
       -d mcr.microsoft.com/mssql/server:2022-latest
    

    此命令使用开发人员版创建 SQL Server 2022 (16.x) 容器(默认)。 SQL Server 端口 1433 在主机上公开为端口 1401。 可选的 -v sql1data:/var/opt/mssql 参数会创建一个名为 sql1data 的数据卷容器。 这用于保留 SQL Server 创建的数据。

    重要

    该示例在 Docker 中使用数据卷容器。 有关详细信息,请参阅 在 Docker 上配置 SQL Server 容器映像

  4. 要查看容器,请使用 docker ps 命令。

    sudo docker ps -a
    
  5. 如果 STATUS 列显示 Up 状态,则 SQL Server 正在容器中运行,并且在侦听 PORTS 列中指定的端口。 如果 SQL Server 容器的 STATUS 列显示 Exited,请参阅 SQL Server Docker 容器故障排除

    $ sudo docker ps -a
    
    CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
    941e1bdf8e1d        mcr.microsoft.com/mssql/server/mssql-server-linux   "/bin/sh -c /opt/m..."   About an hour ago   Up About an hour    0.0.0.0:1401->1433/tcp   sql1
    

更改 SA 密码

SA 帐户是在安装期间创建的 SQL Server 实例上的系统管理员。 创建 SQL Server 容器后,可以通过在容器中运行 echo $MSSQL_SA_PASSWORD 来发现指定的 MSSQL_SA_PASSWORD 环境变量。 出于安全考虑,请考虑更改 SA 密码:

  1. 选择 SA 用户要使用的强密码。

  2. 使用 docker exec 运行 sqlcmd 实用工具,以通过 Transact-SQL 语句来更改密码。 将 <YourStrong!Passw0rd><YourNewStrong!Passw0rd> 替换为你自己的密码值:

    重要

    SA_PASSWORD 环境变量已弃用。 请改用 MSSQL_SA_PASSWORD

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourStrong!Passw0rd>' \
       -Q 'ALTER LOGIN SA WITH PASSWORD="<YourNewStrong!Passw0rd>"'
    
    docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd `
       -S localhost -U SA -P "<YourStrong!Passw0rd>" `
       -Q "ALTER LOGIN SA WITH PASSWORD='<YourNewStrong!Passw0rd>'"
    

将备份文件复制到容器中

本教程使用 Microsoft SQL 的 Wide World Importers 示例数据库。 使用以下步骤下载 Wide World Importers 数据库备份文件并将其复制到 SQL Server 容器。

  1. 首先,使用 docker execdocker exec 来创建备份文件夹。 以下命令在 SQL Server 容器中创建 /var/opt/mssql/backup 目录/var/opt/mssql/backup

    sudo docker exec -it sql1 mkdir /var/opt/mssql/backup
    
  2. 接下来,将 WideWorldImporters-Full.bak 文件下载到主机。 以下命令导航到主页/用户目录,并将备份文件下载为 wwi.bakwwi.bak

    cd ~
    curl -L -o wwi.bak 'https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak'
    
  3. 使用 docker cp 将备份文件复制到 /var/opt/mssql/backup 目录的容器中docker cp/var/opt/mssql/backup

    sudo docker cp wwi.bak sql1:/var/opt/mssql/backup
    

还原数据库

备份文件现在位于容器内。 在还原备份之前,请务必了解备份中的逻辑文件名和文件类型。 以下 Transact-SQL 命令使用容器中的 sqlcmd 检查备份并执行还原

提示

本教程在容器中使用 sqlcmd,因为容器内预安装了该工具。 不过,也可以使用容器外的其他客户端工具(例如适用于 Visual Studio Code 的 SQL Server 扩展)来运行 Transact-SQL 语句,或者使用 Windows 上的 SQL Server Management Studio 来管理 Linux 上的 SQL Server。 若要连接,请使用映射到容器中的 1433 端口的主机端口。 在此示例中,为主机上的“localhost,1401”和远程的“Host_IP_Address,1401”localhost,1401Host_IP_Address,1401

  1. 在容器中运行 sqlcmd,列出备份中的逻辑文件名和路径。 这是通过“RESTORE FILELISTONLY”Transact-SQL 语句实现的RESTORE FILELISTONLY

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd -S localhost \
       -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'RESTORE FILELISTONLY FROM DISK = "/var/opt/mssql/backup/wwi.bak"' \
       | tr -s ' ' | cut -d ' ' -f 1-2
    

    应该会看到与下面类似的输出:

    LogicalName   PhysicalName
    ------------------------------------------
    WWI_Primary   D:\Data\WideWorldImporters.mdf
    WWI_UserData   D:\Data\WideWorldImporters_UserData.ndf
    WWI_Log   E:\Log\WideWorldImporters.ldf
    WWI_InMemory_Data_1   D:\Data\WideWorldImporters_InMemory_Data_1
    
  2. 调用 RESTORE DATABASE 命令,还原容器中的数据库。 为上一步中的每个文件指定新路径。

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'RESTORE DATABASE WideWorldImporters FROM DISK = "/var/opt/mssql/backup/wwi.bak" WITH MOVE "WWI_Primary" TO "/var/opt/mssql/data/WideWorldImporters.mdf", MOVE "WWI_UserData" TO "/var/opt/mssql/data/WideWorldImporters_userdata.ndf", MOVE "WWI_Log" TO "/var/opt/mssql/data/WideWorldImporters.ldf", MOVE "WWI_InMemory_Data_1" TO "/var/opt/mssql/data/WideWorldImporters_InMemory_Data_1"'
    

    应该会看到与下面类似的输出:

    Processed 1464 pages for database 'WideWorldImporters', file 'WWI_Primary' on file 1.
    Processed 53096 pages for database 'WideWorldImporters', file 'WWI_UserData' on file 1.
    Processed 33 pages for database 'WideWorldImporters', file 'WWI_Log' on file 1.
    Processed 3862 pages for database 'WideWorldImporters', file 'WWI_InMemory_Data_1' on file 1.
    Converting database 'WideWorldImporters' from version 852 to the current version 869.
    Database 'WideWorldImporters' running the upgrade step from version 852 to version 853.
    Database 'WideWorldImporters' running the upgrade step from version 853 to version 854.
    Database 'WideWorldImporters' running the upgrade step from version 854 to version 855.
    Database 'WideWorldImporters' running the upgrade step from version 855 to version 856.
    Database 'WideWorldImporters' running the upgrade step from version 856 to version 857.
    Database 'WideWorldImporters' running the upgrade step from version 857 to version 858.
    Database 'WideWorldImporters' running the upgrade step from version 858 to version 859.
    Database 'WideWorldImporters' running the upgrade step from version 859 to version 860.
    Database 'WideWorldImporters' running the upgrade step from version 860 to version 861.
    Database 'WideWorldImporters' running the upgrade step from version 861 to version 862.
    Database 'WideWorldImporters' running the upgrade step from version 862 to version 863.
    Database 'WideWorldImporters' running the upgrade step from version 863 to version 864.
    Database 'WideWorldImporters' running the upgrade step from version 864 to version 865.
    Database 'WideWorldImporters' running the upgrade step from version 865 to version 866.
    Database 'WideWorldImporters' running the upgrade step from version 866 to version 867.
    Database 'WideWorldImporters' running the upgrade step from version 867 to version 868.
    Database 'WideWorldImporters' running the upgrade step from version 868 to version 869.
    RESTORE DATABASE successfully processed 58455 pages in 18.069 seconds (25.273 MB/sec).
    

验证还原的数据库

运行以下查询以在容器中显示数据库名称的列表:

sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
   -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
   -Q 'SELECT Name FROM sys.Databases'

应能在数据库列表中看到 WideWorldImporters

做出更改

按照以下步骤在数据库中进行更改。

  1. 运行查询,查看 Warehouse.StockItems 表中的前 10 项Warehouse.StockItems

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'SELECT TOP 10 StockItemID, StockItemName FROM WideWorldImporters.Warehouse.StockItems ORDER BY StockItemID'
    

    应会看到项标识符和名称的列表:

    StockItemID StockItemName
    ----------- -----------------
              1 USB missile launcher (Green)
              2 USB rocket launcher (Gray)
              3 Office cube periscope (Black)
              4 USB food flash drive - sushi roll
              5 USB food flash drive - hamburger
              6 USB food flash drive - hot dog
              7 USB food flash drive - pizza slice
              8 USB food flash drive - dim sum 10 drive variety pack
              9 USB food flash drive - banana
             10 USB food flash drive - chocolate bar
    
  2. 用以下 UPDATE 语句更新第一项的说明UPDATE

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'UPDATE WideWorldImporters.Warehouse.StockItems SET StockItemName="USB missile launcher (Dark Green)" WHERE StockItemID=1; SELECT StockItemID, StockItemName FROM WideWorldImporters.Warehouse.StockItems WHERE StockItemID=1'
    

    应该会看到与以下文本类似的输出:

    (1 rows affected)
    StockItemID StockItemName
    ----------- ------------------------------------
              1 USB missile launcher (Dark Green)
    

新建备份

将数据库还原到容器后,可能还需要定期在正在运行的容器中创建数据库备份。 步骤与之前步骤的模式类似,但顺序相反。

  1. 使用“BACKUP DATABASE”Transact-SQL 命令在容器中创建数据库备份BACKUP DATABASE。 本教程在之前创建的 /var/opt/mssql/backup 目录中创建新的备份文件 wwi_2.bak

    sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q "BACKUP DATABASE [WideWorldImporters] TO DISK = N'/var/opt/mssql/backup/wwi_2.bak' WITH NOFORMAT, NOINIT, NAME = 'WideWorldImporters-full', SKIP, NOREWIND, NOUNLOAD, STATS = 10"
    

    应会看到如下所示的输出:

    10 percent processed.
    20 percent processed.
    30 percent processed.
    40 percent processed.
    50 percent processed.
    60 percent processed.
    70 percent processed.
    Processed 1200 pages for database 'WideWorldImporters', file 'WWI_Primary' on file 1.
    Processed 53096 pages for database 'WideWorldImporters', file 'WWI_UserData' on file 1.
    80 percent processed.
    Processed 3865 pages for database 'WideWorldImporters', file 'WWI_InMemory_Data_1' on file 1.
    Processed 938 pages for database 'WideWorldImporters', file 'WWI_Log' on file 1.
    100 percent processed.
    BACKUP DATABASE successfully processed 59099 pages in 25.056 seconds (18.427 MB/sec).
    
  2. 接下来,将备份文件从容器中复制到主计算机上。

    cd ~
    sudo docker cp sql1:/var/opt/mssql/backup/wwi_2.bak wwi_2.bak
    ls -l wwi*
    

使用持久化数据

除了获取数据库备份来保护数据外,还可以使用数据卷容器。 本教程的开头创建了 sql1 容器,使用了 -v sql1data:/var/opt/mssql 参数。 即使已删除了容器,sql1data 数据卷容器仍会保留 /var/opt/mssql 数据。 以下步骤完全删除 sql1 容器,然后使用保存的数据创建新的容器 sql2

  1. 停止 sql1 容器。

    sudo docker stop sql1
    
  2. 删除容器。 这不会删除以前创建的 sql1data 数据卷容器和其中保存的数据。

    sudo docker rm sql1
    
  3. 创建新的容器 sql2,并重新使用 sql1data 数据卷容器。

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql2' -e 'MSSQL_PID=Developer' -p 1401:1433 \
       -v sql1data:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2017-latest
    
  4. Wide World Importers 数据库现在位于新容器中。 运行查询以验证以前所做的更改。

    sudo docker exec -it sql2 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'SELECT StockItemID, StockItemName FROM WideWorldImporters.Warehouse.StockItems WHERE StockItemID=1'
    

    注意

    SA 密码不是你为 sql2 容器指定的密码 MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>。 所有 SQL Server 数据都是从 sql1 还原的,其中包括本教程前面部分中已更改的密码。 实际上,由于在 /var/opt/mssql. 中还原数据,与此类似的某些选项会被忽略。 出于此原因,密码是 <YourNewStrong!Passw0rd>,如下所示。

  1. 停止 sql1 容器。

    sudo docker stop sql1
    
  2. 删除容器。 这不会删除以前创建的 sql1data 数据卷容器和其中保存的数据。

    sudo docker rm sql1
    
  3. 创建新的容器 sql2,并重新使用 sql1data 数据卷容器。

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql2' -e 'MSSQL_PID=Developer' -p 1401:1433 \
       -v sql1data:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2019-latest
    
  4. Wide World Importers 数据库现在位于新容器中。 运行查询以验证以前所做的更改。

    sudo docker exec -it sql2 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'SELECT StockItemID, StockItemName FROM WideWorldImporters.Warehouse.StockItems WHERE StockItemID=1'
    

    注意

    SA 密码不是你为 sql2 容器指定的密码 MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>。 所有 SQL Server 数据都是从 sql1 还原的,其中包括本教程前面部分中已更改的密码。 实际上,由于在 /var/opt/mssql. 中还原数据,与此类似的某些选项会被忽略。 出于此原因,密码是 <YourNewStrong!Passw0rd>,如下所示。

  1. 停止 sql1 容器。

    sudo docker stop sql1
    
  2. 删除容器。 这不会删除以前创建的 sql1data 数据卷容器和其中保存的数据。

    sudo docker rm sql1
    
  3. 创建新的容器 sql2,并重新使用 sql1data 数据卷容器。

    sudo docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
       --name 'sql2' -e 'MSSQL_PID=Developer' -p 1401:1433 \
       -v sql1data:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2022-latest
    
  4. Wide World Importers 数据库现在位于新容器中。 运行查询以验证以前所做的更改。

    sudo docker exec -it sql2 /opt/mssql-tools/bin/sqlcmd \
       -S localhost -U SA -P '<YourNewStrong!Passw0rd>' \
       -Q 'SELECT StockItemID, StockItemName FROM WideWorldImporters.Warehouse.StockItems WHERE StockItemID=1'
    

    注意

    SA 密码不是你为 sql2 容器指定的密码 MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>。 所有 SQL Server 数据都是从 sql1 还原的,其中包括本教程前面部分中已更改的密码。 实际上,由于在 /var/opt/mssql. 中还原数据,与此类似的某些选项会被忽略。 出于此原因,密码是 <YourNewStrong!Passw0rd>,如下所示。

下一步

在本教程中,你已学习如何在 Windows 上备份数据库,并将其移动到容器中运行 SQL Server 2017 (14.x) 的 Linux 服务器。 你已了解如何执行以下操作:

在本教程中,你已学习如何在 Windows 上备份数据库,并将其移动到容器中运行 SQL Server 2019 (15.x) 的 Linux 服务器。 你已了解如何执行以下操作:

在本教程中,你已学习如何在 Windows 上备份数据库,并将其移动到容器中运行 SQL Server 2022 (16.x) 的 Linux 服务器。 你已了解如何:

  • 创建 SQL Server Linux 容器映像。
  • 将 SQL Server 数据库备份复制到容器中。
  • 使用 sqlcmd 运行 Transact-SQL 语句。
  • 创建和从容器中提取备份文件。
  • 使用数据卷容器来持久保存 SQL Server 生产数据。

接下来,查看其他容器配置和故障排除方案:

参与编辑 SQL 文档

你是否知道你可以自行编辑 SQL 内容? 你如果这样做,不仅可以帮助改进我们的文档,还可以获得页面贡献者的殊荣。

有关详细信息,请参阅如何参与 SQL Server 文档编辑