首页 > 解决方案 > 是否建议使用触发器在 mysql 中创建约束?

问题描述

我有一个案例让我困惑和烦恼了很长时间,目前我正在努力是否应该使用触发器。这里我在 MYSQL 中有两个表

Create table type(
id int primary key not null auto_increment,
class int not null default 0,
name string not null
)

Create table buddy (
id int primary key not null auto_increment,
value string not null)

Create table value (
id int primary key not null auto_increment,
type_id int not null,
buddy_id int default null,
value string not null,
relied_id int default null
foreign key type_id references type(id)
)

在这种情况下,有几个规则,

在 value table 里面,有些 value 可以参考 buddy table,有些不是。

if (the buddy_id inside value is not null){ 
   row with this buddy_id should be unique
} else{ 
   could have several instances with the nil buddy_id
}

如果 buddy_id 为 nil,这意味着它不引用任何内容,则它可能是重复的。

在我的模块中,我将收到来自同事队列的消息,然后执行以下操作:

1), if I detect inside the message, there is a buddy_id, I need to use sql to check whether the value with this buddy_id is already in the database, if yes, just ignore, else should create one.
2), else, directly create a new one

在第一种情况下,我的同事一直向我发送重复的消息,因为在我得到“具有此 buddy_id 的实例是否已经在数据库中”结果为 false 之后,它仍然需要一些时间来做一些逻辑并创建一个新的实例,然后插入数据库。我得到结果和插入之间可能存在差距。

在此期间,可能会有另一个消息带有相同的 buddy_id,它会触发另一个 goroutine 或线程,但第一次插入仍然没有完成,在这种情况下,它也会发现“这个 buddy_id 的实例不在数据库中,我应该创造一个”。

结果,多个具有相同 buddy_id 的实例将被插入到数据库中。 在此处输入图像描述 我认为这张图片可以更好地说明我在说什么,两个具有相同 buddy_id 的消息一个接一个,但是当消息 1 的 buddy_id = 10 正在处理时,在插入之前,消息 2 来了,发现没有 buddy_id = 10,所以消息2还在数据库中创建一个实例。

之前我尝试锁定表,但是项目经理要求我取消锁定,因为这个值表是主表,他不希望我锁定数据库。

我还查看了唯一约束,但 buddy_id 的情况是“如果它是 nil,则不唯一,如果它不是 nil,则唯一”。我认为这不能仅使用唯一键约束来完成。

所以有人知道我是否应该在插入之前使用触发器进行检查以确保实例不重复?或者有什么其他推荐的方法?

谢谢。

标签: mysqlsqldatabase-trigger

解决方案


推荐阅读