SQL Server ではコンピューター名変更時、手動で変更作業が必要
あまりないケースかもしれませんが、SQL Serverがインストールされたコンピューターのコンピューター名を変更する場合、みなさんなにか意識されていますでしょうか?
コンピューター名を変更したらいきなりDBにアクセスできなくなる、といったことはなく普通に使えるので、特に意識してない方も多いのではないかと思います。
リモート接続なども変更後のコンピューター名でバッチリできますしね。
しかし実は、SQL Serverのメタデータ内にはコンピューター名の情報を持っていて、OSでコンピュータ名を変更した際に自動では変更されません。手動での変更作業が必要になります。
変更をしていないと、一部処理が正常に動作しなくなってしまい思わぬエラーが出ることも。
エラーが発生するケース
コンピュータ名の変更作業が漏れていることによって、エラーが発生するケースをご紹介。
例えば、以下のようなクエリの発行がエラーとなります。
SELECT * FROM [AFTERNAME\TEST].[testDB].[dbo].[table_a]
前提は以下
- SQL Server インストール時のコンピューター名が「PREVNAME」
- OSでコンピューター名を「AFTERNAME」に変更
- インスタンス「TEST」のデータベース「testDB」内「table_a」テーブルのレコードを全行取得
例のクエリでポイントとなるのが、SQL Serverの「リンクサーバー」という機能を意識してテーブル名の前に「サーバー名\インスタンス」を付加しているところです。
◯実行例
◯エラー内容
sys.servers でサーバー ‘AFTERNAME\TEST’ が見つかりませんでした。正しいサーバー名を指定したかどうかを確認してください。必要であればストアド プロシージャ sp_addlinkedserver を実行し、サーバーを sys.servers に追加してください。
理由
SQL Serverには「リンクサーバー」という機能があります。
ざっくりいうと、あるSQL Serverにアクセスしている際にリンクサーバーとして設定している他のDBサーバー(インスタンス)のデータに対してもアクセスが可能になる機能です。
※にわかなので、ご容赦を…。詳しくは以下をご参照ください。
リンク サーバー (データベース エンジン) – SQL Server
何がよいのかといいますと、例えば異なるDBサーバー(インスタンス)のテーブル同士を結合したクエリが発行できたりします。
※Aサーバーに接続時に、AサーバーのBテーブルとリンクサーバーに設定したCサーバーのDテーブルを結合してSELECT、みたいな。
そんなリンクサーバー機能ですが、クエリを発行する際に対象テーブルがどのサーバー(インスタンス)のテーブルかを識別するために、テーブル名の前に「サーバー名\インスタンス名」を付加するわけです。
↓異なるサーバー同士のテーブル結合のクエリは、こんな感じになります。
SELECT * FROM [AServer\INSTANCE].[DatabaseA].[dbo].[TableA] A LEFT OUTER JOIN [BServer\INSTANCE].[DatabaseB].[dbo].[TableB] B ON B.KeyColumn = A.BKey
「サーバー名\インスタンス」の部分ですが、どうやらSQL Serverに保持しているメタデータと照合しているようです。
メタデータは、以下のクエリで確認することができます
SELECT * FROM sys.servers
上記には、リンクサーバーを作成すると設定内容に応じた情報がレコードとして追加されます。
また、任意に作成したリンクサーバーとは別に既定で
ローカルサーバー(自分自身)の情報が存在します(server_id=0 のレコード)。
※画像の例は、リンクサーバーを作成していないのでローカルサーバーのレコードのみです。
この情報にはコンピューター名の情報が含まれています。
(「name」列/「data_source」列)
そしてこちらの情報は、コンピュータ名変更時に自動では更新されません。
そのため、クエリを変更後のコンピュータ名で記述しているのに対して、このメタデータが古いと、サーバーが見つからないとのエラーになってしまうというわけですね。
反対に、クエリの記述が実際のOSのコンピューター名と一致していなくても、このメタデータの情報に合致していればクエリは成功しました。(意図的に両者が異なる場合って、あるのかな・・・?)
もちろん、クエリでテーブル名に [サーバー名\インスタンス名] を付加するのは、リンクサーバーへアクセスするときに必要なもので、自サーバー(インスタンス)へアクセスする際は必要ありません。
そのため、このような問題はあまり想定されないレアケースではあるのですが…
SQL Serverと連携するシステム開発で、遭遇することがあるカモ。
変更方法
以下のプロシージャを実行することで、SQLServer内コンピューター名の情報を変更することができます。
反映には、実行後インスタンスの再起動が必要になります。
※サービスを再起動すればOK
既定のインスタンスの場合
EXEC sp_dropserver '<old_name>'; GO EXEC sp_addserver '<new_name>', local; GO
名前付きインスタンスの場合
EXEC sp_dropserver '<old_name\instancename>'; GO EXEC sp_addserver '<new_name\instancename>', local; GO
その場合はsp_dropremoteloginプロシージャでリモート接続を削除します。
※もちろん、使用者に確認したあとで…
実行例
実行前
○メタデータ
○クエリ
現在のコンピュータ名「AFETRNAME」でクエリを発行しても、メタデータに存在しないのでエラーとなります。
実行後
○メタデータ
コンピュータ名に関する列の値が書き換わっていますね。
※「name」列/「data_source」列
○クエリ
エラーなく実行結果が返るようになりました(サービス再起動後)。
参考
SQL Server のスタンドアロン インスタンスをホストするコンピューターの名前を変更する – SQL Server
sys.servers (Transact-SQL) – SQL Server
リンク サーバー (データベース エンジン) – SQL Server
おわりに
環境依存で起こる問題って、やーね。
(我ながらPrevに対してAfterて…なんだ;)