原則として、すべてのストアドプロシージャが実際に決定的である場合、それらをDETERMINISTICキーワードで宣言する必要がありますか?
ストアドプロシージャの大部分は確定的であるように思えます。非決定的なプロシージャはRand()やCURDATE()などの非決定的な関数を呼び出すものだけだと私は思いますか?
とにかく、私が尋ねている理由は、MySQL Workbench内でデータ復元機能を使用すると、次のエラーが発生するためです。
ERROR 1418 (HY000) at line 1209: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
代わりに単に「log_bin_trust_function_creators = 1」を設定する方が良いでしょうか? 50以上のストアドプロシージャがあることに注意してください。
次の理由により、実際に決定論的であるプロシージャに対してdeterministic
キーワードを使用することには意味があります。
確定的ルーチンをNONDETERMINISTICとして宣言すると、使用可能な最適化が使用されなくなるため、パフォーマンスが低下する可能性があります。
だが:
非決定的な手続きはRand()やCURDATE()のような非決定的な関数を呼び出すものだけだと私は思いますか?
いいえ、データベースからデータを読み取り、その結果に基づいて(その入力に加えて)データを基にするプロシージャも非決定的です(呼び出し間でデータが変わる可能性があるため)。
プロシージャが決定的であるかどうかは、レプリケーションのコンテキストで考慮する必要があることを指摘する価値があります。
ただし:
行ベースまたは混合バイナリー・ロギングが使用されている場合、関数がDETERMINISTICキーワードなしで定義されていても、ステートメントは受け入れられ、複製されます。
log_bin_trust_function_creators
これは、ストアドプロシージャを移行する際の穴のエースです。 DETERMINISTICプロパティが次の2つに追加されました。
バイナリロギングが有効になっていて、ストアドプロシージャが存在するため、エラーメッセージは単に醜い頭を抱えています。バイナリロギングを無効にするか、ストアドプロシージャを確定的としてマークします。
スクリプトを編集せずに、すべてのストアドプロシージャに対して簡単にできることを以下に示します。mysql.procを更新して、これを実行します。
UPDATE mysql.proc SET is_deterministic = 'YES';
MySQL 5.5.12 for Windowsで試してみました
mysql> select db,name from mysql.proc;
+--------+-----------------------+
| db | name |
+--------+-----------------------+
| lovesh | LoadMyData |
| stuff | DoesUserHaveEditPrivs |
| stuff | LoadSampleData |
| stuff | MakeTables |
| stuff | ShowLast40 |
| test | CreateSampleTable |
| test | CreateSampleTables |
| test | GetMissingIntegers |
| test | GetTestTableCounts |
| test | ImportWeeklyBatch |
| test | InsertName |
| test | LoadSampleTables |
| test | MigrateColumn |
+--------+-----------------------+
13 rows in set (0.00 sec)
mysql> select db,name,is_deterministic from mysql.proc ;
+--------+-----------------------+------------------+
| db | name | is_deterministic |
+--------+-----------------------+------------------+
| test | InsertName | NO |
| test | MigrateColumn | NO |
| test | GetMissingIntegers | NO |
| test | CreateSampleTable | NO |
| test | CreateSampleTables | NO |
| test | LoadSampleTables | NO |
| test | ImportWeeklyBatch | NO |
| test | GetTestTableCounts | NO |
| stuff | MakeTables | NO |
| stuff | ShowLast40 | NO |
| stuff | LoadSampleData | NO |
| stuff | DoesUserHaveEditPrivs | NO |
| lovesh | LoadMyData | NO |
+--------+-----------------------+------------------+
13 rows in set (0.00 sec)
mysql> update mysql.proc set is_deterministic='YES' where db='lovesh';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select db,name,is_deterministic from mysql.proc ;
+--------+-----------------------+------------------+
| db | name | is_deterministic |
+--------+-----------------------+------------------+
| test | InsertName | NO |
| test | MigrateColumn | NO |
| test | GetMissingIntegers | NO |
| test | CreateSampleTable | NO |
| test | CreateSampleTables | NO |
| test | LoadSampleTables | NO |
| test | ImportWeeklyBatch | NO |
| test | GetTestTableCounts | NO |
| stuff | MakeTables | NO |
| stuff | ShowLast40 | NO |
| stuff | LoadSampleData | NO |
| stuff | DoesUserHaveEditPrivs | NO |
| lovesh | LoadMyData | YES |
+--------+-----------------------+------------------+
13 rows in set (0.00 sec)
mysql> desc information_schema.routines;
+--------------------------+---------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+---------------+------+-----+---------------------+-------+
| SPECIFIC_NAME | varchar(64) | NO | | | |
| ROUTINE_CATALOG | varchar(512) | NO | | | |
| ROUTINE_SCHEMA | varchar(64) | NO | | | |
| ROUTINE_NAME | varchar(64) | NO | | | |
| ROUTINE_TYPE | varchar(9) | NO | | | |
| DATA_TYPE | varchar(64) | NO | | | |
| CHARACTER_MAXIMUM_LENGTH | int(21) | YES | | NULL | |
| CHARACTER_OCTET_LENGTH | int(21) | YES | | NULL | |
| NUMERIC_PRECISION | int(21) | YES | | NULL | |
| NUMERIC_SCALE | int(21) | YES | | NULL | |
| CHARACTER_SET_NAME | varchar(64) | YES | | NULL | |
| COLLATION_NAME | varchar(64) | YES | | NULL | |
| DTD_IDENTIFIER | longtext | YES | | NULL | |
| ROUTINE_BODY | varchar(8) | NO | | | |
| ROUTINE_DEFINITION | longtext | YES | | NULL | |
| EXTERNAL_NAME | varchar(64) | YES | | NULL | |
| EXTERNAL_LANGUAGE | varchar(64) | YES | | NULL | |
| PARAMETER_STYLE | varchar(8) | NO | | | |
| IS_DETERMINISTIC | varchar(3) | NO | | | |
| SQL_DATA_ACCESS | varchar(64) | NO | | | |
| SQL_PATH | varchar(64) | YES | | NULL | |
| SECURITY_TYPE | varchar(7) | NO | | | |
| CREATED | datetime | NO | | 0000-00-00 00:00:00 | |
| LAST_ALTERED | datetime | NO | | 0000-00-00 00:00:00 | |
| SQL_MODE | varchar(8192) | NO | | | |
| ROUTINE_COMMENT | longtext | NO | | NULL | |
| DEFINER | varchar(77) | NO | | | |
| CHARACTER_SET_CLIENT | varchar(32) | NO | | | |
| COLLATION_CONNECTION | varchar(32) | NO | | | |
| DATABASE_COLLATION | varchar(32) | NO | | | |
+--------------------------+---------------+------+-----+---------------------+-------+
30 rows in set (0.02 sec)
mysql> select * from information_schema.routines where routine_schema='lovesh'\G
*************************** 1. row ***************************
SPECIFIC_NAME: LoadMyData
ROUTINE_CATALOG: def
ROUTINE_SCHEMA: lovesh
ROUTINE_NAME: LoadMyData
ROUTINE_TYPE: PROCEDURE
DATA_TYPE:
CHARACTER_MAXIMUM_LENGTH: NULL
CHARACTER_OCTET_LENGTH: NULL
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
CHARACTER_SET_NAME: NULL
COLLATION_NAME: NULL
DTD_IDENTIFIER: NULL
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: BEGIN
DECLARE NDX INT;
SET NDX = 0;
WHILE NDX < 100 DO
INSERT INTO mydata (ti_time) VALUES (NOW() - INTERVAL CEILING(14400*Rand()) SECOND
);
SET NDX = NDX + 1;
END WHILE;
END
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE: SQL
IS_DETERMINISTIC: YES
SQL_DATA_ACCESS: CONTAINS SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2011-07-25 11:12:02
LAST_ALTERED: 2011-07-18 22:39:34
SQL_MODE:
ROUTINE_COMMENT:
DEFINER: [email protected]
CHARACTER_SET_CLIENT: cp850
COLLATION_CONNECTION: cp850_general_ci
DATABASE_COLLATION: latin1_swedish_ci
1 row in set (0.03 sec)
mysql>
すべてのストアドプロシージャに対してこれを行うと、MySQL Workbenchは文句を言わなくなります。