web-dev-qa-db-ja.com

sys.database_filesでis_media_read_only列のUPDATEを正確にトリガーするものは何ですか?

これを解決しようとする 間違った値に関連する問題is_media_read_onlyデータベースプロパティの場合、いくつかの調査とテストを行いましたが、最終的には何を整理できなかったかexactlyは、is_media_read_onlyに対する列sys.database_filesのUPDATEをトリガーします。

sys.database_files のドキュメントによると、列is_media_read_onlyには次の2つの値のいずれかが必要です。

1 =ファイルは読み取り専用メディア上にあります。

0 =ファイルは読み取り/書き込みメディアにあります。

この情報を使用して、SQL Serverの2つの異なるバージョンで次の実験を行いました。

Microsoft SQL Server 2014(SP3-GDR)(KB4505218)-12.0.6108.1(X64)
Microsoft SQL Server 2017(RTM-CU16)(KB4508218)-14.0.3223.3(X64)

ノートブック(ドライブE :)にペンドライブを差し込み、次のようにデータベースを作成しました。

CREATE DATABASE [MyDB]
 ON  PRIMARY 
( NAME = N'MyDB_01', FILENAME = N'D:\DataBases\MyDB_01.mdf'), 
 FILEGROUP [SECONDARY] 
( NAME = N'MyDB_02', FILENAME = N'E:\DataBasesPendrive\MyDB_02.ndf')
 LOG ON 
( NAME = N'MyDB_log', FILENAME = N'D:\DataBases\MyDB_log.ldf')
GO

クエリされたsys.database_files:

USE MyDB;
GO
SELECT file_id, name, physical_name, is_media_read_only, is_read_only, state_desc  
FROM sys.database_files;
GO

これは結果でした:

Query result before

データベースが作成されたら、CMDプロンプトを開いてdiskpartを実行しました。ユーティリティで、次のコマンドを発行しました。

list disk
select disk 2
attributes disk set readonly
attributes disk

DiskPart

ディスク2(ペンドライブ)は読み取り専用メディアになったので、is_media_read_only値が変更されることを期待していましたが、照会するとsys.database_files再び変更はありませんでした:is_media_read_onlyはまだ0でした。そこで、データベースをランダムに実行し、データベースが読み取り専用メディアに置かれていることをSQL Serverが認識して、値を1. 2つの状況でこれを達成できます。

1st:データベースをREAD_ONLYモードに変更し、READ_WRITEに戻します。 (それは両方のアクションでなければなりません、それらの1つだけではトリックは行われません):

USE master;
GO
ALTER DATABASE MyDB SET READ_ONLY;
ALTER DATABASE MyDB SET READ_WRITE;
GO

2番目:データベースをデタッチして再度アタッチします。

これらは、画像からわかるように、is_media_read_only1に更新できる2つの状況でした。

Query result after

さて、ペンドライブを再びread_writeに戻すときがきたので、diskpartに戻って実行しました。

select disk 2
attributes disk clear readonly

ディスク2を再度読み取り書き込みモードに変更すると、is_media_read_onlyは、切り離しと接続の手順で0のみ更新します。 SQL Serverインスタンスを再起動して、値が更新されることを期待しましたが、うまくいきませんでした。

データベースがデタッチおよびアタッチされるまで、SQL Serverは、ディスクが1でなくなった場合でも、is_media_read_onlyの値READ_ONLYを残します。

したがって、私の質問:is_media_read_onlyで列sys.database_filesUPDATEを正確にトリガーするものは何ですか?この実験で示された動作はSQL Serverのバグですか?

8
Ronaldo

私はSQL Server製品チームのエンジニアです。この読み取り専用メディアの動作は仕様によるものではなく、修正プログラムを発行しました。

動作を説明するために、ファイルが開かれたときに読み取り専用のメディアチェックが行われます(例:DBの起動、readonly-> readwriteのようなDBの状態の変更)。その後、SQLはメモリ内のファイルの読み取り専用メディアフラグを維持し、これをメタデータ(システムカタログ上)に永続化できます。他のファイルのメタデータがたまたま変更されたり、DBの状態が変化したりすると、フラグがメタデータに永続化される場合があります。ここでの実際の問題は、メタデータ(プライマリデータファイルにある)で強化されると、メディアが読み取り専用でなくても、メタデータを適切にリセットしなかったことです。フラグをリセットできる条件の1つはアタッチですが、それはセカンダリデータファイルに対してのみ行われます。

望ましい動作は、ファイルが開かれ、メディアが読み取り専用ではなくなったときに、読み取り専用のメディアフラグがオフになることです。そのため、データベースが再起動すると、データベースの状態が変化し、復元され、またはデータベースがアタッチされたときに、is_media_read_onlyはすべてのファイルに対してデータベースを正しく反映する必要があります。

修正

修正は KB Article 4538378 で文書化されています。

7
wonkim

LowlyDBAが提案するように、ファイル自体に変更を加えようとすると、値が更新されるようです。ただし、セカンダリデータファイルに変更を加える必要がない場合にのみ、ディスクが読み取り専用に設定されている場合に限ります。まだ変更が必要な場合は、別のエラーが表示されます。

たとえば、F:\にデータファイルが1つあるデータベースを作成する場合、後で読み取り専用として設定します。

USE MASTER
GO
CREATE DATABASE Test
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'Test1', FILENAME = N'E:\Data\Test.mdf' , SIZE = 4160KB , MAXSIZE = UNLIMITED, FILEGROWTH = 16384KB ),
( NAME = N'testreadonly', FILENAME = N'F:\ReadonlyDisk\testreadonly.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 16384KB )
 LOG ON 
( NAME = N'Test_log', FILENAME = N'E:\Data\Test_Log.ldf' , SIZE = 1040KB , MAXSIZE = 2048GB , FILEGROWTH = 16384KB )
GO

Diskpartコマンドを実行した後、予想どおりis_media_read_onlyは変更されません。

USE Test
GO
select name,physical_name,is_media_read_only,is_read_only
from sys.database_files;

結果

name             physical_name                      is_media_read_only  is_read_only
Test1            E:\Data\Test.mdf                   0                    0
Test_log         E:\Data\Test_Log.ldf               0                    0
testreadonly     F:\ReadonlyDisk\testreadonly.ndf   0                    0

ファイルサイズを大きくしようとすると、次のようになります。

USE [master]
GO
ALTER DATABASE [Test] MODIFY FILE ( NAME = N'testreadonly', SIZE = 6144KB )
GO

私はそれが2つの方法で起こっていることに気づきました。デバイスの準備ができていないというエラーメッセージです。

メッセージ5149、レベル16、状態3、行21物理ファイル 'F:\ ReadonlyDisk\testreadonly.ndf'を拡張しようとしたときに、MODIFY FILEでオペレーティングシステムエラー21(デバイスの準備ができていません)が発生しました。

これは悪い状態です。データベースが整合性のある状態になる前にSQLサーバーがセカンダリデータファイルを変更する必要があるため、データベースもオフラインとオンラインに戻ることができなくなります。

ディスクはread_onlyに設定されていましたが、セカンダリデータファイルに変更を加える必要がありました。

もう1つのエラーメッセージは、データベースを再びオンラインとオフラインに設定でき、SQLサーバーがディスクの状態を認識しているが、変更はできないことを示しています。

物理ファイル 'F:\ ReadonlyDisk\testreadonly.ndf'を拡張しようとしたときに、MODIFY FILEでオペレーティングシステムエラー19(メディアは書き込み保護されています。)が発生しました。

この2番目のエラーメッセージが発生すると、たとえばファイルサイズを変更すると、状態が更新されます。

use master  
go
ALTER DATABASE [Test] MODIFY FILE ( NAME = N'testreadonly', SIZE = 10240KB )
GO

is_media_read_only列が更新される結果:

name             physical_name                      is_media_read_only  is_read_only
Test1            E:\Data\Test.mdf                   0                    0
Test_log         E:\Data\Test_Log.ldf               0                    0
testreadonly     F:\ReadonlyDisk\testreadonly.ndf   1                    0

.mdfまたは.ldfファイルを読み取り専用ディスクに配置すると、再起動時にデータベースがオンラインになりません。これらのファイルはデータベース回復の分析ステップで変更されるため。

これを検証するには、別のデータベースを作成し、3つのファイル(.mdf.ndf.ldf)をすべて同じディスクに置き、オフラインとオンラインに再度設定します。

ALTER DATABASE [Test] SET OFFLINE

ALTER DATABASE [Test] SET ONLINE 

.mdfおよび.ldfが最後のオフライン以降に変更された場合->オンライン

enter image description here

したがって、理論的には、セカンダリファイルを読み取り専用ディスクに置くことができ、SQLサーバーが読み取り専用ディスクにあることをSQLサーバーが認識すると、is_media_read_only列が更新されます。

セカンダリデータファイルに変更が加えられていないため、データベースまたはインスタンスを再起動するときに、これを知ることはできません。リカバリのUNDOまたはREDOプロセス中などの変更がセカンダリデータファイルに発生する必要がある場合、データベースはオンラインになりません。

.mdfまたは.ldfファイルでこれを試行すると、データベースがオンラインにならず、次のようなエラーメッセージが表示されます。

FixupLogTail中のファイル「ファイルの場所」でのオペレーティングシステムエラー19(メディアは書き込み保護されています。).

これらは、dbの起動時に変更されるためです。

したがって、どちらの実験でも、ファイルの変更によってis_media_read_onlyが変化することがわかりました。一貫性がないように見えますが、それはある意味でパターンです。その結論で、この問題はそのフラグの「通常の」動作を超えていると言えるでしょうか?

さて私は実際のすべてのファイル変更がそれを引き起こす可能性がある/するだろうと言いますが、ファイル変更が発生しなければならない場合、またはデータベースが一貫した状態にない場合、データベースは単にオンラインにならない/他の問題が発生します。手動でファイルを拡張するなど、データベースが一貫した状態にあるときに変更が失敗した場合、エラーが発生し、is_media_read_onlyが更新されます。

そしてここでも、ディスクを読み取り専用に変更して実行するとファイルの変更は行われません

USE master;
GO
ALTER DATABASE Test SET READ_ONLY;
ALTER DATABASE Test SET READ_WRITE;
GO

次に、ディスクを再度読み取り/書き込みに変更し、2つのalter databaseステートメントを再度実行します。

enter image description here

is_media_read_onlyが元に戻らないのは、ファイルが再度書き込み可能ディスク上にあることが「テスト」されていないためです。

はい、そのテスト。それはこのようでした:パート1-ドライブをread_onlyに変更します。データベースをread_onlyに変更します。データベースをread_writeに変更します。 is_media_read_onlyは1(完全)です。パート2-ドライブをread_writeに変更します。データベースをread_onlyに変更します。データベースをread_writeに変更します。 is_media_read_onlyは1のままです(すべてのファイル変更がis_media_read_onlyの更新をトリガーするという結論をサポートするには、0に変更する必要があります)。

編集で表示されるように、データベースを読み取り専用に変更して再度戻す場合、セカンダリデータファイルは変更されません。実際に試みられたすべてのファイル変更は、is_media_read_only状態を変更します。

is_media_read_only状態は、2次ファイルを変更しない変更ステートメントとは関係ありません。これは、これらの変更ステートメントが動作する方法です。

これを自分でテストするには、データベースを読み取り専用に設定し、読み取りと書き込みを行い、セカンダリデータファイルの最終更新日を確認します。

ディスクが読み取り専用に設定され、セカンダリデータファイルを変更せずにデータベースの変更コマンドが実行されたときに、更新がトリガーされる理由についての回答が必要な場合、その部分をテストできません。エラーが表示されず、ステートメントの実行時のエラーログ。データベースが削除されたときに、SQLサーバーがis_media_read_only = 1を使用してディスク上にあるセカンダリデータファイルを削除しようとしないことにも関係がある可能性があります。エラーの可能性が少なくなります。

6
Randi Vertongen