ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql-镜像表:触发器,死锁和隐式提交

2019-11-21 07:16:30  阅读:451  来源: 互联网

标签:deadlock autocommit mysql triggers stored-procedures


我有2个相似的表,例如A和B.我想将A中的插入复制到B中,并将B中的插入复制到A中以集成两个用户系统.我在每个触发器上配置了“插入触发器之后”.例:

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_A_INSERT`
AFTER INSERT ON `A`
FOR EACH ROW BEGIN 
INSERT INTO `B`
SET `id` = NEW.`id`,`name` = NEW.`name`;
END$$
DELIMITER ;

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_B_INSERT`
AFTER INSERT ON `B`
FOR EACH ROW BEGIN 
INSERT INTO `A`
SET `id` = NEW.`id`,`name` = NEW.`name`;
END$$
DELIMITER ;

如果我在A中插入,触发器将在B中调用一个插入,但是此插入将在B中执行触发器,并且会发生死锁,从而避免了无限循环.

我已经尝试在执行INSERT之前编辑触发器以删除另一个表触发器,然后在它之后再次创建它.例:

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_B_INSERT`
AFTER INSERT ON `B`
FOR EACH ROW BEGIN 
DROP TRIGGER IF EXISTS `after_A_INSERT`;
INSERT INTO `A`
SET `id` = NEW.`id`, `name` = NEW.`name`;
/* And CREATE again here */
END$$
DELIMITER ;

但是CREATE是进行隐式提交的数据定义语言(DDL)语句.因此,这无法完成.

我试图用内部的DROP调用PROCEDURE来显式处理提交,但这也是不可能的.

有什么建议可以反映这两个表吗?

更新:使用Bill Karwin suggestion,我向具有各自默认默认值A或B的每个表中添加了一个origin字段.然后,我按以下方式更改(删除和重新创建)触发器:

在A中触发:

...
BEGIN 
IF NEW.`origin`='A' THEN
    INSERT INTO `B`
        SET `id` = NEW.`id`, `name` = NEW.`name`,  `origin` = NEW.`origin`;
    END IF;
END

在B中触发:

...
BEGIN 
IF NEW.`origin`='B' THEN
    INSERT INTO `A`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END

解决方法:

您需要某种方式来避免创建周期.

我建议在两个表中都添加一个列原点.在表A中,将默认值设为“ A”.在表B中,将DEFAULT’B’设为默认值.

当插入到应用程序中的任何一个表时,请始终省略origin列,使其采用默认值.

在两个触发器中,仅当NEW.origin等于相应表的默认值时,才复制到另一个表.

重新发表您的评论和新错误:

抱歉,我忘了提到在触发器中插入另一个表时,还必须复制NEW.origin的值.仅在您的应用程序中执行原始插入操作时,才会忽略原点.

在A中触发:

...
BEGIN 
IF NEW.`origin`='A' THEN
    INSERT INTO `B`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END

在B中触发:

...
BEGIN 
IF NEW.`origin`='B' THEN
    INSERT INTO `A`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END

我创建了这些触发器,然后进行了测试:

mysql> insert into A set name = 'bill';
Query OK, 1 row affected (0.00 sec)

mysql> insert into B set name = 'john';
Query OK, 1 row affected (0.01 sec)

mysql> select * from A;
+----+------+--------+
| id | name | origin |
+----+------+--------+
|  1 | bill | A      |
|  2 | john | B      |
+----+------+--------+
2 rows in set (0.00 sec)

mysql> select * from B;
+----+------+--------+
| id | name | origin |
+----+------+--------+
|  1 | bill | A      |
|  2 | john | B      |
+----+------+--------+

标签:deadlock,autocommit,mysql,triggers,stored-procedures
来源: https://codeday.me/bug/20191121/2049896.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有