RESTORE FILELISTONLY FROM DISKでの復元

昨日、とあるお客さんからSQLServerのバックアップ用スクリプトが
正しく動かないので急ぎで直して欲しいと言われ修正した時のメモ。

ちなみにバッチファイルの方でそのとき出力されていたエラー文は下記のようなもの。

メッセージ 911、レベル 16、 状態 11、サーバー XXXXXXX、行 1
エントリがデータベース ‘yyyyyy’ のsysdatabasesに見つかりませんでした。
指定された名前のエントリがありませんでした。名前が正しく入力されていることを確認してください。

メッセージ 3013、レベル 16、状態 1、サーバー XXXXXX、行 1
BACKUP DATABASEが異常終了しています。

更に調べてみると、SQLファイルの方でもログを出力されるようになっていたので
該当のログファイルを見てみると下記のようなエラーが・・・。

メッセージ 213、レベル 16、状態 7、サーバー XXXXXX、行 1
挿入エラー : 列名または指定された値の数がテーブルの定義と一致しません。
メッセージ 3013、レベル 16、状態 1、サーバー XXXXXX、行 1
RESTORE FILELIST が異常終了しています。

ん?「列名または指定された値の数がテーブルの定義と一致しません」?

SQLファイルを見てみると、どうもバックアップしたファイルを
RESTORE FILELISTONLY FROM DISK で読み込み
それを一時テーブルに入れてから復元している模様。

その際、一時テーブルを以下のような形で生成していました。

CREATE TABLE #tmp (
LogicalName nvarchar(128) ,
PhysicalName nvarchar(260) ,
Type char(1) ,
FileGroupName nvarchar(128) ,
[Size] numeric(20,0) ,
[MaxSize] numeric(20,0)
);

これに対してRESTORE FILELISTONLY FROM DISKで読み込んだテーブルには下記のようなヘッダーが存在する模様。
LogicalName PhysicalName Type FileGroupName Size MaxSize
FileId CreateLSN DropLSN UniqueId ReadOnlyLSN ReadWriteLSN
BackupSizeInBytes SourceBlockSize FileGroupId LogGroupGUID
DifferentialBaseLSN DifferentialBaseGUID IsReadOnly IsPresent

あれ、なんか全然数が一致していない・・・。
ということで、一時テーブルの作成部分を以下のように修正。

CREATE TABLE #tmp (
LogicalName nvarchar(128) ,
PhysicalName nvarchar(260) ,
Type char(1) ,
FileGroupName nvarchar(128) ,
[Size] numeric(20,0) ,
[MaxSize] numeric(20,0),
FileID bigint,
CreateLSN DECIMAL(25,0),
DropLSN DECIMAL(25,0),
UniqueID UNIQUEIDENTIFIER,
ReadOnlyLSN DECIMAL(25,0),
ReadWriteLSN DECIMAL(25,0),
BackupSizeInBytes DECIMAL(25,0),
SourceBlockSize INT,
FileGroupId INT,
LogGroupGUID UNIQUEIDENTIFIER,
DifferentialBaseLSN DECIMAL(25,0),
DifferentialBaseGUID UNIQUEIDENTIFIER,
IsReadOnly BIT,
IsPresentBIT
);

これで、無事動きました!
ただ、以前は元のスクリプトで動いていたのに急に動かなくなったと言われたので
SQLServerの更新か何かで変わったのかなとは思いますが詳しくは不明。

また、今回の環境はSQLServer2005だったのですが、2008環境ではこれはうまく動かないようです。

いずれにせよ、いきなり直して欲しいと言われ、しかも自分が作成したやつではない上に
SQLServerは普段あまり使用しないので、最初はどうなるかと思いましたが、修正できてよかったです。

コメントを書く

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です