我有一个名为'messages'(INNODB)的表,用户可以在其中插入自己的帖子。 我想提出一个限制。在我的PHP脚本中,当表达到10条记录时,您无法添加更多记录。程序的逻辑或多或少如下。
步骤1.我运行查询来计算表格中的行。
步骤2.恢复该值,我决定是否插入新帖子。
我的困难在于妥善管理两个用户同时做同样事情的可能性。如果用户A在步骤1中而用户B刚刚完成第十个帖子的输入,则用户A将包括第十一个帖子。
如何避免它?
答案 0 :(得分:4)
您可以创建CHAR(1)
NOT NULL
字段,并使用UNIQUE INDEX
覆盖该字段。这样可以防止插入超过10行。
其他可行的解决方案是创建BEFORE INSERT
触发器,检查行数并在超过10(look here for sample)时引发错误(但在这种情况下,您可能会因条件争用而失败) )。
答案 1 :(得分:3)
为了允许您更改表的阈值,您可以使用触发器。由于MySQL触发器没有“阻止INSERT
”选项,因此您需要将表中的值设置为NOT NULL
。然后,触发器可以将该列的插入值设置为NULL
,如果您的条件检查失败,将阻止INSERT
。
这样的触发器:
CREATE TRIGGER block_insert
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
DECLARE count INT;
SELECT COUNT(*)
FROM table_name INTO count;
IF count >= 10
THEN
SET NEW.non_nullable_value = NULL;
END IF;
END;
如果插入第11行,将失败,如下所示:
ERROR 1048 (23000): Column 'non_nullable_value' cannot be null
您可能希望将不可为空的列的名称设置为代表其使用的名称。您可以通过让触发器从配置表中提取限制值来改善这一点。
为了避免必须使用不可为空的列,您也可以创建一个错误过程,并从触发器CALL
创建它 - 类似于example in the "Emulating Check Constraints" section of this page - 它们引用的是Oracle数据库,其中检查约束实现了您想要的,但MySQL不支持它们。
示例中的“错误过程”会将重复行的INSERT
执行到错误表中,从而导致唯一键错误并停止父事务。
正如下面的评论中指出的那样,多个同时进行的交易可以绕过支票 - 您必须使用LOCK TABLES <name> WRITE
以确保它们不能。{/ p>
答案 2 :(得分:1)
2 /您也可以锁定MySQL表。
这也确保了每个动作都是按顺序执行的。 (但你必须处理性能开销)
希望这可能有用。
自以下评论更新后:在这种情况下,交易不起作用
1 /您正在使用InnoDB,您也可以使用数据库事务
这将确保每个操作都是一个接一个地执行。