SQL Azure Team Blog

Consuming SQL Azure Data with the OData SDK for PHP – SQL Azure Team Blogを簡単に翻訳したエントリーです。

Brain SwanはOData SDK for PHPを使用してSQL Azure OData ServiceからSQL Azureのデータを取得する方法についてブログに投稿している。
Consuming SQL Azure Data with the OData SDK for PHPを読んでみると良い。

========

以下、そのブログを抜粋して簡単に翻訳しています。
元記事では、SQL Azureサーバーの準備と、ローカルのNorth WindowデータベースをSQL Azure Migration Wizardを使用してSQL Azureにデータベースを移行する手順が説明されています。以下の抜粋は、SQL Azure上にデータベースの用意をしたところからの説明になります。

SQL Azure OData Serviceを作成する

 

  1. Welcome to SQL Azure Labsにアクセスし、SQL Azure ODataServiceを選択する。
  2. サーバー名、ユーザー名、パスワードを入力し、Connectボタンをクリックする。
  3. 接続後、ドロップダウンリストからOdata Serviceに使用したいデータベースを選択します。Enable ODataチェックボックスにチェックを入れます。
  4. Anonymous Access Userドロップダウンリストからdboを選択することで、匿名アクセスが可能になります。

OData Serviceのエンドポイントを用意できました。URLをブラウザーにコピー&ペーストすることで、いじることができます。

 

PHPでOData Serviceにアクセスする

 

OData Serviceのセットアップが完了したら、Retrieving Data with the OData SDK for PHP – Brian Swanの投稿で説明した方法でPHPからOData Serviceにアクセスできる。

SQL Azure Team Blog

I Miss You SQL Server Agent: Part 2 – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

今のところ、SQL AzureはSQL Server Agentの概念を持っていません。このシリーズでは、Windows Azureワーカーロールを使用して、簡単に代用できるものを作成したいと思います。このシリーズの最初の投稿で、Visual Studioとコードで、Windows AzureワーカーロールでSQL Server Agentと同等のものを作成する方法を紹介しました。
このエントリーでは、一日に一回ジョブを実行するメカニズムを作成します。

 

データベースの作成

Windows Azureは、ワーカーロールは、そのうちデータセンターで異なるサーバに移動する可能性のあるステートレスなプラットフォームです。このため、ジョブが完了するまでジョブの状態を記録し続ける必要があります。その為に迷うことなくSQL Azureを選択します。SQL Azureサーバ下に、SQLServerAgentと呼ばれるデータベースを作成します(データベース名msdbは予め予約されています)。このデータベースに、オンプレミスのSQL Server Agentテーブルsysjobactivityの簡単バージョンであるjobactivityと呼ばれるテーブルを作成します。
私が使用したスクリプトは以下のものです。

CREATE TABLE [dbo].[jobactivity](
    [job_id] uniqueidentifier NOT NULL PRIMARY KEY,
    [job_name] nvarchar(100) NOT NULL,
    [start_execution_date] datetime NOT NULL,
    [stop_execution_date] datetime NULL,
) 

job_idはオブジェクトの日次インスタンスを表し、job_nameはジョブ実行の為の任意のキーです。異なる名前を使用することで多くのジョブを走らせる為に、このテーブルを使用します。

 

ジョブの開始と停止の追跡

 

ジョブ開始時にテーブルにデータを追加する為のストアドプロシージャと、ジョブ停止時に実行ストップを更新する為のストアドプロシージャの2つが必要です。Startjobストアドプロシージャは、ワーカーロールがジョブを開始する為のシグナルを行に登録する前に、ジョブが始まらないことを保証します。

CREATE PROCEDURE StartJob (
    @job_name varchar(100),
    @job_id uniqueidentifier OUTPUT)
AS

BEGIN TRANSACTION

SELECT    @job_id
FROM    [jobactivity]
WHERE    DATEDIFF(d, [start_execution_date], GetDate()) = 0 
    AND [job_name] = @job_name

IF (@@ROWCOUNT=0)
BEGIN
    -- Has Not Been Started
    SET @job_id = NewId()
    INSERT INTO [jobactivity] 
        ([job_id],[job_name],[start_execution_date])
        VALUES (@job_id, @job_name, GetDate())
END
ELSE
BEGIN 
    SET @job_id = NULL
END

COMMIT TRAN

もう一つのストアドプロシージャStopJobは、次のようになります。

CREATE PROCEDURE [dbo].[StopJob](
    @job_id uniqueidentifier)
    
AS

UPDATE [jobactivity]
SET [stop_execution_date] = GetDate()
WHERE job_id = @job_id

ストアドプロシージャを呼び出すワーカーロールを書きます。

protected Guid? StartJob(String jobName)
{
    using (SqlConnection sqlConnection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["SQLServerAgent"].
            ConnectionString))
    {
        try
        {
            // Open the connection
            sqlConnection.Open();

            SqlCommand sqlCommand = new SqlCommand(
                "StartJob", sqlConnection);

            sqlCommand.CommandType =
                System.Data.CommandType.StoredProcedure;

            sqlCommand.Parameters.AddWithValue("@job_name", jobName);

            // WWB: Sql Job Id Output Parameter
            SqlParameter jobIdSqlParameter = new 
                SqlParameter("@job_id", SqlDbType.UniqueIdentifier);
            jobIdSqlParameter.Direction = ParameterDirection.Output;
            sqlCommand.Parameters.Add(jobIdSqlParameter);

            sqlCommand.ExecuteNonQuery();

            if (jobIdSqlParameter.Value == DBNull.Value)
                return (null);
            else
                return ((Guid)jobIdSqlParameter.Value);
        }
        catch (SqlException)
        {
            // WWB: SQL Exceptions Means It Is Not Started
            return (null);
        }
    }
}

protected void StopJob(Guid jobId)
{
    using (SqlConnection sqlConnection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["SQLServerAgent"].
            ConnectionString))
    {
        // Open the connection
        sqlConnection.Open();

        SqlCommand sqlCommand = new SqlCommand(
            "StopJob", sqlConnection);

        sqlCommand.CommandType =
            System.Data.CommandType.StoredProcedure;

        sqlCommand.Parameters.AddWithValue("@job_id", jobId);

        sqlCommand.ExecuteNonQuery();
    }
}

1日1回、午後1時にspTestJobストアドプロシージャを実行するために、ワーカーロールのRunメソッドを実行します。

public override void Run()
{
    Trace.WriteLine("WorkerRole1 entry point called", "Information");

    while (true)
    {
        DateTime nextExecutionTime = new DateTime(
            DateTime. UtcNow.Year, 
            DateTime. UtcNow.Month, DateTime. UtcNow.Day,
            13, 0, 0);
        if (DateTime. UtcNow > nextExecutionTime)
        {
            // WWB: After 1:00 pm, Try to Get a Job Id.
            Guid? jobId = StartJob("TestJob");
            if (jobId.HasValue)
            {
                Trace.WriteLine("Working", "Information");

                // WWB: This Method Has the Code That Execute
                // A Stored Procedure, The Actual Job
                ExecuteTestJob();

                StopJob(jobId.Value);
            }

            // WWB: Sleep For An Hour
            // This Reduces The Calls To StartJob
            Thread.Sleep(3600000);
        }
        else
        {
            // WWB: Check Every Minute
            Thread.Sleep(60000);
        }
    }
}

上のコードにエラーハンドリングのコードがないことに気づいたでしょうか。エラーが発生したらどうなるでしょうか。SQL Azureがエラーを返したらどうなるでしょうか。データセンターで異なるサーバでワーカーロールがリサイクルしたらどうなるでしょうか。それらの問題への対処については、このシリーズの3回目でコードを追加して対処したいと思います。

SQL Azure Team Blog

I Miss You SQL Server Agent: Part 1 – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

今のところ、SQL Azureはクラウド上でのSQL Server Agentの動作をサポートしていません。SQL Azureで、SQL Server Agentの機能が必要な場合は、Windows Azureワーカーロールとカスタムコードで代用できます。このシリーズで、代用する方法を紹介します。

 

SQL Server Agent

SQL Server Agentは、ジョブと呼ばれる管理タスクをスケジュール実行するためのMicrosoft Windows サービスです。SQL Server Agentは、SQL Serverに格納されたジョブ情報を使用します。ジョブは、一つ以上のジョブステップを含んでいます。各ステップは、データベースバックアップのようにSQL Server自信のタスクも含んでいます。SQL Server Agentは、ジョブをスケジュール実行、特定のイベント結果を受けての実行、呼び出されての実行に対応しています。例えば、平日業務後、全ての会社のサーバをバックアップしたい場合、SQL Server Agentを使用すれば自動実行させることができます。月曜から金曜までの22時以降起動するバックアップをスケジュールします。もしバックアップ実行に問題が発生した場合、SQL Server Agentはイベントを記録し、あなたに通知します。SQL Server AgentはオンプレミスのEnterprise、Datacenter、StandardエディションのSQL Serverにインストールされますが、ExpressとCompactエディションには提供されていません。

 

ワーカーロール

ワーカーロールはクラウド上の基本的なWindowsサービスです。ワーカーロールを開始させたとき、エンドレスループをするようにデザインされています。

  • シングルプロセスイベントを確認する
  • 動作を実行する
  • 次に確認する必要ができるまでスリープする様々な目的で使用できるように、ワーカーロールは意図的に抽象的になっています。

注意事項:ワーカーロールは意図的に抽象化されており、SQL Server Agentは開発されており、一年程度で製品提供されると思うので、ワーカーロールで完璧にSQL Server Agentの機能を複製するつもりはありません。代わりに、Windows AzureワーカーロールからSQL Server Agentが行うような多くのタスクを実現できるように、いくつかのアイディアとシンプルなコードを提供しようと思っています。

 

初めに

初めに、Visual Studioでワーカーロールを含むクラウドプロジェクトを作成します。これに関して、基本的な事を知りたい場合は、ここを参照してください。

vs01

WorkerRole.vbと呼ばれるファイルにいくつかのサンプルコードが生成されます。

public override Sub Run()
    ' これは WorkerRole1 の実装例です。実際のロジックに置き換えてください。
    Trace.WriteLine("WorkerRole1 entry point called", "Information");

    While (True)
        Thread.Sleep(10000);
        Trace.WriteLine("Working", "Information");
    End While
End Sub

最初にすることは、SQL Azureデータベース上でストアドプロシージャを実行させるコードを書くことです。これは、SQL Server Agentジョブ内のステップでTransact-SQLを実行させるのと同等です。

vs02

次のようなコードになります。

    Protected Sub ExecuteTestJob()

        Using sqlConnection As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("AdventureWorksLTAZ2008R2").ConnectionString)

            Try

                '接続を開く

                sqlConnection.Open()



                Dim sqlCommand As SqlCommand = New SqlCommand("spTest", sqlConnection)

                sqlCommand.CommandType = System.Data.CommandType.StoredProcedure



                sqlCommand.ExecuteNonQuery()



            Catch ex As SqlException

                Trace.WriteLine("SqlException", "Error")

                Throw

            End Try

        End Using

    End Sub

基本的にはSQL Azure上で、SqlCommand.ExecuteNonQuery()メソッドを使用して、データを返さないストアドプロシージャを実行します。SQL Server Agentのように何も結果を返しません。

 

例外のハンドリング

 

上の例では、Windows AzureワーカーロールでSQL Server Agent版を作成するための最初のステップなので、例外のハンドリングがとても貧相になっています。

SQL Server Agentのロジックから、成功したら次のステップへ進み、失敗したらジョブを終了し、失敗を報告するものを使用する場合、ワーカーロールでtry/catchを使用してSQL Server Agentの動作をシミュレーションします。このシリーズの3回目でエラーハンドリングの問題について取り組みます。

 

まとめ


このシリーズの2回目では、一日の間で、特定の時間にストアドプロシージャを実行させる方法について紹介します。

SQL Azure Team Blog

Programmatically Changing the Firewall Settings – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

SQL Azureは2種類のアクセス制御をしています。

  • ユーザIDとパスワードによる認証
  • IPアドレスによるアクセス制御を行うサーバ側のFirewallによるフィルタリング

SQL Azure ServerにはIPアドレスによる通信制御を行うFirewallがあります。アクセスしようとしているクライアントのIPがFirewallのアクセス許可ルールに登録されていない場合は、クライアントはSQL Azureにアクセスすることはできません。
アクセスを許可するIPを登録するには、SQL Azureポータルを使用することが一般的です。SQL Azureを使用するには、SQL AzureポータルでFirewallルールを作成する必要があります。Firewallルールを作成するまでは、クライアントはSQL Azureにアクセスすることができません。
下のスクリーンショットは、SQL AzureのFirewallルールを追加した例です。

 

Transact-SQLでFirewallルールを変更する方法

 

SQL Azureに接続して、MasterデータベースでTransact-SQLを実行することでFirewallルールを変更することができます。
システムストアドプロシージャ「sp_set_firewall_rule」を実行することでFirewallルールを追加することができます。次の例は、FirewallルールにアクセスすることができるIPアドレスを1つ追加するTransact-SQLです。

exec sp_set_firewall_rule N'Wayne Berry','206.63.251.3','206.63.251.3'

次の例は、Microsoft servicesとWindows Azureからのアクセスを許可するFirewallルールを追加するTransact-SQLです。

exec sp_set_firewall_rule N'MicrosoftServices','0.0.0.0','0.0.0.0'

Firewallルールの名前は、一意である必要があります。

Firewallルール一覧を確認するには、sys.firewall_rulesビューを参照します。

次の例は、ルール一覧を取得するTransact-SQLです。

select * from sys.firewall_rules

次のスクリーンショットは、SQL Server Management StudioでSQL Azureに接続して、コマンドを実行した結果です。

また、「sp_delete_firewall_rule」システムストアドプロシージャを使用することで、Firewallルールを削除することができます。

exec sp_delete_firewall_rule N'Wayne Berry'

 

セキュリティの考察

 

Masterデータベースに接続している間、サーバプリンシパルレベルのログインのみSQL AzureサーバのFirewallの設定をすることができます。SQL Azureポータルに管理者でログインしたときと同じ話です。

SQL Azureに接続して、sp_set_firewall_ruleなどのプロシージャを実行する前に、予め最低一つはFirewallルールを追加しておかなければなりません。

 

コマンドラインからFirewallルールを設定する方法

 

Windowsコマンドラインからsqlcmd.exeを使用してSQL Azureに対してTransact-SQLを実行することができます。

コマンドラインを使用して、Firewallルールを設定するスクリプトを実行することができます。

 

Windows AzureからFirewallルールを設定する方法

 

ADO.NETを使用して、Windows AzureからSQL Azureに対してTransact-SQLを実行することができます。つまり、Windows AzureからSQL AzureのFirewallルールを設定することができます。

Windows Azureは、Windows Azureを呼び出したクライアントのIPがわかることです。

Windows Azure webロール上のwebページを呼び出したIPを動的に、SQL AzureのFirewallルールに追加することができます。

PowerPivotまたはWinFormsのようにユーザが直接SQL Azureに接続する場合に、とても有効です。

次の例は、動的にSQL AzureのFirewallルールに動的にIPアドレスを追加している簡単な例です。

String clientIPAddress = Request.UserHostAddress;

using (SqlConnection sqlConnection = 
    new SqlConnection(ConfigurationManager.ConnectionStrings["SqlAzureMaster"].ConnectionString))
{
    sqlConnection.Open();

    using (SqlCommand sqlCommand =
        new SqlCommand("sp_set_firewall_rule", sqlConnection))
    {
        sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;

        sqlCommand.Parameters.Add("@name", SqlDbType.NVarChar).Value 
            = clientIPAddress;
        sqlCommand.Parameters.Add("@start_ip_address", SqlDbType.VarChar).Value 
            = clientIPAddress;
        sqlCommand.Parameters.Add("@end_ip_address", SqlDbType.VarChar).Value 
            = clientIPAddress;


        sqlCommand.ExecuteNonQuery();
    }
}

SQL Azure Team Blog

Understanding the Procedure Cache on SQL Azure – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

SQL ServerとSQL Azureはクエリのパフォーマンス改善に利用する為のプロシージャキャッシュを持っています。このエントリでは、SQL Azure上のプロシージャキャッシュの動きについて説明します。

SQL Azureには、実行計画とバッファデータの保存に使用するためのメモリプールがあります。このメモリプールは、データベースの所有者に関係無く、物理マシン上の全てのデータベースで使用されます。プールは、マシン上の全てのデータベースにまたがる為、自分のDBの実行計画が一つも保存されていない場合があります。実行計画やバッファデータがプール上で使用できる割合は、システムの状態に応じて動的に変わります。メモリプールの中で、実行計画の保存に使用されている部分は、プロシージャキャッシュと呼ばれます。

SQL AzureでSQL文を実行したとき、リレーショナルエンジンは最初に、同じSQL文に実行計画が存在するかどうかを確認します。SQL Azureは実行計画がある場合は再利用し、SQL文を再コンパイルするオーバーヘッドを減らします。もし実行計画が存在しない場合は、SQL azureはクエリの実行計画を生成します。

SQL Azureとプロシージャキャッシュのレプリカ

 

SQL Azure上で動作するデータベースのインスタンスはレプリカと呼ばれます。同時に、起動している1つのデータベースには、3つのレプリカが存在します。一つ目のレプリカは、プライマリレプリカと見なされます。全ての読み書きをするクエリはプライマリレプリカに発行されます。他の二つのレプリカはセカンダリと見なされます。プライマリレプリカに書き込まれたデータは、セカンダリレプリカに書き込まれます。もしプライマリレプリカが落ちた場合、ロードバランサーが起動し、セカンダリレプリカをプライマリレプリカへ昇格させます、
それぞれのレプリカは、別々のラックに分かれた異なる物理マシン上に配置されます。プロシージャキャッシュは、各サーバごとにあるので、プライマリレプリカが落ちてセカンダリレプリカがプライマリレプリカに昇格したときには、プロシージャキャッシュには、そのデータベース用の実行計画はありません。

 

プロシージャキャッシュの統計情報

 

SQL Azureはキャッシュ上に全ての実行計画のパフォーマンス統計情報を保持しています。動的管理ビュー(DMV)であるsys.dm_exec_query_statsを使用して自分のデータベースに発行された統計情報を見ることができます。

SELECT *
FROM sys.dm_exec_query_stats

sys.dm_exec_query_statsを使用してI/Oパフォーマンスが悪いクエリを見つける方法について、別のエントリで説明しています。

sys.dm_exec_query_statsは、SQL Azureデータベースのプライマリレプリカの統計情報のみを表示します。もしセカンダリレプリカがプライマリレプリカに昇格したら、sys.dm_exec_query_statsの結果は、すごく変わります。キャッシュ上にクエリは無く、実行回数は少なくなります。

 

プロシージャキャッシュから実行計画を削除する

 

実行計画は、メモリに保存できる限りは、プロシージャキャッシュに記録されます。Memory Pressureが発生した場合、SQL Azureは、プロシージャキャッシュから削除する実行計画を決定するためにコストベースを使用します。

SQL Azureは計画の所有者に関係無くキャッシュから実行計画を削除します。サーバ上に存在する全てのデータベースの、全ての実行計画が横断的に、削除のために評価されます。プロシージャキャッシュ上の実行計画は、個々のデータベースでは無く、物理マシーンの利益の為に最適化されます。

SQL Azureは現在のところDBCC FREEPROCCACHE (Transact-SQL)をサポートしていません。その為、手動でキャッシュから実行計画を削除することはできません。しかし、クエリ(ALTER TABLE や ALTER VIEW) でテーブルやビューの参照関係を変更すると、キャッシュから実行計画は削除されます。

まとめ

 

SQL AzureはSQL Serverの上に構築されているので、多くの点で、プロシージャキャッシュはSQL Serverと同じように動作します。しかし、幾つかの違いがあり、それらを理解しておいて方が良いと思います