トリガのダンプ結果を流すとレプリケーションが停止する件

 MySQL5.0の新しい機能のひとつであるトリガー。便利な機能であることは疑う余地はないのですが、その他の新機能と同様、どうもイマヒトツ感を感じます。
 今回見つけたのは、mysqldumpでダンプしたトリガ生成文を実行するとレプリケーションが停止してしまう、というもの。レプリケーション環境で運用している場合はかなり致命的です。 
 原因は、bin-logに書かれる内容にあります。
 以下詳細ご覧ください。


(1)テーブルとトリガの作成
 以下のようにテーブル test_table1 と トリガ tri_test を作成します。

CREATE DATABASE test2;
use test2;

CREATE TABLE test_table1 (no int, str varchar(16));

DELIMITER //
CREATE TRIGGER tri_test BEFORE INSERT ON test_table1 FOR EACH ROW begin
  declare v_no integer;
    select no into v_no from test_table1 for update;
    update test_table2 set cnt = cnt + 1;
    set new.no = v_no;
end//
DELIMITER ;

(2)このテーブル定義とトリガをダンプします

コマンド:

mysqldump -uroot test2


ダンプ結果:

(前略)
--
-- Table structure for table `test_table1`
--

DROP TABLE IF EXISTS `test_table1`;
CREATE TABLE `test_table1` (
  `no` int(11) default NULL,
  `str` varchar(16) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- Dumping data for table `test_table1`
--


/*!40000 ALTER TABLE `test_table1` DISABLE KEYS */;
LOCK TABLES `test_table1` WRITE;
UNLOCK TABLES;
/*!40000 ALTER TABLE `test_table1` ENABLE KEYS */;

/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
DELIMITER ;;
/*!50003 SET SESSION SQL_MODE="" */;;
/*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER 
`tri_test` BEFORE INSERT ON `test_table1` FOR EACH ROW begin
  declare v_no integer;
    select no into v_no from test_table1 for update;
    update test_table2 set cnt = cnt + 1;
    set new.no = v_no;
end */;;

DELIMITER ;
(後略)


(3)テーブルを削除後、ダンプ結果を流し込み
・まず DROP TABLE test_table1; でテーブルを削除。
・その後 先ほどのダンプ結果を流し込み。


その結果 bin-log には・・・・

# at 982
#060422  0:02:53 server id 1  end_log_pos 1096  Query   thread_id=4     exec_tim
e=0     error_code=0
SET TIMESTAMP=1145631773;
/*!40000 ALTER TABLE `test_table1` DISABLE KEYS */;
# at 1096
#060422  0:02:53 server id 1  end_log_pos 1209  Query   thread_id=4     exec_tim
e=0     error_code=0
SET TIMESTAMP=1145631773;
/*!40000 ALTER TABLE `test_table1` ENABLE KEYS */;
# at 1209
#060422  0:02:54 server id 1  end_log_pos 1524  Query   thread_id=4     exec_tim
e=0     error_code=0
SET TIMESTAMP=1145631774;
SET @@session.sql_mode=0;
CREATE DEFINER=`root`@`localhost` TRIGGER `tri_test` BEFORE INSERT ON 
                                          `test_table1` FOR EACH ROW begin
  declare v_no integer;
    select no into v_no from test_table1 for update;
    update test_table2 set cnt = cnt + 1;
    set new.no = v_no;
end */;
# End of log file

 なんと CREATE TRIGGER 文の end の後に */ がついています! 開始の /*! がないのに!!
 これによりレプリケーションのスレーブでの実行がエラーとなり、めでたくレプリケーション停止の結果を得られることになりましたとさ。

 
 log-bin に記録する際に、先頭に /*!50002 とかがつくのが正しいのか、 それとも */ は除去するほうが良いのかはわかりませんが、
 いずれにせよコメント(バージョン指定)処理が、bin-log出力処理の中で半端な状態であることは確かです。



 なお、view でも同様の現象が起きます。

# at 2350
#060422  0:17:28 server id 1  end_log_pos 2564  Query   thread_id=6     exec_tim
e=0     error_code=0
SET TIMESTAMP=1145632648;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW
`test_view` AS select `test_table1`.`no` AS `no` from `test_table1` */;
# End of log file



20520