【发布时间】:2014-01-24 07:08:39
【问题描述】:
在高层次上,我所拥有的是:
- 由应用程序 1 填充和管理的“主”数据库。
- 使用standard mechanism 从“主”数据库复制的单独主机上的“从”数据库。
- 应用程序 2,独立于应用程序 1 运行,对从属数据库的只读访问权限和对其自己独立数据库的读写访问权限非常有限。
基本上需要发生的是,当“从属”数据库中的某些事情发生变化时,应用程序 2 需要得到通知,以便它可以检查“从属”数据库的内容并将一些内容写入自己的数据库。
性能不是问题,发生这种情况时锁定整个“从属”数据库是可以接受的。 关键是要确保在应用程序 2 完成操作之前不会将更多信息复制到“从属”数据库中。应用程序 2 从独立于触发的会话访问“从属”数据库通知。
为此,我有以下触发器:
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;可能会做到这一点?
编辑 - 这是一个额外的后续问题:
当应用程序 2 去做它的事情时,它看到的数据并没有反映应该在“从”数据库中的最新信息。具体来说,作为触发事务的一部分对jobs 表所做的任何更新对应用程序 2 都是不可见的。
既然触发器配置为触发AFTER UPDATE,为什么会出现这种情况?是否有任何方法可以使数据库中的应用程序 2 可以看到新内容,或者是否有必要手动收集并传递所有更新的字段值作为发送通知的一部分?
【问题讨论】:
标签: mysql stored-procedures triggers database-replication