如何调试 mysql 外键约束,ON DELETE CASCADE 在生产环境中不从子 table 中删除行
How to debug mysql foreign key constraint, ON DELETE CASCADE not deleting rows from Child table on production environment
我定义了 2 个 table 和它们之间的外键约束,如下所示:
| 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 |
从用户 table 中删除一行时,会从本地和暂存环境中的 user_oauth table 中删除相应的条目。但是同样的事情在生产环境中不起作用。我想知道如何调试它。
更新:
- 两个table都是innodb
- 运行 mysql 在严格模式下
外键可能不起作用的原因是:
- 它们不受支持(例如 MyISAM-tables)
- 它们被禁用
MySQL 允许您通过将系统变量 foreign_key_checks 设置为 0
来禁用外键约束。这将允许您违反所有外键约束(例如删除 parent 或添加 parentless 子项)。但它反过来也会禁用相关功能,如级联,这些功能可以自动防止特定约束违规(例如删除 children)——如果禁用该选项,这当然不会再发生。
这个想法是为了帮助您完成一些管理任务,例如在引用数据尚不存在时导入数据,但通常不应在正常操作期间使用。如果该设置再次出现,您可能需要检查您的应用程序是否意外设置了此选项,因为默认情况下它在每台服务器启动后启用并且必须明确禁用。
您可以通过例如使用
select @@foreign_key_checks;
您可以使用
SET foreign_key_checks = 1;
再次启用它,但请注意它不会检查您的当前数据:
Setting foreign_key_checks to 1 does not trigger a scan of the existing table data. Therefore, rows added to the table while foreign_key_checks=0 will not be verified for consistency.
所以你必须自己检查并修复它。您可以在再次启用该设置之前或之后执行此操作,尽管之前执行此操作可能更容易。要触发重新检查,您可以而且应该删除并重新创建外键,只是为了确保现在一切都一致。
我定义了 2 个 table 和它们之间的外键约束,如下所示:
| 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 |
从用户 table 中删除一行时,会从本地和暂存环境中的 user_oauth table 中删除相应的条目。但是同样的事情在生产环境中不起作用。我想知道如何调试它。
更新:
- 两个table都是innodb
- 运行 mysql 在严格模式下
外键可能不起作用的原因是:
- 它们不受支持(例如 MyISAM-tables)
- 它们被禁用
MySQL 允许您通过将系统变量 foreign_key_checks 设置为 0
来禁用外键约束。这将允许您违反所有外键约束(例如删除 parent 或添加 parentless 子项)。但它反过来也会禁用相关功能,如级联,这些功能可以自动防止特定约束违规(例如删除 children)——如果禁用该选项,这当然不会再发生。
这个想法是为了帮助您完成一些管理任务,例如在引用数据尚不存在时导入数据,但通常不应在正常操作期间使用。如果该设置再次出现,您可能需要检查您的应用程序是否意外设置了此选项,因为默认情况下它在每台服务器启动后启用并且必须明确禁用。
您可以通过例如使用
select @@foreign_key_checks;
您可以使用
SET foreign_key_checks = 1;
再次启用它,但请注意它不会检查您的当前数据:
Setting foreign_key_checks to 1 does not trigger a scan of the existing table data. Therefore, rows added to the table while foreign_key_checks=0 will not be verified for consistency.
所以你必须自己检查并修复它。您可以在再次启用该设置之前或之后执行此操作,尽管之前执行此操作可能更容易。要触发重新检查,您可以而且应该删除并重新创建外键,只是为了确保现在一切都一致。