Pages

Friday, November 29, 2013

SQL Azure の ID がジャンプする件ほか

最近、ひとに名刺を渡しつつ、申し訳程度に書いているこの Blog の URL なのだが、少しはまともなメモをたまには書かなければと思う今日この頃。そんなわけで、思いつき程度にさきほど気になったことをメモ。というか、むしろ淡々と技術的な備忘録にしちゃえばいいんじゃないかと思ったり。


Windows Azure の SQL サーバー サービスを使っていると、なぜかテーブルの ID たる int の自動生成カラムのシードがジャンプすることがある。

こんな感じ。どうやら、これは仕様らしくて、詳細はここでみつけた: Azure data transfer Identity Column Seed Jumped by 10,000

超要約すると、SQL の運用チームが「このほうが効率いいんじゃね?」って思って導入したということらしいのだが、それも今となっては「やっぱビミョー」だそうで、いつの日にか「やっぱやーめた」となる可能性があるということらしい。はい。


もう一件。Entity Framework を使っている人は、なんだかデータベースに接続するときに接続文字列が昔に比べてややこしいことにお気づきかと。具体的には、たとえば App.config にこんな感じの文字列がはいってらっしゃる:

metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="hoge fuga piyo"
これの意味を再考せねばならない事態がおこるのが、次のようなとき:
これは、テスト用につくったソリューションだが、あるライブラリにデータベース接続用の EF モデルを作った。それを画面中のソースコードで使おうとしているが、次のような例外が発生している。

An unhandled exception of type 'System.Data.Entity.Core.MetadataException' occurred in EntityFramework.dll

Additional information: Unable to load the specified metadata resource.

どう見てもお怒りである。これは、*.edmx ファイルに書いてある EF モデルがうまく読み込めていない、とのことである。先ほどの接続文字列に戻ってみると、最初に metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl という記述がある。これがミソで、この例外が示すところは、このメタデータが読めてない、ということである。さて、このメタデータなのだが、実は *.edmx ファイルの構成を見てみれば、何をさしているのかわかる。たいてい、以下のような構成になっているはずだ。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient">
        データベースの物理的構成がここに。
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="Model" Alias="Self">
        データベースの論理的構成がここに。
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S">
        物理構成と論理構成の間のマッピングがここに。
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <edmx:Designer>
    細かいオプションとか、デザイナでの表示とかがここに。
  </edmx:Designer>
</edmx:Edmx>

細かいことはさておき、*.edmx ファイルのこの 3 つのコンポーネントが、コンパイル時にアセンブリ内にデフォルトでリソースとして埋め込まれる。それらがそれぞれ、Model.csdl, Model.ssdl, Model.msl という名前であり、さきほどの接続文字列はそれをさしていたのである。なお、細かいことが気になる人はこの記事が大変良く参考になる。

ではなぜ今回うごかなかったのかというと、Library のアセンブリを見てみるとき、良く見るとモデルが DB というフォルダ内に入っている。この場合、必ずしもアセンブリに埋め込まれるリソース名が上記のようにはならないのだ。

このとおり。そんなわけで、そういう場合には接続文字列を直してやる必要がある。ちなみに、res://*/ の * は、現在のアプリケーション ドメイン内で読み込まれているアセンブリすべてから当該名称を持つリソースを探すよ、という意味である。アセンブリ名が分かっているなら、当然指定したほうが早いらしい。参考まで。

Sunday, June 16, 2013

巨大なファイルをコピーするときの話

仕事でメンテナンスしているサーバが落ちたとの連絡があった。聞くところによると、本来うごいているべきサーバと通信が出来ないとのことらしい。このメモは、完全復旧 (+ 再構築) に 3 日かかったそのトラブルの顛末 (特に、大きなファイルをコピーして死にかけるという問題とその対策) をまとめておいた。

くだんのサーバは仮想構成になっていて、ホストもゲストも共に Windows Server 2008 という構成。ゲストには OS が入った VHD ファイル (50GB) と、データが入った VHD (3GB) がマウントされていて、それらはホストに接続されたソフトウェア ミラー構成の 2 枚の物理 HDD においてある。

6/13 朝9時すぎ。緊急の連絡があって業務データにアクセスできないということらしい。リモートでのアクセスには成功したので、物理サーバは起動している。だが、Hyper-V でゲスト OS の起動をかけようとすると、「ファイルシステム制限のため要求された操作を完了できませんでした」というエラーが出る。Google 先生で調べてみたところ、VHD の最適化を試みるとその問題が起こるケースが多いようで、ゲスト側の VSS (ボリューム シャドー コピー サービス) が有効になっているせい、という見解が多い。だが、(VHD 最適化でなく) VM 開始時にこれで落ちるという情報は見当たらない。イベント ログを見てみたら、前回の電源遮断は Windows Update があった 6/13 の午前 3 時過ぎ。なんてことはない、通常の再起動のはずである。異常な電源遮断ではなく、物理 HDD のミラーリングに不整合は生じていないので、再同期も必要なかった。

朝 10 時。とりあえずファイル システムの損傷を疑って、ディスクの完全なエラー チェックを実施。数年来そのまま使っていて過去にはハードウェア的な問題による異常な電源遮断も何度かあったので、問題があれば修復するようにした。これがまためちゃくちゃ時間がかかる。

午後 4 時。スキャン ディスクの結果は問題なし。ファイルシステムにも損傷はない。すると問題は何だ? VHD ファイルは正常なのに、Hyper-V から起動できないし、VHD の最適化にも失敗する。仕方がないので、Explorer 上で VHD ファイルを複製して、VM からは複製後のファイルをマウントさせることに。ファイル システムの制限、というからには自然な判断である。ここからが問題である

午後 8 時。リモート デスクトップでセッションに再接続したのだが、様子がおかしい。

  1. VHD ファイルのコピーは残り 10GB の表示のまま、まったく変化する様子がない。残り時間は減らないし、プログレス バーも当然すすまない。
  2. それから、Ctrl + Shift + Esc でタスク マネージャが上がらない。
  3. さらに、ゲスト OS は走ってないのに、メモリ使用量は 8G 積んだ物理メモリの 98% まで (!) 逼迫している模様。
  4. しまいには、管理コンソールでディスク情報を見ようとしても「取得中」のまま一時停止。
  5. 挙句 diskpart コマンドも起動してバージョン情報をはいたらそのまま応答がなくなる。

仕方ないので、この時点で現場急行を判断。過剰なページングによるスタベーションか、ディスク アクセスの異常を疑った。

午後 10 時。予想以上にひどかった。直接の対話型コンソール ログインができないのである。いわゆる「ようこそ」の画面のままクルクルしてて、ぜんぜんデスクトップが表示されない。さらにリモート管理で接続できないことも判明。打つ手なしになり、やむなく強制的な電源遮断を決断。当然ながら再起動するとミラーの整合性が失われるので、再同期が開始された。こうすると、HDD アクセスは全部もっていかれてしまうので、夜間に再同期を待つことに。この時点で現場での作業は終了、結局なにもできなかったに等しい。なお後日談だが、これはやってはいけなかった。この時点で安全のためにディスクの物理障害と論理障害を疑っていれば、ミラーになったディスクを分離し、代わりに予備のディスクを接続するなどの措置が必要だった。

翌朝 9時。ミラーの状態は正常。昨晩の症状は原因不明だし、他に無策だったので、今度は現場で確認しながら、ファイル コピーを試みることに。なお、上記の理由から予備ディスクにコピーすることにした。とりあえず業務に必要なデータだけは可及的速やかに抽出しなければならなかったので、データ (SQL Server の mdf ファイルなど) が入った小さい方の VHD ファイルだけ先に複製。ちなみにこれで、先の「ファイルシステム制限」のエラーは回避でき、別の VM へはマウントできるようになった。やはり、物理ディスクのファイル システムの問題なのだろうか。ともかく復旧にかかる懸念は、ファイル コピーできるかのほうに移ってきた。

ところで、ここである重要なことに気付いた。対話ログインで、リソース モニタで現状を追いかけていると、コピー中になぜかメモリ使用量が上がっていくのである。どうも調べたら、この問題らしい。そして同じように困っている人がいた。そんなわけで、上の KB 中に公開されている Dynamic Cache サービスをダウンロードして展開。

午前 11 時。業務データを救出して、予備サーバで続行するための作業と並行しつつ、ゲスト OS が入った巨大なほうの VHD ファイルを複製することに。さきのサービスも適切に展開したから、今度こそコピーに成功するはず・・・。なのだがやはり様子がおかしい。最初はメモリ使用量が増加せずに好調なのだが、やはり途中から増加して食い尽くしていくのである。そして、resmon で監視しながらわかったこととして、複製元の HDD の読み出し速度が書き込み側を上回る状態が続くと、メモリ使用量が増えるらしい。当然と言えば当然の結果なのだが、Dynamic Cache サービスを有効にしてても起こるらしい。最終的にどうしたかというと、読み出し側が速い状況が続いて、メモリが限界まで増えてきたときに、ソースとなるディスク側に高負荷の IO を行わせる (= 具体的には、小さいファイルがたくさんあるディレクトリを無意味に複製させるなど) ことで、書き込み側が追いつくのを待つ。50GB のファイルをコピーする中、2 時間ずっとリソース使用状況を監視していた。(メモリが逼迫したら、無駄な IO でキャッシュをフォールトさせる方向に調整。平衡を保つようににらめっことは、なんかの化学実験をやってるかのようであった。おちおちトイレにもいけない)

午後 2 時。VHD ファイルの無事を確認し、それぞれ複製後のファイルをマウントしたら VM も正しく起動するようになったことを確認。これで復旧としても良かったのだが、次、いつ同じようなトラブルがあるかわからないので、ディスクを新しくしてホスト OS も新たにインストールしたサーバを用意することにした。ハードウェアの寿命だったのかもしれない。

そんなわけで、新しいサーバを用意して、そちらにデータを元通りにして、ドメインに参加させてネットワークの設定を行ったり、業務端末からの通信テストをしたりしていたら、僕の 3 日間は消えたのでした。ちゃんちゃん。