На высоком уровне, что у меня есть это:MySQL - таблицы блокировки или начать транзакцию с триггером
- базы данных «мастер» A, который заполняется и управляется Application 1.
- ведомому» 'на отдельном хосте, который реплицируется из базы данных «master», используя standard mechanism.
- Приложение 2, которое выполняется независимо от Приложения 1 и имеет очень ограниченный доступ только для чтения к базе данных подчиненного устройства и доступ на чтение и запись к своей отдельной базе данных.
И в основном то, что должно произойти, заключается в том, что когда некоторые вещи изменяются в базе данных «slave», приложение 2 должно быть уведомлено, чтобы оно могло проверять содержимое базы данных «подчиненный» и записывать некоторые вещи в свои собственные база данных.
Производительность не вызывает беспокойства, и это приемлемо для блокировки всей базы данных slave, когда это происходит. Важнейшей задачей является обеспечение того, чтобы никакая дополнительная информация не была реплицирована в базу данных «slave», пока Application 2 не выполнит свою задачу. Приложение 2 обращается к базе данных «slave» из сеанса, независимого от сеанса, инициирующего уведомление.
Для достижения этой цели, я следующий триггер:
delimiter //
CREATE TRIGGER create_report_trigger AFTER UPDATE ON jobs
FOR EACH ROW
BEGIN
DECLARE report_id INT;
IF (NEW.status = 7 AND OLD.status != 7) THEN
CALL CREATE_REPORT_PROC(NEW.id, @report_id);
END IF;
END;
//
delimiter ;
... и так как вы не можете начать транзакцию или заблокировать базу данных внутри триггера, у меня есть следующий процедура:
delimiter //
CREATE PROCEDURE create_report_proc(
IN jobId INT,
OUT report_id INT
)
BEGIN
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT CREATE_REPORT(jobId) INTO report_id;
COMMIT;
END //
delimiter ;
процедура взывает к user-defined function, который использует Libcurl связаться приложения 2 и дайте ему знать, что он должен обработать работа.
Эта процедура отлично работает, когда я вызываю ее вручную в командной строке MySQL. Однако, когда она вызывается из триггера, следующее сообщение об ошибке появляется в журнале MySQL:
Explicit or implicit commit is not allowed in stored function or trigger
... так что, по-видимому MySQL достаточно умны, чтобы обнаружить, что я пытался не подорвать его «нет блокировки изнутри триггера ", используя триггер-делегат для процедуры.
Пользовательская функция ожидает завершения работы приложения 2, прежде чем возвращать результат вызывающему абоненту, что может быть актуальным (если процесс репликации MySQL по существу блокируется выполнением триггера, тогда нет необходимости вручную блокировать ничего, процесс репликации - это единственное, что может внести изменения в базу данных «подчиненный»).
Во всяком случае, я полагаю, есть два вопроса:
Поскольку триггер срабатывает, как следствие обновления, сделанное в процессе репликации MySQL, это означает, что процесс репликации блокируется, пока спусковой крючок возвращается?
Если нет, как заблокировать базу данных или остановить процесс репликации с помощью триггера? Я полагаю, что выдача
STOP SLAVE;
изнутри триггера может это сделать?
Edit - А вот бонус Followup вопрос:
Когда Application 2 идет делать свое дело, данные, которые он видит, не отражает самую последнюю информацию, которая должна быть в «раба» база данных. В частности, любые обновления, сделанные в таблице jobs
как часть триггерной транзакции, не видны для приложения 2.
Почему это так, если триггер сконфигурирован для запуска AFTER UPDATE
? И есть ли способ сделать новый контент видимым для приложения 2 в базе данных, или же необходимо вручную собирать и передавать все обновленные значения полей как часть отправленного уведомления?