如何调试MySQL的外键约束,ON DELETE CASCADE不是在生产环境中

问题描述:

我已经定义了2个表和它们之间的foriegn键约束删除从子表中的行如下:如何调试MySQL的外键约束,ON DELETE CASCADE不是在生产环境中

| users | CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `account_master_id` int(11) NOT NULL, 
    `user_type_id` int(11) NOT NULL, 
    `user_group_id` int(11) NOT NULL, 
    `user_type_code` char(1) NOT NULL, 
    `membership_number` varchar(40) NOT NULL, 
    `password` varchar(60) NOT NULL, 
    `email` varchar(200) NOT NULL, 
    `isd` varchar(10) NOT NULL, 
    `mobile` varchar(20) NOT NULL, 
    `passenger_id` int(11) NOT NULL, 
    `added_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `updated_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `added_by` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `email` (`email`), 
    KEY `account_master_id` (`account_master_id`), 
    CONSTRAINT `acMaster_to_user` FOREIGN KEY (`account_master_id`) REFERENCES `account_master` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=189 DEFAULT CHARSET=utf8 | 


user_oauth | CREATE TABLE `user_oauth` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `service` varchar(30) NOT NULL, 
    `auth_id` varchar(100) NOT NULL, 
    `email` varchar(100) NOT NULL, 
    `auto_share` tinyint(4) NOT NULL, 
    `photo` varchar(255) NOT NULL, 
    `auth_token_short` varchar(255) DEFAULT NULL, 
    `auth_details` text NOT NULL, 
    `device_type` varchar(60) NOT NULL, 
    `login_date` datetime NOT NULL, 
    `login_ip` varchar(20) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `user` (`user_id`), 
    CONSTRAINT `user_to_oauth` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=latin1 | 

从删除行users表中删除LOCAL和Staging环境中user_oauth表的相应条目。但是同样的东西在PRODUCTION环境下不起作用。我想知道我该如何调试。

更新:

  • 两个表是在严格模式下的InnoDB
  • 运行MySQL
+1

做'select @@ foreign_key_checks;'(当发生这种行为时)。如果它说0,修复你的数据,将它设置为1,然后去解雇一个人(除非是你自己,然后在地毯下面扫)。如果它说1,你将不得不寻找其他的想法。 – Solarflare

+0

感谢队友,那是区别。你能告诉我你是怎么弄出来的。我不是想要得到答案,而是了解问题以及如何调试这些问题。 – Gunnrryy

+0

我会添加一些关于该选项的背景作为答案。如何弄清楚它很难说清楚。如果你知道这个选项存在,那就没有魔力了。如果你不这样做,那很有意思。你也许能够推断出这样的东西存在并能够在手册中找到它。不幸的是,对于一些信息,在MySQL手册中找到正确的答案也需要魔法。 (尽管如此,包括技术细节在内的很多方面都做得很好)。我想一个现实的解决方案是谷歌它或要求知道它的人(例如在stackoverflow)。 – Solarflare

为什么外国键可能无法正常工作的原因是:

  • 他们不支持(例如在MyISAM桌上)
  • 他们disa流血

MySQL允许你通过系统变量foreign_key_checks设置为0禁用的外键约束上。这将允许您违反所有外键约束(例如,删除父母或添加无父母的孩子)。但它反过来也会禁用级联等相关功能,这些功能会自动阻止特定的约束违规(例如通过删除子级) - 如果该选项被禁用,哪些当然不会再发生。

这个想法是帮助你完成一些管理任务,例如,当引用数据尚未存在时导入数据,但通常在正常操作期间不应使用。如果该设置再次出现,您可能需要检查您的应用程序是否意外设置了该选项,因为每个服务器在默认情况下启动后都会启用它,并且必须明确禁用。

您可以通过检查当前设置。使用

select @@foreign_key_checks; 

您可以使用

SET foreign_key_checks = 1; 

再次启用它,但请注意,它不会检查你当前的数据:

FOREIGN_KEY_CHECKS设置为1,不触发扫描的现有表格数据。因此,在foreign_key_checks = 0时添加到表中的行将不会被验证是否一致。

所以你必须自己检查和修复它。您可以在再次启用设置之前或之后执行此操作,不过之前执行此操作可能会更容易。要触发重新检查,您可以并且应该删除并重新创建外键,以确保现在一切都一致。

+0

感谢您的解释。我认为这是因为从phpMyadmin中通过选择“禁用外键检查”并通过终端手动复制粘贴代码并忘记在最后启用“外键检查”而导出。这真的很有帮助。 – Gunnrryy