sql >> データベース >  >> NoSQL >> MongoDB

最初のアドバイザーを書く

    何がClusterControlでディスクがいっぱいになっているというアドバイスをトリガーするのか疑問に思ったことはありませんか?または、InnoDBテーブルに主キーが存在しない場合は、それらに主キーを作成するためのアドバイスはありますか?これらのアドバイザは、Javascriptのような言語であるClusterControlドメイン固有言語(DSL)で記述されたミニスクリプトです。これらのスクリプトは、ClusterControlで作成、コンパイル、保存、実行、およびスケジュールできます。これが、ClusterControlDeveloperStudioブログシリーズの内容です。

    今日は、Developer Studioの基本について説明し、最初のアドバイザーを作成する方法を示します。ここでは、2つのステータス変数を選択し、その結果についてアドバイスします。

    アドバイザー

    アドバイザは、オンデマンドまたはスケジュールの後にClusterControlによって実行されるミニスクリプトです。それらは、単純な構成のアドバイス、しきい値に関する警告、予測のためのより複雑なルール、またはサーバーやデータベースの状態に基づくクラスター全体の自動化タスクなど、何でもかまいません。一般に、アドバイザーはより詳細な分析を実行し、アラートよりも包括的な推奨事項を作成します。

    アドバイザはClusterControlデータベース内に保存されており、新しいアドバイザを追加したり、既存のアドバイザを変更/変更したりできます。また、アドバイザーを私たちや他のClusterControlユーザーと共有できるアドバイザーGithubリポジトリもあります。

    アドバイザに使用される言語は、いわゆるClusterControl DSLであり、理解しやすい言語です。言語のセマンティクスは、いくつかの違いがあるJavascriptと最もよく比較できます。ここで、最も重要な違いは次のとおりです。

    • セミコロンは必須です
    • 整数や符号なしlonglong整数などのさまざまな数値データ型。
    • 配列は2次元であり、1次元配列はリストです。

    違いの完全なリストは、ClusterControlDSLリファレンスにあります。

    DeveloperStudioインターフェース

    Developer Studioインターフェースは、「クラスター」>「管理」>「DeveloperStudio」の下にあります。これにより、次のようなインターフェースが開きます:

    アドバイザー

    アドバイザボタンは、最後に実行してからの出力とともに、すべてのアドバイザの概要を生成します。

    アドバイザのスケジュールはcrontab形式で表示され、最後の更新以降の日付/時刻も表示されます。一部のアドバイザーは1日に1回だけ実行されるようにスケジュールされているため、たとえば、警告された問題をすでに解決している場合、アドバイスは現実を反映しなくなる可能性があります。アドバイザを選択して実行することにより、アドバイザを手動で再実行できます。これを行う方法を読むには、「コンパイルして実行する」セクションに移動してください。

    アドバイザーのインポート

    [インポート]ボタンを使用すると、新しいアドバイザーが含まれているtarballをインポートできます。 tarballは、アドバイザのメインパスを基準にして作成する必要があるため、MySQLクエリキャッシュサイズスクリプトの新しいバージョン(s9s / mysql / query_cache / qc_size.js)をアップロードする場合は、tarballを開始する必要があります。 s9sディレクトリから。

    アドバイザーのエクスポート

    ツリーでノードを選択して[エクスポート]ボタンを押すと、アドバイザーまたはその一部をエクスポートできます。これにより、提示された構造のフルパスにあるファイルでtarballが作成されます。変更を加える前にs9s/mysqlアドバイザのバックアップを作成したい場合は、ツリーでs9s / mysqlノードを選択し、[エクスポート]を押し​​ます。

    注:s9sディレクトリが/ home /myuser/に存在することを確認してください。

    これにより、内部ディレクトリ構造がs9s / mysql / *

    の/home/myuser/s9s/mysql.tar.gzというtarballが作成されます。

    新しいアドバイザーの作成

    輸出入について説明したので、実験を開始できます。それでは、新しいアドバイザーを作成しましょう。 [新規]ボタンをクリックして、次のダイアログを表示します。

    このダイアログでは、空のファイルを使用して新しいアドバイザを作成するか、GaleraまたはMySQL固有のテンプレートを事前に入力することができます。どちらのテンプレートも、必要なインクルード(common / mysql_helper.js)と、GaleraまたはMySQLノードを取得してそれらをループするための基本を追加します。

    Galeraテンプレートを使用して新しいアドバイザーを作成すると、次のようになります。

    #include "common/mysql_helper.js"

    ここでは、mysql_helper.jsが含まれており、MySQLノードに接続してクエリを実行するための基礎を提供していることがわかります。

    このファイルには、必要に応じて呼び出すことができる関数が含まれています。たとえば、readVariable()を使用すると、グローバル変数の値を取得したり、readStatusVariable()を呼び出したりできます。 MySQLでグローバルステータス変数を取得します。このファイルは、以下に示すようにツリーに配置できます。

    var WARNING_THRESHOLD=0;
    …
    if(threshold > WARNING_THRESHOLD)

    警告しきい値は現在0に設定されています。つまり、測定されたしきい値が警告しきい値より大きい場合、アドバイザーはユーザーに警告する必要があります。可変しきい値は、独自のアドバイザーのキックスタートであるため、テンプレートではまだ設定/使用されていないことに注意してください。

    var hosts     = cluster::Hosts();
    var hosts     = cluster::mySqlNodes();
    var hosts     = cluster::galeraNodes();

    上記のステートメントはクラスター内のホストをフェッチし、これを使用してそれらをループできます。それらの違いは、最初のステートメントにはすべての非MySQLホスト(CMONホストも)が含まれ、2番目のステートメントにはすべてのMySQLホストが含まれ、最後のステートメントにはのみ ガレラのホスト。したがって、GaleraクラスターにMySQL非同期読み取りスレーブが接続されている場合、それらのホストは含まれません。

    それ以外は、これらのオブジェクトはすべて同じように動作し、変数の読み取り、ステータス、およびそれらに対するクエリ機能を備えています。

    アドバイザボタン

    新しいアドバイザを作成したので、このアドバイザに使用できる6つの新しいボタンがあります。

    保存 最新の変更をアドバイザ(CMONデータベースに保存)に保存します。移動 アドバイザを新しいパスに移動し、削除 明らかにアドバイザーを削除します。

    さらに興味深いのは、ボタンの2行目です。アドバイザをコンパイルすると、アドバイザのコードがコンパイルされます。コードが正常にコンパイルされると、このメッセージがメッセージに表示されます。 アドバイザーのコードの下の対話:

    コンパイルが失敗した場合、コンパイラは失敗した場所のヒントを提供します:

    この場合、コンパイラは24行目に構文エラーが見つかったことを示しています。

    コンパイルして実行 ボタンを押すと、スクリプトがコンパイルされるだけでなく、実行され、その出力が[メッセージ]、[グラフ]、または[未加工]ダイアログに表示されます。 auto_tunersからテーブルキャッシュスクリプトをコンパイルして実行すると、次のような出力が得られます。

    最後のボタンはスケジュールです ボタン。これにより、アドバイザーをスケジュール(またはスケジュール解除)してタグを追加できます。これについては、この投稿の最後で、独自のアドバイザーを作成し、スケジュールを設定したいときに説明します。

    私の最初のアドバイザー

    ClusterControl Developer Studioの基本について説明したので、ようやく新しいアドバイザーの作成を開始できます。例として、一時テーブルの比率を確認するためのアドバイザーを作成します。次のように新しいアドバイザーを作成します。

    作成するアドバイザの背後にある理論は単純です。ディスク上に作成された一時テーブルの数を、作成された一時テーブルの総数と比較します。

    tmp_disk_table_ratio = Created_tmp_disk_tables / (Created_tmp_tables + Created_tmp_disk_tables) * 100;

    まず、しきい値や警告メッセージ、OKメッセージなど、スクリプトの先頭にいくつかの基本を設定する必要があります。すべての変更と追加は以下に適用されます:

    var WARNING_THRESHOLD=20;
    var TITLE="Temporary tables on disk ratio";
    var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
    var ADVICE_OK="Temporary tables on disk are not excessive." ;

    ここでしきい値を20%に設定しましたが、これはすでにかなり悪いと考えられています。しかし、アドバイザーを完成させたら、そのトピックについてさらに詳しく説明します。

    次に、MySQLからこれらのステータス変数を取得する必要があります。結論にジャンプして「SHOWGLOBALSTATUSLIKE'Created_tmp_%'」クエリを実行する前に、この関数がcommon / mysql_helperにある上記のように、MySQLインスタンスのステータス変数を取得する関数がすでにあります。 js:

    statusVar = readStatusVariable(<host>, <statusvariablename>);

    アドバイザでこの関数を使用して、Created_tmp_disk_tablesとCreated_tmp_tablesをフェッチできます。

        for (idx = 0; idx < hosts.size(); ++idx)
        {
            host        = hosts[idx];
            map         = host.toMap();
            connected     = map["connected"];
            var advice = new CmonAdvice();
            var tmp_tables = readStatusVariable(host, ‘Created_tmp_tables’);
            var tmp_disk_tables = readStatusVariable(host, ‘Created_tmp_disk_tables’);

    これで、一時ディスクテーブルの比率を計算できます:

            var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;

    そして、この比率が最初に設定したしきい値よりも大きい場合は警告します:

            if(checkPrecond(host))
            {
               if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
                   advice.setJustification("Temporary tables written to disk is excessive");
                   msg = ADVICE_WARNING;
               }
               else {
                   advice.setJustification("Temporary tables written to disk not excessive");
                   msg = ADVICE_OK;
               }
            }

    ここでアドバイスをmsg変数に割り当てることが重要です。これは、後でsetAdvice()関数を使用してアドバイスオブジェクトに追加されるためです。完全を期すための完全なスクリプト:

    #include "common/mysql_helper.js"
    
    /**
     * Checks the percentage of max ever used connections 
     * 
     */ 
    var WARNING_THRESHOLD=20;
    var TITLE="Temporary tables on disk ratio";
    var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
    var ADVICE_OK="Temporary tables on disk are not excessive.";
    
    function main()
    {
        var hosts     = cluster::mySqlNodes();
        var advisorMap = {};
    
        for (idx = 0; idx < hosts.size(); ++idx)
        {
            host        = hosts[idx];
            map         = host.toMap();
            connected     = map["connected"];
            var advice = new CmonAdvice();
            var tmp_tables = readStatusVariable(host, 'Created_tmp_tables');
            var tmp_disk_tables = readStatusVariable(host, 'Created_tmp_disk_tables');
            var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
            
            if(!connected)
                continue;
            if(checkPrecond(host))
            {
               if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
                   advice.setJustification("Temporary tables written to disk is excessive");
                   msg = ADVICE_WARNING;
                   advice.setSeverity(0);
               }
               else {
                   advice.setJustification("Temporary tables written to disk not excessive");
                   msg = ADVICE_OK;
               }
            }
            else
            {
                msg = "Not enough data to calculate";
                advice.setJustification("there is not enough load on the server or the uptime is too little.");
                advice.setSeverity(0);
            }
            advice.setHost(host);
            advice.setTitle(TITLE);
            advice.setAdvice(msg);
            advisorMap[idx]= advice;
        }
        return advisorMap;
    }

    これで、しきい値20を試してみることができます。たとえば、しきい値を1または2に下げてみてください。そうすれば、このアドバイザーが実際にこの問題についてどのようにアドバイスするかがわかるでしょう。

    ご覧のとおり、簡単なスクリプトを使用して、2つの変数を相互にチェックし、その結果に基づいてレポート/アドバイスを行うことができます。しかし、それだけですか?まだ改善できることがいくつかあります!

    最初のアドバイザーの改善

    最初に改善できることは、このアドバイザーはあまり意味がないということです。メトリックが実際に反映するのは、最後のFLUSHSTATUSまたはMySQLの起動以降のディスク上の一時テーブルの総数です。それが言っていないのは、レートです 実際にディスク上に一時テーブルを作成します。したがって、Created_tmp_disk_tablesを、ホストの稼働時間を使用してレートに変換できます。

        var tmp_disk_table_rate = tmp_disk_tables / uptime;

    これにより、1秒あたりの一時テーブルの数がわかり、tmp_disk_table_ratioと組み合わせると、状況をより正確に把握できるようになります。繰り返しになりますが、1秒あたり2つの一時テーブルのしきい値に達した後は、アラート/アドバイスをすぐに送信したくありません。

    改善できるもう1つの点は、common / mysql_helper.jsライブラリのreadStatusVariable()関数を使用しないことです。この関数は、ステータス変数を読み取るたびにMySQLホストへのクエリを実行しますが、CMONはすでにほとんどの変数を毎秒取得しているため、リアルタイムのステータスは必要ありません。 2つまたは3つのクエリがクラスター内のホストを強制終了するわけではありませんが、これらのアドバイザーの多くが同様の方法で実行されると、余分なクエリのヒープが作成される可能性があります。

    この場合、host.sqlInfo()関数を使用してマップ内のステータス変数を取得し、すべてを一度にマップとして取得することで、これを最適化できます。この関数には、ホストの最も重要な情報が含まれていますが、すべてが含まれているわけではありません。たとえば、レートに必要な可変稼働時間はhost.sqlInfo()マップでは利用できず、readStatusVariable()関数で取得する必要があります。

    これは、変更/追加が太字でマークされた、現在のアドバイザーの外観です:

    #include "common/mysql_helper.js"
    
    /**
     * Checks the percentage of max ever used connections 
     * 
     */ 
    var RATIO_WARNING_THRESHOLD=20;
    var RATE_WARNING_THRESHOLD=2;
    var TITLE="Temporary tables on disk ratio";
    var ADVICE_WARNING="More than 20% of temporary tables are written to disk and current rate is more than 2 temporary tables per second. It is advised to review your queries, for example, via the Query Monitor.";
    var ADVICE_OK="Temporary tables on disk are not excessive.";
    
    function main()
    {
        var hosts     = cluster::mySqlNodes();
        var advisorMap = {};
    
        for (idx = 0; idx < hosts.size(); ++idx)
        {
            host        = hosts[idx];
            map         = host.toMap();
            connected     = map["connected"];
            var advice = new CmonAdvice();
            var hostStatus = host.sqlInfo();
            var tmp_tables = hostStatus['CREATED_TMP_TABLES'];
            var tmp_disk_tables = hostStatus['CREATED_TMP_DISK_TABLES'];
            var uptime = readStatusVariable(host, 'uptime');
            var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
            var tmp_disk_table_rate = tmp_disk_tables / uptime;
            
            if(!connected)
                continue;
            if(checkPrecond(host))
            {
               if(tmp_disk_table_rate > RATE_WARNING_THRESHOLD && tmp_disk_table_ratio > RATIO_WARNING_THRESHOLD) {
                   advice.setJustification("Temporary tables written to disk is excessive: " + tmp_disk_table_rate + " tables per second and overall ratio of " + tmp_disk_table_ratio);
                   msg = ADVICE_WARNING;
                   advice.setSeverity(0);
               }
               else {
                   advice.setJustification("Temporary tables written to disk not excessive");
                   msg = ADVICE_OK;
               }
            }
            else
            {
                msg = "Not enough data to calculate";
                advice.setJustification("there is not enough load on the server or the uptime is too little.");
                advice.setSeverity(0);
            }
            advice.setHost(host);
            advice.setTitle(TITLE);
            advice.setAdvice(msg);
            advisorMap[idx]= advice;
        }
        return advisorMap;
    }

    最初のアドバイザーのスケジュール

    この新しいアドバイザを保存し、コンパイルして実行したら、このアドバイザをスケジュールできます。過度の作業負荷がないため、このアドバイザーはおそらく1日に1回実行します。

    基本スケジューリングモードは、毎分、5分、時間、日、月が事前設定されているCronに似ています。これはまさに必要なものであり、スケジューリングの管理が非常に簡単です。これを詳細に変更すると、他のグレー表示された入力フィールドのロックが解除されます。これらの入力フィールドはcrontabとまったく同じように機能するため、特定の日、曜日をスケジュールしたり、平日に設定したりすることもできます。

    このブログに続いて、SELinuxのチェッカー、またはノードが影響を受ける場合はSpectreとMeltdownのセキュリティチェックを作成します。しばらくお待ちください!


    1. MongoDBでコレクションのサイズを確認する5つの方法

    2. MongoDB $ dayOfYear

    3. StackExchangeRedisChannelPrefixがキーをスコープしない

    4. MongoDBのインデックスのリストを取得する