一見シンプルなコンセプトに戸惑いました。 Mysqlは決定論的関数を
同じ入力パラメーターに対して常に同じ結果を生成します
だから私の理解では、のような機能
CREATE FUNCTION foo (val INT) READS SQL DATA
BEGIN
DECLARE retval INT;
SET retval = (SELECT COUNT(*) FROM table_1 WHERE field_1 = val);
RETURN retval;
END;
確定的ではありません(関数の2つの呼び出しの間に削除/更新/挿入が発生しないという保証はありません)。同時に、クエリの結果に基づいて戻り値がほぼ同じで、DETERMINISTIC
として宣言されている多くの関数を確認しました。基本的なものが欠けているようです。
誰かがこの問題を明確にできますか?
ありがとう。
更新答えてくれてありがとう(+1);これまでのところ、DETERMINISTIC
キーワードの誤用が広まっているようです。多くの人がそうしていると私が信じるのはまだ難しいので、他の答えを少し待ちます。
MySQL 5.0リファレンスから:
ルーチンの性質の評価は、作成者の「誠実さ」に基づいています。MySQLは、DETERMINISTICと宣言されたルーチンに非決定的な結果を生成するステートメントがないことを確認しません。ただし、ルーチンを誤って宣言すると、結果やパフォーマンスに影響を与える可能性があります。非決定的ルーチンをDETERMINISTICとして宣言すると、オプティマイザが誤った実行プランを選択するため、予期しない結果が生じる可能性があります。確定的ルーチンをNONDETERMINISTICとして宣言すると、使用可能な最適化が使用されなくなり、パフォーマンスが低下する可能性があります。 MySQL 5.0.44より前では、DETERMINISTIC特性は受け入れられていますが、オプティマイザでは使用されていません。
したがって、それができたら、ストアドルーチンにDETERMINISTIC
のタグを付けなくてもタグ付けできますが、予期しない結果やパフォーマンスの問題が発生する可能性があります。
DETERMINISTIC結果は、異なる時間に返される異なる結果セットを参照しません(その間に追加されたデータによって異なります)。さらに、同じデータを使用する異なるマシンの結果セットへの参照です。たとえば、uuid()を含む関数を実行するか、サーバー変数を参照する2台のマシンがある場合、これらは確定的ではないと見なされます。関数呼び出しはバイナリログ(マスター)に保存され、スレーブによっても実行されるため、これはレプリケーションなどで役立ちます。詳細と例については、 http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html を参照してください
したがって、DETERMINISTICの使用は正しい(99%の場合)であり、誤用とは見なされません。
あなたのルーティンは決定論的だと思います。ドキュメントはあまり明確ではないため、多くの人がこの問題について非常に混乱しています。この問題は、実際には何よりもレプリケーションに関するものです。
2つのデータベース間でレプリケーションを設定している状況を考えてみましょう。マスターデータベースは、入力パラメーターを含め、実行されたすべてのストアドルーチンのログを保持し、このログをスレーブに送信します。スレーブは、同じ入力パラメーターで同じ順序で同じストアドルーチンを実行します。スレーブデータベースにマスターデータベースと同一のデータが含まれるようになりますか?ストアドルーチンがGUIDを作成してデータベースに保存する場合は、いいえ、マスターデータベースとスレーブデータベースが異なり、レプリケーションが壊れます。
DETERMINISTICフラグの主な目的は、このストアドルーチンへの呼び出しをレプリケーションログに含めると、マスターデータベースとレプリケートされたスレーブの間に違いが生じるため、安全ではないかどうかをMySQLに伝えることです。
DETERMINISTICフラグがストアドルーチンに適切かどうかを判断するときは、次のように考えてください。2つの同一のデータベースで開始し、両方のデータベースで同じ入力パラメーターを使用してルーチンを実行した場合、データベースは同じですか?もしそうなら、私のルーチンは決定論的です。
ルーチンが確定的でない場合に確定的であると宣言した場合、MySQLはプロシージャログをレプリケーションログに追加するだけであり、スレーブでプロシージャを実行しても同じ結果が生成されないため、メインデータベースのレプリカは元のデータベースと同一ではない可能性があります。 。
ルーチンが非決定的である場合、MySQLは影響を受ける行をレプリケーションログに含める必要があります。ルーチンが非決定論的であると宣言した場合、これは何も壊しませんが、レプリケーションログには、プロシージャコールだけで十分な場合に影響を受けるすべての行が含まれ、パフォーマンスに影響を与える可能性があります。
何も不足していません。この関数は非決定的です。確定的であると宣言してもデータベースは溶けませんが、パフォーマンスに影響する可能性があります。 MySQLサイトから :「非決定的ルーチンをDETERMINISTICとして宣言すると、オプティマイザが誤った実行プランを選択するため、予期しない結果が生じる可能性があります。」しかし、MySQLは宣言された決定論的ルーチンが実際に決定論的であるかどうかを強制または確認しません--- MySQLは、あなたが何をしているのかを知っていると信頼しています。
レプリケーションをオンにしている場合、または1日使用する可能性がある場合は、確定性が重要です。たとえば、行の変更(更新または挿入)を引き起こす非決定的関数呼び出しは、バイナリ(行ベース)を使用して複製する必要があります。ここで、決定的関数はステートメントベースで複製できます。これは、上記のSQLの例を見ると興味深いものです。ステートメントベースを使用してレプリケートすると同じ結果が得られ(同じ結果が得られます)、マスターで取得した結果を使用してレプリケートする必要があります(行ベース)。ステートメントが適切なロックで実行され、スレーブで同じ順序で実行されることが保証される場合、それらは実際に確定的です。スレーブが使用するロック/ステートメントの順序(同時実行なし、ステートメントの開始順にシリアル処理)が答えを変える可能性がある場合、関数は非決定的である必要があります。