阻止表的替代方法

时间:2011-04-23 12:19:38

标签: php mysql

我有一个名为'messages'(INNODB)的表,用户可以在其中插入自己的帖子。 我想提出一个限制。在我的PHP脚本中,当表达到10条记录时,您无法添加更多记录。程序的逻辑或多或少如下。

步骤1.我运行查询来计算表格中的行。

步骤2.恢复该值,我决定是否插入新帖子。

我的困难在于妥善管理两个用户同时做同样事情的可能性。如果用户A在步骤1中而用户B刚刚完成第十个帖子的输入,则用户A将包括第十一个帖子。

如何避免它?

3 个答案:

答案 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执行到错误表中,从而导致唯一键错误并停止父事务。

更新2

正如下面的评论中指出的那样,多个同时进行的交易可以绕过支票 - 您必须使用LOCK TABLES <name> WRITE以确保它们不能。{/ p>

答案 2 :(得分:1)

2 /您也可以锁定MySQL表。

  • 执行:LOCK TABLES my_table
  • 然后执行您的业务规则。
  • 执行:UNLOCK TABLES

这也确保了每个动作都是按顺序执行的。 (但你必须处理性能开销)

希望这可能有用。

自以下评论更新后:在这种情况下,交易不起作用

1 /您正在使用InnoDB,您也可以使用数据库事务

  • 打开交易
  • 然后执行您的业务规则。
  • 提交或回滚您的交易

这将确保每个操作都是一个接一个地执行。