在Docker容器中恢复数据库

28
在Docker容器内恢复AdventureWorks2017数据库时出现以下错误。运行SQL Server 2019 CTP 2.0(mcr.microsoft.com/mssql/server:vNext-CTP2.0-ubuntu)。备份和目标数据卷均已持久化。创建新数据库没有问题。检查路径并正确。使用2017-latest Docker镜像还原时没有任何问题。其他人是否遇到了这个问题,有解决方法吗?
“Msg 3634,Level 16,State 1,Line 7 The operating system returned the error '2(The system cannot find the file specified.)' while attempting 'RestoreContainer::ValidateTargetForCreation' on '/var/opt/mssql/data/AdventureWorks2017.mdf'。Msg 3156,Level 16,State 5,Line 7 File 'AdventureWorks2017' cannot be restored to '/var/opt/mssql/data/AdventureWorks2017.mdf'。Use WITH MOVE to identify a valid location for the file。Msg 3634,Level 16,State 1, Line 7 The operating system returned the error '2(The system cannot find the file specified.)' while attempting 'RestoreContainer::ValidateTargetForCreation' on '/var/opt/mssql/log/AdventureWorks2017_log.ldf'。Msg 3156,Level 16, State 5,Line 7 File 'AdventureWorks2017_log' cannot be restored to '/var/opt/mssql/log/AdventureWorks2017_log.ldf'。Use WITH MOVE to identify a valid location for the file。Msg 3119,Level 16,State 1, Line 7 Problems were identified while planning for the RESTORE statement。Previous messages provide details。Msg 3013,Level 16, State 1,Line 7 RESTORE DATABASE is terminating abnormally。”
创建容器。
$datapath = "D:\Foo";
$logpath = "D:\Foo";
$backuppath = "D:\Foo";
$pass = ":-)"

$ct = (docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=$pass" `
    -e "MSSQL_PID=Developer" -p 2017:1433 `
    -e "MSSQL_TCP_PORT=1433" `
    -v ${datapath}:/var/opt/mssql/data `
    -v ${logpath}:/var/opt/mssql/log `
    -v ${backuppath}:/var/opt/mssql/backup `
    -e "MSSQL_BACKUP_DIR=/var/opt/mssql/backup" `
    -e "MSSQL_DATA_DIR=/var/opt/mssql/data" ` 
    -e "MSSQL_LOG_DIR=/var/opt/mssql/log" `
    -d mcr.microsoft.com/mssql/server:vNext-CTP2.0-ubuntu)

恢复命令。

RESTORE DATABASE [AdventureWorks2017] FROM  DISK = N'/var/opt/mssql/backup/AdventureWorks2017.bak' 
WITH  FILE = 1,  
MOVE N'AdventureWorks2017' TO N'/var/opt/mssql/data/AdventureWorks2017.mdf',  
MOVE N'AdventureWorks2017_log' TO N'/var/opt/mssql/log/AdventureWorks2017_log.ldf', 
NOUNLOAD,  STATS = 1 

你正在运行哪个命令?你是如何将AdventureWorks2017文件放入容器中的? - Shoan
added to question - Daniel N
如果您不从主机计算机映射目录,则不会出现此错误。 - Alew
7个回答

36

通过首先创建一个空的数据库,然后使用“替换”选项进行还原,成功地解决了这个问题。


1
这个问题在Windows 1909、Docker Desktop 2.1.0.5和SQL Server 2019上仍然存在。你提供的解决方法是我找到的唯一可行的解决方案。 - Jaecen
我不确定原因,但在2022年,当我尝试在Mac M1上使用Docker恢复数据库时,以下方法适用:先使用CREATE DATABASE xxx;再使用RESTORE DATABASE xxx FROM DISK = '/xxx' WITH REPLACE; - trebor

23

我已在Windows 1909、Docker Desktop 2.3.0.3和SQL Server 2019上重现了此问题。

我验证了三种解决方法:

  1. Daniel的解决方法是创建数据库并在其上还原
  2. 在还原之前手动创建文件
  3. 使用卷映射存储而不是主机文件夹映射存储

我发现只有在指定docker -v或--mount标志将主机文件夹映射到容器文件夹时才会出现此问题。不幸的是,这正是我想要做的,以利用附加到我的主机的各种存储卷。

我能够成功地将数据库还原到其他文件夹,包括卷映射文件夹,但需要注意权限。请确保mssql用户可以写入该文件夹,或者以root身份运行该进程。

在还原之前手动创建文件也可以实现相同的效果。请注意,即使数据库尚不存在,您也需要在还原中使用REPLACE选项。

docker run `
    -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=$pwd" `
    -e "MSSQL_DATA_DIR=/home/data" `
    -e "MSSQL_LOG_DIR=/home/log" `
    -e "MSSQL_BACKUP_DIR=/home/backup" `
    --mount source=sql2019sysdatavol,target=/var/opt/mssql `
    --mount type=bind,source="E:\SQL2019\Data",target=/home/data `
    --mount type=bind,source="E:\SQL2019\Log",target=/home/log `
    --mount type=bind,source="E:\SQL2019\Backup",target=/home/backup `
    --name sql2019 --hostname sql2019 `
    -p 1433:1433 `
    -d mcr.microsoft.com/mssql/server:2019-latest

docker container exec sql2019 touch /home/data/AdventureWorks2019.mdf
docker container exec sql2019 touch /home/log/AdventureWorks2019_Log.ldf

$cmd = " `
    RESTORE DATABASE [AdventureWorks2019] `
    FROM  DISK = N'/home/backup/AdventureWorks2019.bak' `
    WITH  FILE = 1, STATS = 5, REPLACE, `
    MOVE N'AdventureWorks2017' TO  N'/home/data/AdventureWorks2019.mdf', `
    MOVE N'AdventureWorks2017_Log'  TO  N'/home/log/AdventureWorks2019_Log.ldf'"

sqlcmd '-Usa' "-P$pwd" '-S127.0.0.1,1433' "-Q"$cmd""
5 percent processed.
...
100 percent processed.
Processed 26344 pages for database 'AdventureWorks2019', file 'AdventureWorks2017' on file 1.
Processed 2 pages for database 'AdventureWorks2019', file 'AdventureWorks2017_log' on file 1.
RESTORE DATABASE successfully processed 26346 pages in 3.018 seconds (68.198 MB/sec).

1
2021年仍存在问题:Win 21H1,Docker Desktop 4.1.1,SQL Server 2019:latest。尝试使用 -u 0:0 以 root 身份运行容器,但出现相同的错误。接触文件可以正常工作。 - brunosp86
谢谢,确认 (2) 已经在 2022 SQL Server 2019:latest 中手动创建文件。 - Jayden
我唯一可行的选择是在运行“RESTORE”命令之前“touch”文件。 - Lord of the Goo
我正在使用Microsoft的此示例数据库,并且touch命令适用于前3个逻辑文件,但第4个文件仍然出现问题。如果有帮助的话,这是源逻辑名称:WWI_InMemory_Data_1和物理名称:D:\Data\WideWorldImporters_InMemory_Data_1 - bkwdesign
好的,在我的情况下,除了使用 touch 命令创建两个 .mdf 文件和一个 .ldf 文件之外,我还需要为内存数据库执行 mkdir 命令。 - bkwdesign

2

我为这个问题苦苦挣扎了数小时。问题在于该目录没有完全权限。

chmod 777 hds
cd hds

sqlcmd -U SA -P <db_password>  -Q "RESTORE DATABASE XSP_A0 FROM DISK=N'/home/hds/DBchema.bak' WITH REPLACE, MOVE N'XSP_A0' TO N'/home/hds/XSP_A0.mdf' , MOVE N'XSP_A0_log' TO N'/home/hds/XSP_A0.ldf'"

1

我正在Windows 10笔记本电脑上运行在Linux容器中的SQL Server。我使用的命令如下。

docker run --name testdb3 -d -p 1433:1433 -e MSSQL_SA_PASSWORD=G52ndTOur -e ACCEPT_EULA=Y -v D:/Vivek/Trials/SqlDocker/data:/var/opt/mssql/data -v D:/Vivek/Trials/SqlDocker/log:/var/opt/mssql/log -v D:/Vivek/Trials/SqlDocker/secrets:/var/opt/mssql/secrets mcr.microsoft.com/mssql/server

一旦命令执行并且容器正在运行,这将在Windows机器上创建三个文件夹,如下所示。

Mounted widows folders with sql server running on linux container

现在将您的.bak文件复制到其中一个文件夹中,比如数据文件夹。
按照以下方式使用SSMS连接到运行在容器中的服务器。',1433'是可选的,因为1433是默认值。因此,一个点(.代表本地主机)也应该可以工作。

Connect to Sql Server running in the container using SSMS

接下来创建您要还原的数据库。在我的情况下,它是 SqlServerOnDocker。

现在右键单击“数据库”,然后选择“还原数据库”。

Restore Database in SSMS

Select You database backup file.

点击“确定”,然后再次点击“确定”。现在在相同的“还原数据库”对话框中,如下所示选择“选项”。

Select Options in Restore Database Dialog

现在点击“确定”以恢复您的数据库。

1

请检查您是否已经为保存该数据库的mdf和ldf文件夹提供了完整的权限。


1
Docker容器在Linux中应该具有root权限。同时,主机上也设置了完全权限。 - Daniel N

0

我正在使用Mac尝试使用挂载的主机卷来处理数据,但我发现这是由于文件名的大小写问题造成的。


0
我在Mac OS上遇到了同样的问题。我正在使用Docker桌面版。所以,我遇到了这个错误,因为Docker桌面版对"虚拟磁盘限制"设置有限制。 打开Docker桌面版 -> 设置 -> 资源 -> 虚拟磁盘限制,增加磁盘限制,之后一切都正常工作了。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接