none
SQL Server 2008のFileStream機能で4GB超のファイルを登録すると4GB分足りなくなる RRS feed

  • 質問

  • Visual Studio 2008 C#で、SQL Serverに接続するアプリケーションを作っています。

    4GBを超えるバイナリファイルをSQL Serverに登録するにあたって、SQL Server 2008/2012ではFileStreamデータ型を使い登録しています。

    SQL Server側にある「C:\data\4GB.dat」を作業用のデータベース「TempDatabase」に格納します。

    //作業用データベースの作成
    _sql = string.Format("CREATE DATABASE {1}"
        + " ON PRIMARY (NAME = mdf,"
        + " FILENAME = '{0}{1}.mdf',"
        + "SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%),"
        + " FILEGROUP data CONTAINS FILESTREAM (NAME = data,"
        + "FILENAME = '{0}{1}')"
        + " LOG ON (NAME = ldf,"
        + "FILENAME = '{0}{1}.ldf',"
        + "SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%)", "C:\\data\\", "TempDatabase");

    _command.CommandText = _sql;
    _command.ExecuteNonQuery();

    //作業用テーブルの作成
    _sql = "CREATE TABLE TempDatabase.dbo.Records"
        + " ([ID] UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,"
        + "[bck] VARBINARY(MAX) FILESTREAM NULL)";

    _command.CommandText = _sql;
    _command.ExecuteNonQuery();

    _sql = string.Format("INSERT INTO {0}(ID,bck) SELECT NEWID() AS [ID], CAST(BulkColumn AS VARBINARY(MAX)) FROM OPENROWSET(BULK N'{1}',SINGLE_BLOB) AS [bck]", "TempDatabase.dbo.Records", "C:\\data\\4GB.dat");

    _command.CommandText = _sql;
    _command.ExecuteNonQuery();

    おおよそ以上のような手順にしています。その結果、SQL Server 2012では正常に登録され、「C:\data\TempDatbase」フォルダに「0881a803-5c5b-493b-9db3-xxxxxx」というような名前のフォルダが作られ、その中に「dbe1ffcf-b617-455b-a3d9-xxxxxx」というような名前のフォルダがあって、「00000014-00000067-xxxx」というような名前のファイルが作られます。そのファイルサイズは「c:\data\4GB.dat」と同じで、ファイルを比較してもまったく同じです。

    ところが、SQL Server 2008を対象に実行すると、エラーも発生せず終了するのですが、できあがったファイルは、ファイルサイズがちょうど4GB分(2^32=4294967296バイト分)不足した状態になっています。

    INSERT INTO文をあれこれ修正して実行してみましたが、変化はありませんでした。当初はSQL Server 2008のバグかと思い、ServicePack1をあててみたり、SQL Server 2008 R2で実行してみましたが、変化はありませんでした。
    (サーバOSはいずれもWindows Server 2008 Standard)

    どなたかこの現象についてなにかご存じのことがありましたら、お教えください。

    2013年7月8日 5:45

すべての返信

  • 情報を追加します。

    SQL Server 2008(Standard)にService Pack2やService Pack3をあて、最新の状態にしてみましたが、変化はありませんでした。
    (Windows Serverとも)

    作成中のアプリケーションとの切り分けを行なうため、C:\backupフォルダを作成し4GB.bakファイルを配置してから、Transact-SQLで

    ■データベースを作成する
    CREATE DATABASE TempDataBase ON PRIMARY (NAME = mdf, FILENAME = 'C:\backup\TemDataBase.mdf', SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%), FILEGROUP data CONTAINS FILESTREAM (NAME = data, FILENAME = 'C:\backup\TemDataBase') LOG ON (NAME = ldf, FILENAME = 'C:\backup\TemDataBase.ldf', SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%);

    ■テーブルを作成する
    CREATE TABLE TempDataBase.dbo.Records ([ID] UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,[bck] VARBINARY(MAX) FILESTREAM NULL);

    ■データを登録する
    INSERT INTO TempDataBase.dbo.Records([ID],[bck]) SELECT NEWID() AS [ID], CAST(BulkColumn AS VARBINARY(MAX)) FROM OPENROWSET(BULK N'C:\backup\4GB.bak',SINGLE_BLOB) AS [bck];

    としても同じ症状です。

    ファイルサイズが2.7GBの場合には問題なく登録できています。しかし、4GBを超えた、たとえば4.55GB(4,889,013,760バイト)のファイルを対象にすると、566MB(594,046,464バイト)のファイルができあがります。その差が4,294,967,296バイトで、ちょうど4GBです。ちょうど4GB分切れてしまうことから、SQL Server 2008のバグではないかとも思いましたが、あまりにイージー(それでいて致命的)なバグがこれまで見過ごされてきたとは思えません。

    引き続き情報を求めたいと思います。

    どなたかお助けを....

     

    2013年7月10日 3:08
  • 気になって調べてみたところ、仕様みたいですね。

    http://msdn.microsoft.com/en-us/library/bb895334(v=sql.105).aspx
    にコメントとして以下のように書かれています。

     > The maximum database size for Denali is also incorrect

     > It's unlikely that Microsoft would decrease the maximum database size limit in Denali back down to 4GB however I've been unable to find the Denali limit anywhere.

    2013年7月24日 2:01