MySQL外键违规率为20%
我有一个“有时会发生”的问题,我甚至不知道从哪里开始 我有以下数据库结构:MySQL外键违规率为20%,mysql,go,Mysql,Go,我有一个“有时会发生”的问题,我甚至不知道从哪里开始 我有以下数据库结构: CREATE TABLE `group` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8; CREATE TABLE `person` ( `id` int(11)
CREATE TABLE `group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`group_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_group` (`group_id`),
CONSTRAINT `user_ibfk_2` FOREIGN KEY (`group_id`) REFERENCES `group` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
所以,我有一个组表和一个人表。此人只能属于一个组,因此它有一个名为group_id的外键
如果我试图删除一个有人引用的组,通常会出现外键错误,无法删除组。但是,有时mysql会很高兴地删除这个组,留下一个人引用一个不存在的组
- MySQL版本是5.7.10,运行正式的Docker映像
- 表是InnoDB
- 外键检查设置为1
### Groups ####
id: 1, name: My group!
id: 2, name: Hello!
id: 3, name: Wat!
id: 22, name: My Group!
id: 23, name: My Other Group!
id: 24, name: Completely Different Group!
### People ####
id: 26, group_id: 1
id: 28, group_id: 3
id: 25, group_id: 23
然后删除进来。。。我最后得出以下结论:
### Groups ####
id: 1, name: My group!
id: 2, name: Hello!
id: 3, name: Wat!
id: 22, name: My Group!
id: 24, name: Completely Different Group!
### People ####
id: 26, group_id: 1
id: 28, group_id: 3
id: 25, group_id: 23
id为23的组已被删除,即使此人:25仍在引用该组
MySQL日志在这两种情况下都是这样的(无论是否抛出外键约束错误):
正如我已经说过多次的那样,这种情况只发生了约20%。我正在使用go-sql驱动程序/mysql
访问数据库
执行所有这些操作的示例代码:
getAllGroups := "SELECT id, name FROM group"
getAllUsers := "SELECT id, group_id FROM person"
rows, err := DB.Query(getAllGroups)
checkErr(err)
defer rows.Close()
// Print all the groups
rows, err = DB.Query(getAllUsers)
checkErr(err)
defer rows.Close()
// Print all the users
// Each group is referenced by a user
query := "DELETE FROM group WHERE id = ?"
_, err = DB.Exec(query, groupID)
// Detect if the deletion failed
if err != nil {
if strings.Contains(err.Error(), "a foreign key constraint fails") {
// FOREIGN KEY CONSTRAINT FAILED
}
// SOMETHING ELSE FAILED
}
// EVERYTHING WORKED... even though it shouldn't have
你能试着把DELETE CASCADE上的
添加到外键定义中吗?这不是我想要的。我希望使用DELETE RESTRICT上的默认
,如果某个对象引用了某一行,我将无法删除该行。
getAllGroups := "SELECT id, name FROM group"
getAllUsers := "SELECT id, group_id FROM person"
rows, err := DB.Query(getAllGroups)
checkErr(err)
defer rows.Close()
// Print all the groups
rows, err = DB.Query(getAllUsers)
checkErr(err)
defer rows.Close()
// Print all the users
// Each group is referenced by a user
query := "DELETE FROM group WHERE id = ?"
_, err = DB.Exec(query, groupID)
// Detect if the deletion failed
if err != nil {
if strings.Contains(err.Error(), "a foreign key constraint fails") {
// FOREIGN KEY CONSTRAINT FAILED
}
// SOMETHING ELSE FAILED
}
// EVERYTHING WORKED... even though it shouldn't have