SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 22.06.2010 17:55:36

boa
Завсегдатай
Зарегистрирован: 22.06.2010
Сообщений: 38

Репликация, триггеры, binlog и binlog-format=STATEMENT

Здравствуйте!
Возникла проблема, буду рад помощи или совету.

Небольшое описание сети:

построена цепочка репликации H1->H2->H3

Где H1 - мастер машина
H2 - реплика1
H3 - еще одна реплика - реплика2.

Все машины содержат БД, для пример назовем ее TestDB.
В базе данных содержится одна таблица table1.
На мастер машине происходит работа с этой таблицей, все изменения реплицируются на реплики, согласно модели репликации.

На репликах Н2 и Н3 в TestDB помимо таблицы table1 есть еще таблица stat для сбора статистики.
На table1 установлены тригеры срабатывающие на insert update и delete и вносящие инфу в таблицу stat
Таблица stat объявлена не реплицируемой ( через replicate-ignore-table)
Чтобы тригерры срабатывали при репликации, формат репликации на всех мастер машинах был установлен в STATEMENT

Соответственно на машине Н2 имеется binlog. он необходим для репликации на машину Н3.

Все работает, но возникла следующая проблема:

В логах error.log Mysql пишется следующее событие
100622 17:50:23 [Warning] Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically. Statement: insert into stat(doc_id, actId, actTime) value( NEW.Id, 1, now())

Я так понимаю ему не нравится что в бинлог попадает sql запрос где используется New.id, но это единственный способ определить ID новой записи которая вставляется.
Думаю если бы использовался row формат он бы не ругался.
Как быть? Таблица не реплицируется, но события связанные с ней попадают в бинлог и mysql ругается.
как это исправить?

Неактивен

 

#2 22.06.2010 23:23:02

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Репликация, триггеры, binlog и binlog-format=STATEMENT

Ему не нравится, что в stat есть автоинкрементное поле, которое реплицируется,
вообще говоря, непереносимым образом.

Можно убрать это поле или включить на H2 и H3 binlog_format = mixed.

Неактивен

 

#3 23.06.2010 11:06:44

boa
Завсегдатай
Зарегистрирован: 22.06.2010
Сообщений: 38

Re: Репликация, триггеры, binlog и binlog-format=STATEMENT

Спасибо за совет
я бы с радостью переключил в mixed, но суть в том что триггеры должны гарантированно срабатывать на репликах. Если использовать mixed формат, то какова гарантия что mysql при репликации таблицы table1 выберет statement выражение? он же может выбрать любой способ с равной степенью вероятности.

я попробовал перевести машину Н2 в mixed формат, и как следствие на машине Н3 перестали срабатывать тригеры на таблице table1.

я изменил структуру таблиц и переписал триггеры. теперь работает хорошо, предупреждения не попадают в еррор.лог
стало так:
в таблице stat изменил поле ID - убрал у него способность автоинкремента

CREATE TABLE `stat` (
  `id` int(11) unsigned NOT NULL DEFAULT '0',
  `doc_id` int(11) unsigned NOT NULL DEFAULT '0',
  `ActId` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `ActTime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `doc_id` (`doc_id`),
  KEY `ActId` (`ActId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

переписал тригеры на таблице table1
один из них
CREATE DEFINER=`root`@`%` TRIGGER `mybd`.`table1_actIns` AFTER INSERT ON `mybd`.`table1`
  FOR EACH ROW begin
select (max(id)+1) into @maxid from stat;
insert into stat(id, doc_id, actId, actTime) value( @maxid , NEW.Id, 1, now());
end;

вроде пока сейчас все работает.
Если я где то допустил неточность или возможную ошибку, напишите плизsmile

И еще у меня есть вопрос, наверное он связан с репликацией тоже.
в триггере есть выражение NOW(), я его использую чтобы вставлять в таблицу stat дату и время когда триггер сработал.
Так вот проблема - время которое попадает в stat не совпадает с текущим системным. Оно как будто опережает системное время на несколько часов, и если системное время у меня 2010-06-23 11:03:50 то в таблицу stat после срабатывания триггера попадает дата и время 2010-06-24 01:52:50
Но в тоже время запрос "select now()" на сервере выдает нормальную дату и время.
В чем может быть проблема в триггере? Почему функция NOW() в триггере выдает совсем другое время и дату?

Неактивен

 

#4 23.06.2010 11:58:23

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Репликация, триггеры, binlog и binlog-format=STATEMENT

А чем идеологически плохо, если у Вас на H3 будет приезжать строчка в
бинарном формате? Ну, не выполнится триггер — но он же выполнился на
H2, и данные в stat тоже приедут через репликацию?

Что касается NOW() — timestamp хранится в UTC, поэтому нужно убедить-
ся, что на всех трех серверах стоит правильное системное время (т.е.
UTC + правильно настроенная временн́aя зона). Ну и, если на каком-
то из серверов у Вас в MySQL явно выставлена TZ — это тоже может влиять.

Неактивен

 

#5 23.06.2010 12:07:54

boa
Завсегдатай
Зарегистрирован: 22.06.2010
Сообщений: 38

Re: Репликация, триггеры, binlog и binlog-format=STATEMENT

paulus написал:

А чем идеологически плохо, если у Вас на H3 будет приезжать строчка в
бинарном формате? Ну, не выполнится триггер — но он же выполнился на
H2, и данные в stat тоже приедут через репликацию?

Ничем не плохо. Пожалуй вы правы.smile

paulus написал:

Что касается NOW() — timestamp хранится в UTC, поэтому нужно убедить-
ся, что на всех трех серверах стоит правильное системное время (т.е.
UTC + правильно настроенная временн́aя зона). Ну и, если на каком-
то из серверов у Вас в MySQL явно выставлена TZ — это тоже может влиять.

Проверю настройки.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson