10bet网址
MySQL 5.6リファレンスマニュアル
下载本手册
PDF(美国高级主任)- 26.8 mb
PDF (A4)- 26.8 mb


MySQL 5.6リファレンスマニュアル/ストアドプログラムおよびビュ. /ストアドプログラムのバ▪▪▪ナリロギング

20.7ストアドプログラムのバescナリロギング

バナリログには,デタベスの内容を変更するSQLステトメントに関する情報が含まれます。この情報は,変更にいて記述したベントの形式で格納されます。バ▪▪ナリログには2▪▪の重要な目的があります。

  • レプリケーションの場合,バイナリログは,スレーブサーバーに送信されるステートメントのレコードとして,マスターレプリケーションサーバー上で使用されます。マスターサーバーは,そのバイナリログに格納されているイベントをそのスレーブに送信し,スレーブはこれらのイベントを実行して,マスター上で実行されたものと同じデータ変更を実行します。セクション17.2“レプリケションの実装”を参照してください。

  • ある特定のデタリカバリ操作には,バナリログの使用が必要です。バックアップファイルがリストアされたあと,バックアップの作成後に記録されたバイナリログ内のイベントが,再度実行されます。これらの▪▪ベントは,デ▪▪タベ▪スをバックアップのポ▪▪ントから最新の状態に持って行きます。セクション7.3.2“リカバリへのバックアップの使用”を参照してください。

ただし,ロギングがステートメントレベルで行われる場合,ストアドプログラム(ストアドプロシージャーおよびストアドファンクション,トリガー,イベント)に関して該当する,特定のバイナリロギングの問題があります。

  • 場合によっては,ステ,トメントが,マスタ,とスレ,ブで別々の行セットに影響する可能性があります。

  • スレーブ上で実行された複製ステートメントは,完全な権限を持つスレーブSQLスレッドで処理されます。プロシージャーが,マスターサーバーとスレーブサーバーで別々の実行パスに従うことが可能なので,ユーザーは,スレーブ上でのみ実行し,完全な権限を持つスレーブスレッドで処理される危険なステートメントを含んだルーチンを作成できます。

  • デ,タを変更するストアドプログラムが非決定的である場合,再現可能ではありません。これにより,マスターとスレーブでデータが異なる結果になったり,リストアしたデータが元のデータと一致しなくなったりする場合があります。

このセクションでは,MySQL 5.6のストアドプログラムのバイナリロギングの処理について説明します。ここでは,実装がストアドプログラムの使用に対して設定している現在の条件と,問題を避けるために実行可能な対処について記しています。また,これらの条件の理由に関する追加情報も示します。

一般に,ここで述べる問題は,SQLステートメントレベルでバイナリロギングが行われるときに生じます。行ベースのバイナリロギングを使用する場合,ログには,SQLステートメントを実行した結果として個々の行に行われた変更が含まれます。ルーチンまたはトリガーが実行されると,行の変更が記録されますが,変更を行なったステートメントは記録されません。ストアドプロシ,ジャ,の場合,これは调用ステ,トメントが記録されないことを意味します。ストアドファンクションの場合,関数内で行われた行の変更が記録され,関数呼び出しは記録されません。トリガ,の場合,トリガ,によって行われた行の変更が記録されます。スレ,ブ側では,行の変更だけが表示され,ストアドプログラムの呼び出しは表示されません。行ベスのロギングに関する一般情報にいては,セクション17.1.2“レプリケション形式”を参照してください。

特に明記しないかぎり,ここでの説明では,——log-binオプションを指定してサーバーを起動することによって,バイナリロギングを有効にしていると想定しています。(セクション5.2.4 "バナリログ"を参照してください)バイナリログが有効でない場合,レプリケーションは可能でなく,バイナリログをデータリカバリに利用することもできません。

MySQL 5.6でストアドファンクションを使用するための現在の条件は,次のように要約できます。これらの条件は,ストアドプロシージャーまたはイベントスケジューラのイベントには適用されず,バイナリロギングが有効でないかぎり適用されません。

  • ストアドファンクションを生成または変更するには,ユ,ザ,は,通常必要になる创建程序権限または改变日常権限以外に,超级権限が必要です。(関数定義の定义者値によっては,バ超级が必要になる場合があります。セクション13.1.15 "创建过程および创建函数構文"を参照してください。)

  • ストアドファンクションを作成するとき,その関数が決定的であるということ,またはデータを変更しないということを宣言する必要があります。そのようにしないと,デ,タリカバリまたレプリケ,ションにとって安全でなくなる可能性があります。

    デフォルトでは,创建函数ステ,トメントを受け入れるには,确定的没有SQL,または读取SQL数据の少なくとも1を明示的に指定する必要があります。そうでない場合はエラ,が発生します。

    错误1418 (HY000):这个函数在它的声明中没有DETERMINISTIC, NO SQL,或READS SQL DATA,并且启用了二进制日志记录(你*可能*想使用不安全的log_bin_trust_function_creators变量)

    次の関数は決定的なため(また,デ,タを変更しません),安全です。

    创建函数f1(i INT)返回确定的读取SQL数据开始返回i结束;

    次の関数はUUID ()を使用しますが,これは決定的でないため,関数も決定的でなく,安全ではありません

    创建函数f2()返回字符集utf8开始返回UUID();结束;

    次の関数はデ,タを変更するので,安全ではない可能性があります。

    创建函数f3(p_id INT)返回INT BEGIN UPDATE t SET modtime = NOW() WHERE id = p_id;返回ROW_COUNT ();结束;

    関数の性質の評価は,作成者の誠実さに基づいています。MySQLは,确定的と宣言された関数に非決定的な結果を生成するステートメントが含まれていないかどうかをチェックしません。

  • 确定的を指定しないで,決定的であるストアドファンクションを作成することは可能ですが,ステートメントベースのバイナリロギングを使用してこの関数を実行できません。このような関数を実行するには,行ベ,スまたは混合バ,ナリロギングを使用する必要があります。または,関数定義で确定的と明示的に指定すると,ステートメントベースのバイナリロギングを含むあらゆる種類のロギングを使用できます。

  • 関数作成に関する前述の条件(超级権限を持つ必要があることと,関数が決定的であるか,データを変更しないと宣言する必要があること)を緩和するには,log_bin_trust_function_creatorsグロバルシステム変数を1に設定します。デフォルトでこの変数には0の値が設定されていますが,次のように変更できます。

    mysql> SET GLOBAL log_bin_trust_function_creators = 1;

    サ,バ,の起動時に——log-bin-trust-function-creators = 1オプションを使用することによって,この変数を設定することもできます。

    バ电子邮箱ナリロギングが有効でない場合,log_bin_trust_function_creatorsは適用されません。前述のように,関数定義の定义者値が必要としないかぎり,関数の作成に超级は必要ありません。

  • レプリケーションで安全ではない可能性のある(そのため,これらを使用するストアドファンクションも安全でなくなります)組み込み関数の詳細は,セクション17.4.1“レプリケ,ションの機能と問題”を参照してください。

トリガーは,ストアドファンクションと似ているので,関数に関する前述の説明がトリガーにも当てはまりますが,创建触发器にはオプションの确定的特性がないため,トリガ,は常に決定的であると想定されるという点が異なります。ただし,この想定は一部の場合で無効になることがあります。たとえば,UUID ()関数は非決定的です(また,複製しません)。トリガ,でのこのような関数の使用には注意する必要があります。

トリガ,はテ,ブルを更新できるので,必要な権限がない場合には,创建触发器で,ストアドファンクションの場合と同様のエラ,メッセ,ジが表示されます。スレ,ブ側では,スレ,ブは定义者トリガ,属性を使用して,トリガ,の作成者であると思われるユ,ザ,を特定します。

このセクションの残りの部分では,ロギングの実装とその意味に関する追加詳細にいて説明します。ストアドルーチンの使用に関する現在のロギング関連の条件の理論的根拠についての背景に関心がある場合には,こちらをお読みください。この説明はステ,トメントベ,スのロギングにのみ該当し,行ベ,スのロギングには該当しませんが,创建および下降ステートメントは,ロギングモードとは無関係にステートメントとして記録されるという最初の項目は除きます。

  • サ,バ,は,创建事件创建过程创建函数改变事件改变的过程改变函数删除事件下降过程,および删除函数ステトメントをバナリログに書き込みます。

  • ストアドファンクションの呼び出しは,この関数がデータを変更し,それ以外では記録されないようなステートメント内で行われた場合に,选择ステ,トメントとして記録されます。これにより,記録されないステートメントでストアドファンクションを使用した結果生じたデータの変更をレプリケーションできなくなるという事態が防止されます。たとえば,选择ステトメントはバナリログに書き込まれませんが,选择は,変更を行うストアドファンクションを呼び出す場合があります。これを扱うため,选择func_name()ステトメントは,指定した関数が変更を行うときにバナリログに書き込まれます。次のステ,トメントがマスタ,で実行されるとします。

    创建函数f1(a INT)返回INT BEGIN IF (a < 3) THEN INSERT INTO t2 VALUES (a)如果;返回0;结束;创建表t1 (INT);插入t1 VALUES (1),(2),(3);SELECT f1(a) FROM t1;

    选择ステ,トメントが実行されると,関数f1 ()は3回呼び出されます。このう2回の呼び出しで行を挿入し,MySQLは各行に対し选择ステ,トメントを記録します。。

    选择f1 (1);选择f1 (2);

    サーバーは,エラーを発生させるストアドプロシージャーをストアドファンクションが呼び出すときに,そのストアドファンクションの呼び出しに対する选择ステ,トメントも記録します。この場合,サ,バ,は,予想されるエラ,コ,ドとともに,选择ステ,トメントをログに書き込みます。スレ,ブ上で,同じエラ,が起きた場合,これは予想される結果でありレプリケ,ションは継続します。それ以外の場合は,レプリケ,ションは停止します。

  • 関数によって実行されるステートメントではなく,ストアドファンクションの呼び出しのロギングは,レプリケーションでは,次の2つの要因から生じるセキュリティー上の意味があります。

    • 関数が,マスタサバとスレブサバで別々の実行パスに従うことが可能です。

    • スレブ上で実行されたステトメントは,完全な権限を持スレブSQLスレッドで処理されます。

    つまり,ユーザーは関数を作成するために创建程序権限を持つ必要がありますが,完全な権限を持つスレッドで処理されるスレーブ上でのみ実行する危険なステートメントを含んだ関数を作成できます。たとえば,マスターサーバーとスレーブサーバーのサーバー ID 値がそれぞれ 1 と 2 の場合、マスターサーバー上のユーザーは、安全ではない関数unsafe_func ()を次のように作成し呼び出すことができます。

    mysql> delimiter // mysql> CREATE FUNCTION unsafe_func () RETURNS INT -> BEGIN -> IF @@server_id=2 THENdangerous_statement;如果;->返回1;- >结束;-> // mysql>分隔符;INSERT INTO t VALUES(unsafe_func());

    创建函数ステ,トメントおよび插入ステトメントはバナリログに書き込まれるので,スレブサバはそれらを実行します。スレ,ブSQLスレッドには完全な権限があるので,危険なステ,トメントを実行します。したがって,関数の呼び出しがマスターとスレーブに与える効果は異なり,レプリケーションは安全ではなくなります。

    バイナリロギングを有効にしているサーバーに対するこの危険から保護するために,ストアドファンクションの作成者は,必要な通常の创建程序権限に加え,超级権限も持必要があります。同様に,改变函数を使用するには,ユ,ザ,は改变日常権限に加え,超级権限を持必要があります。超级権限がないと,エラ,が発生します。

    错误1419 (HY000):您没有SUPER权限并且启用了二进制日志记录(您*可能*想使用不太安全的log_bin_trust_function_creators变量)

    関数作成者が超级権限を持よう要求しない場合(たとえば,システム上の创建程序権限を持すべてのユザが経験豊かなアプリケション開発者である場合),log_bin_trust_function_creatorsグロバルシステム変数を1に設定します。サ,バ,の起動時に——log-bin-trust-function-creators = 1オプションを使用することによって,この変数を設定することもできます。バ电子邮箱ナリロギングが有効でない場合,log_bin_trust_function_creatorsは適用されません。前述のように,関数定義の定义者値が必要としないかぎり,関数の作成に超级は必要ありません。

  • 更新を実行する関数が非決定的である場合,再現可能ではありません。これは次の2の望ましくない影響を及ぼす可能性があります。

    • スレ,ブがマスタ,と一致しなくなります。

    • リストアされたデ,タが元のデ,タと異なります。

    これらの問題に対処するために,MySQLでは,関数を決定的であるか,データを変更しないと宣言しないかぎり,マスターサーバーでは関数の作成と変更は拒否されるという要件を強制しています。ここでは次の2の関数特性セットが適用されます。

    • 确定的特性と不确定性特性は,関数が一定の入力に対して常に同じ結果を生成するかどうかを示します。どらの特性も指定されていない場合は,デフォルトは不确定性です。関数が決定的であることを宣言するには,明示的に确定的を指定する必要があります。

    • 包含SQL没有SQL读取SQL数据,および修改SQL数据特性は,関数がデ,タを読み取るか書き込むかに関する情報を示します。没有SQLまたは读取SQL数据は,関数がデ,タを変更しないことを示しますが,特性が指定されていない場合にデフォルトは包含SQLになるので,これらのどらかを明示的に指定する必要があります。

    デフォルトでは,创建函数ステ,トメントを受け入れるには,确定的没有SQL,または读取SQL数据の少なくとも1を明示的に指定する必要があります。そうでない場合はエラ,が発生します。

    错误1418 (HY000):这个函数在它的声明中没有DETERMINISTIC, NO SQL,或READS SQL DATA,并且启用了二进制日志记录(你*可能*想使用不安全的log_bin_trust_function_creators变量)

    log_bin_trust_function_creatorsを1に設定した場合,関数が決定的であるか,デ,タを変更しないという要件は破棄されます。

  • ストアドプロシ,ジャ,の呼び出しは调用レベルでなく,ステ,トメントレベルで記録されます。,调用ステ,トメントを記録せず,実際に実行するプロシ,ジャ,内のステ,トメントを記録します。その結果,マスタ,で行われた同じ変更が,スレ,ブサ,バ,で確認されます。これにより,別々のマシン上で異なる実行パスを持プロシジャから生じる問題が防止されます。

    一般に,ストアドプロシージャー内で実行されるステートメントは,スタンドアロンでステートメントを実行した場合に適用されるものと同じルールを使用して,バイナリログに書き込まれます。プロシージャー内でのステートメントの実行は,非プロシージャーのコンテキストとまったく同じにはならないので,プロシージャーステートメントのロギング時には,十分に注意してください。

    • 記録されるステ,トメントには,ロ,カルプロシ,ジャ,変数への参照が含まれる場合があります。これらの変数は,ストアドプロシージャーのコンテキスト外に存在しないので,このような変数を参照するステートメントは,文字どおりには記録できません。代わりに,ロ,カル変数のそれぞれの参照は,ロギングのために次の構造構文に置き換えられます。

      NAME_CONST (var_namevar_value

      var_nameはロ,カル変数名であり,var_valueは,ステ,トメントの記録時に変数に含まれていた値を示す定数です。NAME_CONST ()にはvar_valueの値とvar_name名前が含まれます。したがって,この関数を直接呼び出した場合,次のような結果が得られます。

      mysql> SELECT name ('myname', 14);+--------+ | 的名字  | +--------+ | 14  | +--------+

      NAME_CONST ()は,マスター上でストアドプロシージャー内で実行された元のステートメントと同じ効果で,記録されたスタンドアロンのステートメントを,スレーブ上でも実行できるようにします。

      NAME_CONST ()を使用した結果,ソ,スカラム式がロ,カル変数を参照するときに,创建表…选择ステ,トメントの問題が生じる場合があります。これらの参照をNAME_CONST ()式に変換した結果,マスターサーバーとスレーブサーバーでカラム名が異なったり,正当なカラム識別子としては長すぎる名前になったりすることがあります。回避策では,ロ,カル変数を参照するカラムのエ,リアスを指定します。myvar#の値が1の場合は次のステ,トメントを検討してください。

      CREATE TABLE t1 SELECT myvar

      これは次のように書き換えられます。

      SELECT NAME_CONST(myvar, 1);

      マスターテーブルとスレーブテーブルに同じカラム名があることを確認するには,次のようなステートメントを作成します。

      SELECT myvar作为myvar

      書き換えられたステ,トメントは次のようになります。

      SELECT NAME_CONST(myvar, 1) AS myvar;
    • 記録されるステ,トメントには,ユ,ザ,定義変数への参照が含まれる場合があります。これを処理するために,MySQLは,ステートメントをバイナリログに書き込んで,マスター上にあるものと同じ値の変数がスレーブ上にもあることを確認します。たとえば,ステ,トメントが変数@my_varを参照する場合、そのステ、トメントはバ、ナリログ内で次のステ、トメントに優先されます。ここで,价值マスタ,上の@my_varの値です。

      SET @my_var =价值
    • プロシ,ジャ,の呼び出しは,コミットまたはロ,ルバックしたトランザクション内で行えます。プロシージャー実行のトランザクションの側面が正しく複製されるように,トランザクションのコンテキストが説明されます。,,,,,开始提交,および回滚ステ,トメントも必要に応じて記録します。たとえば,プロシージャーがトランザクションテーブルだけを更新し、ロールバックされるトランザクション内で実行される場合、これらの更新は記録されません。プロシージャーがコミットされたトランザクション内で行われた場合、开始および提交ステ,トメントが更新とともに記録されます。ロールバックしたトランザクション内で実行するプロシージャーの場合,そのステートメントは,ステートメントがスタンドアロンで実行された場合に適用されるものと同じルールを使用して記録されます。

      • トランザクションテ,ブルに対する更新は記録されません。

      • 非トランザクションテ,ブルに対する更新は,ロ,ルバックで取り消されないので,記録されます。

      • トランザクションテーブルと非トランザクションテーブルの混在に対する更新は,スレーブがマスターと同じ変更およびロールバックを行うように,开始回滚で囲まれて記録されます。

  • ストアドプロシージャーの呼び出しは,ストアドファンクション内から呼び出される場合,ステートメントレベルのバイナリログに書き込まれません。この場合,記録される唯一の対象は,関数を呼び出すステートメント(記録されたステートメント内で行われた場合)またはステ,トメント(記録されないステ,トメント内で行われた場合)です。このため,それ以外の場合にプロシージャー自体が安全であっても,プロシージャーを呼び出すストアドファンクションを使用するときには注意を払う必要があります。