在 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 语句来查看和修改数据库。
- 备份修改后的数据库。
先决条件
- 安装的容器运行时,例如 Docker,或者 Podman
- 安装最新的 sqlcmd
- Linux 上的 SQL Server 的系统要求。
部署选项
本部分提供环境部署选项。
sqlcmd 目前不支持在创建容器时使用 MSSQL_PID
参数。 如果使用本教程中的 sqlcmd 说明,你将使用 SQL Server 开发人员版本创建容器。 依照命令行接口 (CLI) 指令,使用所选许可证创建容器。 有关详细信息,请参阅部署并连接到 SQL Server Linux 容器。
拉取并运行容器映像
打开 Linux 上的 bash 终端。
从 Microsoft 容器注册表中请求 SQL Server 2017 (14.x) Linux 容器映像。
sudo docker pull mcr.microsoft.com/mssql/server:2017-latest
要通过 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 容器映像。
要查看容器,请使用
docker ps
命令。sudo docker ps -a
如果
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
打开 Linux 上的 bash 终端。
从 Microsoft 容器注册表中请求 SQL Server 2019 (15.x) Linux 容器映像。
sudo docker pull mcr.microsoft.com/mssql/server:2019-latest
要通过 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 容器映像。
要查看容器,请使用
docker ps
命令。sudo docker ps -a
如果
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
打开 Linux 上的 bash 终端。
从 Microsoft 容器注册表中请求 SQL Server 2022 (16.x) Linux 容器映像。
sudo docker pull mcr.microsoft.com/mssql/server:2022-latest
要通过 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 容器映像。
要查看容器,请使用
docker ps
命令。sudo docker ps -a
如果
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 密码:
选择 SA 用户要使用的强密码。
使用
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 容器。
首先,使用 docker exec
docker exec
来创建备份文件夹。 以下命令在 SQL Server 容器中创建 /var/opt/mssql/backup 目录/var/opt/mssql/backup
。sudo docker exec -it sql1 mkdir /var/opt/mssql/backup
接下来,将 WideWorldImporters-Full.bak 文件下载到主机。 以下命令导航到主页/用户目录,并将备份文件下载为 wwi.bak
wwi.bak
。cd ~ curl -L -o wwi.bak 'https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak'
使用 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,1401
Host_IP_Address,1401
。
在容器中运行 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
调用
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
。
做出更改
按照以下步骤在数据库中进行更改。
运行查询,查看 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
用以下 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)
新建备份
将数据库还原到容器后,可能还需要定期在正在运行的容器中创建数据库备份。 步骤与之前步骤的模式类似,但顺序相反。
使用“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).
接下来,将备份文件从容器中复制到主计算机上。
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
。
停止
sql1
容器。sudo docker stop sql1
删除容器。 这不会删除以前创建的
sql1data
数据卷容器和其中保存的数据。sudo docker rm sql1
创建新的容器
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
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>
,如下所示。
停止
sql1
容器。sudo docker stop sql1
删除容器。 这不会删除以前创建的
sql1data
数据卷容器和其中保存的数据。sudo docker rm sql1
创建新的容器
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
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>
,如下所示。
停止
sql1
容器。sudo docker stop sql1
删除容器。 这不会删除以前创建的
sql1data
数据卷容器和其中保存的数据。sudo docker rm sql1
创建新的容器
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
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 文档编辑