<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Блог Андрея Смирнова (trigger)</title><link>http://www.smira.ru/</link><description></description><language>ru</language><lastBuildDate>Sun, 11 Jan 2015 19:24:26 GMT</lastBuildDate><generator>http://getnikola.com/</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>MySQL, ROW/STATEMENT/MIXED-репликация и триггеры</title><link>http://www.smira.ru/posts/20100215mysql-row-statement-mixed-replication-triggers.html</link><dc:creator>Andrey</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;p&gt;Описанная особенность MySQL попалась мне на глаза слишком поздно, пишу, чтобы кто-то не напоролся на те же грабли. Начнем с начала. Итак, необходимо было отслеживать изменения MySQL-базы данных и складывать эти изменения в очередь (не в БД) для дальнейшей обработки внешней системой. Для отслеживания изменений подходят триггеры, но они активируются в процессе выполнения запросов транзакции и в случае последующего "rollback" не будут откатываться (что совершенно нормально для триггеров, влияющих только на состояние БД, т.к. состояние БД будет корректно откатываться).  Поэтому необходимо выполнять триггеры только для успешных транзакций: проще всего это достигнуть с помощью репликации - на слейв передаются только запросы зафиксированных транзакций. Таким образом, мастер-БД не содержит триггеров, после репликации данные попадают на слейв, таблицы на котором обвешаны триггерами, те активируются и данные попадают в очередь. Казалось бы, все замечательно?&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;Однако MySQL не был бы MySQL, если бы не какие-нибудь приколы на пути. Читаем раздел &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/replication-features-triggers.html"&gt;16.3.1.29&lt;/a&gt; документации: триггеры на слейве выполняются только при использовании STATEMENT-based репликации, при использовании ROW-based репликации они выполняются на мастере. ROW-based репликация - одно из нововведений 5.1, при котором на слейв передаются не запросы (текст запроса), измененный в БД записи (подробнее см. раздел &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/replication-formats.html"&gt;16.1.2&lt;/a&gt;). Но это было бы еще полбеды - попробовал, увидел, что триггеры не выполняются, и пошел разбираться. Однако в MySQL придумали еще режим репликации MIXED: при этом сервер сам переключается между STATEMENT и ROW-based репликацией (я не нашел, по какому условию). Далее, в версиях MySQL от 5.1.12 до 5.1.29 режимом репликации по умолчанию &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_binlog-format"&gt;выбирается как раз MIXED&lt;/a&gt;. Как вы уже догадываетесь, в MIXED-режиме триггеры на слейве то выполняются, то нет, при этом внешне это совершенно незаметно. Так прекрасно работавший слейв в один прекрасный день вдруг перестает поставлять обновления в очередь, хотя сам по себе слейв не отстал и содержит все данные.&lt;/p&gt;
&lt;p&gt;Итого, несколько часов на поиск проблемы, работа по пересинхронизации данных во внешней системе... Спасибо, MySQL!&lt;/p&gt;
&lt;p&gt;Кратко: чтобы триггеры на слейве всегда выполнялись, надо добавить в my.cnf (на мастере):&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre&gt;
&lt;p&gt;[mysqld]&lt;/p&gt;
&lt;p&gt;binlog-format=STATEMENT&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;</description><category>mysql</category><category>trigger</category><category>разработка</category><guid>http://www.smira.ru/posts/20100215mysql-row-statement-mixed-replication-triggers.html</guid><pubDate>Mon, 15 Feb 2010 19:48:10 GMT</pubDate></item></channel></rss>