web-dev-qa-db-ja.com

master、tempdb、model、およびmsdbがそれぞれ1、2、3、4以外のdatabase_idを持つことは可能ですか?

SQL Server システムデータベース は、私の知る限り、常に同じIDを持ち、インターネットで述語WHERE database_id > 4を使用してそれらのアクションから除外する多くのメンテナンススクリプトを見てきました。スクリプト。

また、新しいユーザーデータベースでSELECT name, schema_id FROM sys.schemas;を実行すると、次のようになります。

name                 schema_id
dbo                  1
guest                2
INFORMATION_SCHEMA   3
sys                  4
db_owner             16384
db_accessadmin       16385
db_securityadmin     16386
db_ddladmin          16387
db_backupoperator    16389
db_datareader        16390
db_datawriter        16391
db_denydatareader    16392
db_denydatawriter    16393

SQL Server 2016とSQL Server 2005の2つの異なるインスタンスでそのクエリを実行しましたが、どちらも同じ結果を返しました。

質問:

  1. システムデータベースマスター、tempdb、モデル、およびmsdbがそれぞれ1,2,3,4以外のdatabase_idを持つ状況(またはSQLサーバーのバージョン)はありますか?
  2. リストしたスキーマがSQL Serverのインスタンスで常に同じIDを持つという事実を信頼して本当にできるので、メンテナンススクリプトに基づいて記述できますそれらのIDで?
8
Ronaldo

理論的には

以下のアクションは、テストのみを目的としています。 データベースインスタンスが使用できなくなったり、応答しなくなったり、データが失われたりすることに問題がない場合は、これを試みないでください

masterデータベースを切り離して、データベースのdatabase_idを再利用することはできません。

modelをデタッチすると、インスタンスがクラッシュし、再度アタッチできなくなります。これにより、 すべてのシステムデータベースを再構築 する必要があります。このプロセスにより、ログイン、ジョブなどのすべての情報が削除されます。そして、ユーザーデータベースが切り離されます。

Tempdbを切り離して、別の名前で再度アタッチしてdatabase_idを再利用しようとすると、database_id 2が再利用されず、tempdbが機能しなくなりました。

_name    database_id
master  1
model   3
msdb    4
test3_2__   5
test3_2_    6
tempdb  7
_

名前をtempdbに戻すことはできましたが、インスタンスがめちゃくちゃになっていて、正常に起動できませんでした。

データベースID 2が見つかりませんでした。データベースがまだアクティブ化されていないか、移行中の可能性があります。データベースが使用可能になったら、クエリを再発行してください。

---> すべてのシステムデータベースを再構築する

しかし、理論的にはmsdbシステムデータベースIDを変更するための2つ(またはそれ以上)のオプションがあります。

msdbデータベースIDを変更するには、msdbをデタッチして新しいユーザーデータベースを作成し、最後に新しいmsdbデータベースを作成します ドキュメント化された手順 to 新しいmsdbデータベースを作成する

msdbデータベースIDを変更するには、msdbを切り離し、別の名前で再接続し、名前をmsdbに戻します。 サポートされていません。これを行わないでください

最初にSQLサーバーを「マスターのみのリカバリモード」で起動します

_NET START MSSQL$InstanceName /f /T3608"
_

Msdbをデタッチして新しいデータベースを作成する

_EXEC sp_detach_db msdb;
GO
CREATE DATABASE test3;
GO
_

Msdbファイルの名前を変更し、インスタンスを通常どおり再起動します

Msdbを初期化します。

_SQLCMD -E -S<servername> -i"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Install\instmsdb.sql" -o"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Install\instmsdb.out"£
_

データベースIDを表示します。

_SELECT name,database_id 
FROM sys.Databases;

name    database_id
master  1
tempdb  2
model   3
test3   4
...
msdb    12
_

サポートされていないメソッド

2つの通常のアタッチプロシージャ_sp_attach_db_および_create database ... for attach_は、msdbをアタッチしようとすると機能しません。

エラーメッセージ:

FILESTREAMデータベースオプションは、 'msdbなどのシステムデータベースでは設定できません

テスト目的でのみ実行できることは、ユーザーデータベース_msdb2_を作成することです。

_CREATE DATABASE msdb2  
    ON (FILENAME = N'X:\MSSQL\DATA\MSDBData.mdf'),   
    (FILENAME = N'X:\MSSQL\DATA\MSDBLog.ldf')   
    FOR ATTACH;  
_

データベースの名前をmsdbに変更します

_ALTER DATABASE msdb2 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE msdb2 MODIFY NAME = msdb ;
GO  
ALTER DATABASE msdb SET MULTI_USER
_

インスタンスを通常どおり再起動します

_NET STOP MSSQL$InstanceName
NET START MSSQL$InstanceName
_

_database_id's_を表示します。

_SELECT name, database_id 
FROM sys.databases;
_

結果

_name    database_id
master  1
tempdb  2
model   3
test    4
...
msdb    10
_

実際には

幸いにも、これはどこにも見られませんが、database_id 4は理論的にはユーザーデータベースで再利用できます。これが起こった場合、私のクエリでシステムデータベースを除外することは、おそらく私の問題の最も少ないでしょう。

そうは言っても、WHERE DB_NAME(database_id) NOT IN ('master','tempdb','model','msdb','distribution','ssisdb')を使用するのが確実な選択です。

15
Randi Vertongen

実際には、これらのIDは、SQL Serverのすべての現在リリースされているバージョンで同じになります。

distributionSSISDBデータベースもシステムデータベースですが、予測可能なdatabase_idがないことに注意してください。

ただし、これが常に当てはまる、または将来も当てはまるという保証はありません。マイクロソフトはドキュメントを提供せず、これらのIDが常に同じであることを保証しません。誰かがデータベースにアクセスし、これらのシステムスキーマをいじったことが保証されます。

SQL Serverの次のバージョンでは、製品チームはID番号スキームに変更を加えることを決定できます。その変更は、Service Packまたは累積的な更新プログラムの既存のバージョンにバックポートされる可能性があります。

これは近い将来ありそうもないになる可能性があるため、心配する必要はありません。しかし、素晴らしいコードを書いたとしても、そのコードが今から10、2年後に使用されている可能性があります。そして、あなたの後継者は絡み合うためにネズミの巣を持ち、あなたのコードは「素晴らしいコード」でなくなります。

将来の変更はさておき、暗号化されたハードコードされたID値に依存するコードは読み取れません。誰もが知っているわけではないschema_id > 16384は、特別なスキーマの範囲を示します。 (私は世紀の変わり目からSQL Serverを使用しており、そのコード行に混乱するでしょう。)

あなたのコードを散文のように読んでください、そうすればあなたはより良く、より保守しやすいコードを手にするでしょう。

9
AMtwo

これらのデータベースはインストール時に作成され、ユーザーが書いたとおり、1、2、3、4と指定されています。システムをいじくり回すと、いつでもシステムを壊すことができます。Microsoftは、IDと目的の両方でこれらのデータベースを変更できます。 MSは、「model2」と呼ばれるさまざまな目的で2番目のモデルデータベースを作成したり、2番目のtempdbデータベースを追加して、さまざまな種類の一時テーブルを分割したり、何らかの理由でそれを行うことができます。

私のアドバイスは、a)SQL Serverのcurrentバージョンでは、これらのデータベースIDが(インストール時に)一貫していることを確認してください。私は他にもそれらを見たことがない。特に懸念がある場合、またはそのしつこい気持ちを揺さぶることができない場合は、プログラム/スクリプトの最初にこれらの事実、特にID#= db name stringを確認してください。

私はそれを書くときにコードで行う私の仮定を追跡するのが好きです。社内コードの場合、これらのデータベース名とIDの想定はかなり安全です。外部のクライアントについては、すべてを確認することを好みます。これは、a)このDB名/ IDの仮定であるかどうかにかかわらず、頭からそれを取り除くのに役立ちます。b)これらの仮定の1つが壊れた場合、非常に速く見つけることができます。頭を悩ませる手間を大幅に省くだけでなく、何を頼りにできるかを知って安心します。

これらの質問を見つけたら、確認して次に進んでください(あなたがしたように、質問を投稿しても害はありません)。このようにして、あなたの時間は実際の問題によりよく費やされ、あなたはこれらのしつこい質問の頭をクリアすることができます。そして、それは物事が失敗したときにあなたに自信を与えます、それはこれらの確認された質問の1つではありません。

この特定のケースでは、これらのデータベースIDを確認する必要性を感じたことはありません。私は直接ではなく、機能を介して常にアクセスしてきました。ただし、これらのデータベースを操作するスクリプトを作成している場合、環境が想定したものとは異なる場合、影響が深刻になる可能性があることを知っているので、想定を確実に検証します。

3
FreeText