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
现在,在实际尝试删除一个组之前,我正在两个表上运行select以查看它们的内容;也许这会有帮助

我有这样的想法:

### 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