SQL Server2005 sys.sysobjvalues 整合性エラー修復方法

SQL Server2005で次のような整合性エラーが発生する場合がある。


失敗:(-1073548784) クエリ “DBCC CHECKDB WITH NO_INFOMSGS
” の実行が次のエラーで失敗しました: “オブジェクト ID 60、インデックス ID 1、パーティション ID 281474980642816、アロケーション ユニット ID 71776119065149440 (型 LOB data) のページ (1:193) の PFS 空き領域情報が不適切です。予想値   0_PCT_FULL、実際の値 100_PCT_FULL。
CHECKDB により、テーブル ‘sys.sysobjvalues’ (オブジェクト ID 60) に 0 個のアロケーション エラーと x 個の一貫性エラーが見つかりました。


SQL Serverのバグらしい。

http://www.sqlservercentral.com/Forums/Topic766849-266-1.aspx(英語)

http://www.sqlskills.com/BLOGS/PAUL/post/Corruption-bug-that-people-are-hitting-Msg-8914-PFS-free-space.aspx(英語)


【修復方法】 REPAIR_ALLOW_DATA_LOSSオプションはデーターが失われる可能性があるため注意する必要がある

(1)シングルユーザーモードにする(しないとREPAIR_ALLOW_DATA_LOSSオプションが使えない)
ALTER DATABASE [DB名] SET SINGLE_USER

(2)DBをバックアップ(REPAIR_ALLOW_DATA_LOSSオプションはデーターが失われる可能性があるため)

(3)修復
DBCC CHECKDB (‘DB名’, REPAIR_ALLOW_DATA_LOSS)

(4)整合性チェック
DBCC CHECKDB (‘DB名’)
DBCC CHECKCONSTRAINTS

(5)マルチユーザーモードに戻す
ALTER DATABASE [DB名] SET MULTI_USER

参考:
http://msdn.microsoft.com/ja-jp/library/ms176064.aspx

【注意】
データーが失われる可能性があるためバックアップを取っておくこと.
修復後にデーターが失われていないか確認する手段を準備しておくこと.
修復中はサーバーが無反応に近くなる場合がある.
したがって,あらかじめテスト環境等で作業に要する時間を調査しておくこと.
作業時間には修復に失敗した場合のリストア時間も含めること.

VB2005 + SQL (複数テーブル参照でCommandBuilderが使えない場合)

データーをストアドからDataTableへ受け取り,グリッドに表示
  (複数テーブル参照でCommandBuilderが使えない場合)
  CommandBuilderが使えない場合は,InsertCommand・UpdateCommand・DeleteCommandをそれぞれ自前で作る

    Dim cn As SqlClient.SqlConnection
    Dim da As New SqlClient.SqlDataAdapter()
    Dim dt As New DataTable

    Private Sub a1()
        Dim cmd As New SqlClient.SqlCommand(“stHoge”, cn)
        Try
            cmd.CommandType = CommandType.StoredProcedure
            da.SelectCommand = cmd

            ‘Insert
            cmd = New SqlClient.SqlCommand(“stHogeInsert”, cn)
            cmd.CommandType = CommandType.StoredProcedure
            cmd.Parameters.Clear()
            cmd.Parameters.Add(“@a1”, SqlDbType.Int, 4, “a1”)
            ‘ID値を返す(これがないとIDが不定となる)
            Dim parameter As SqlClient.SqlParameter = cmd.Parameters.Add(“@Identity”, SqlDbType.Int, 4, “ID”)
            parameter.Direction = ParameterDirection.Output
            da.InsertCommand = cmd

            ‘Update
            cmd = New SqlClient.SqlCommand(“stHogeUpdate”, cn)
            cmd.CommandType = CommandType.StoredProcedure
            cmd.Parameters.Clear()
            cmd.Parameters.Add(“@ID”, SqlDbType.Int, 4, “ID”)
            cmd.Parameters.Add(“@a2”, SqlDbType.Int, 4, “a2”)
            da.UpdateCommand = cmd

            ‘Delete
            cmd = New SqlClient.SqlCommand(“stHogeDelete”, cn)
            cmd.CommandType = CommandType.StoredProcedure
            cmd.Parameters.Clear()
            cmd.Parameters.Add(“@ID”, SqlDbType.Int, 4, “ID”)
            da.DeleteCommand = cmd

            dt.PrimaryKey = Nothing
            dt.Locale = System.Globalization.CultureInfo.InvariantCulture
            dt.Clear()
            da.Fill(dt)
            ‘dt.PrimaryKey = New DataColumn() {dt.Columns(“ID”)}

            DGV.DataSource = dt

        Finally
            cmd.Dispose()
        End Try

    End Sub

VB2005 + SQL CommandBuilder使用

データーをストアドからDataTableへ受け取り,DataGridViewに表示 (CommandBuilder使用)

  Dim cn As SqlConnection
  Dim da As New SqlClient.SqlDataAdapter()
  Dim dt As New DataTable

  Private Sub a()

    Dim cmd As New SqlClient.SqlCommand(“stHoge”, cn)
    Try
      cmd.CommandType = CommandType.StoredProcedure
      cmd.Parameters.Clear
      cmd.Parameters.Add(“@ID”, SqlDbType.Int).Value = ID
      da.SelectCommand = cmd
      dt.Locale = System.Globalization.CultureInfo.InvariantCulture
      dt.Clear()
      Dim commandBuilder As New SqlClient.SqlCommandBuilder(da)
      da.Fill(dt)
      dt.Columns(“ID”).ReadOnly = True
      DGV.DataSource = dt
    Finally
     cmd.Dispose()
    End Try

  End Sub

    ‘更新
    Private Sub b()
        da.Update(dt)
        dt.AcceptChanges()
    End Sub