【问题标题】:Auto increment of a unique varchar could cause duplicate唯一 varchar 的自动增量可能会导致重复
【发布时间】:2017-07-17 03:56:52
【问题描述】:

我有一个每天接受数百个数据的 php 系统。我使用 MySQL 作为数据库来存储所有数据。

其中一个主表,我们称之为“tableData”,存储所有主数据并有 2 个主键。第一个主键是一个自增整数。第二个主键是submission_num,它以这种格式存储了一个varchar值(rep/yyyy/A.I.integer,例如rep/2017/00021、rep/2017/00023、rep/2016/02345)

当需要将数据提交到tableData中时,php会检索到submission_num的最大个数并将其加1,然后使用新的submission_num将新数据插入到tableData中。 (例如,如果php接收rep/2017/00034为最大数,它将整数部分加1,这将导致新的提交num rep/2017/00035,然后将新数据与新提交一起存储数)

PHP 脚本的算法看起来像这样

  1. 获取最大提交数,
    查询:SELECT submit_num FROM tableData WHERE substr(submission_num,5,4) = '$curYear' ORDER BY submit_num DESC LIMIT 0, 1

  2. 整数部分加1

  3. 存储数据

这种方法引起了问题。当两个或更多用户在正确的时刻点击“提交”按钮时。它们将生成相同的提交编号,并与重复的提交编号一起保存到数据库中(此提交编号必须是唯一的)

有没有一种方法可以暂时锁定我的 PHP 脚本中的任何 Select 查询中的表?

【问题讨论】:

  • 顺便说一句,如果我告诉你们不好,我很抱歉。我的英语很糟糕
  • 根据使用表的类型,您将使用事务或锁。无论如何,如果您在一个表中有/需要两个自动增量,则表明您可能只需要其中一个,或者您可能需要创建第二个表。

标签: php mysql


【解决方案1】:

一张表只有一个主键约束,它可以有多个唯一约束。现在把肥皂盒放在一边。

您遇到了麻烦,因为submission_num 代表表的 3 个不同属性。因为您想在插入行时计算第三个属性(给定行集的子序列),所以您遇到了一个并发问题,导致您询问有关锁定表的问题。

您应该做的是定义表格以模拟现实的方式并将submission_num 的第一个组件存储为某种类型的代码列,并将第二个组件存储为 insert_date 列。

然后您可以稍后在查询表时计算第三个“子属性”。这样,您不必必须锁定表,这是面向用户的应用程序永远不必做的事情。

附录 1

您可以在新表中进行更改(包括附加的 year_submission_num 列),为插入日期小于 2017 年 1 月 1 日的行填充 year_submission_num,然后创建一个由两个集合 A 和乙

集合 A 是 year_submission_num 不为空的行集合,您可以在其中定义投影列 C,它是当前具有的值的串联。

集合 B 是 year_submission_num 为空的一组行,您可以在其中编写更复杂的子查询来生成 C。

然后,您每天运行一次批处理作业来更新 year_submission_num 当前为空的位置。这样,“更复杂的子查询”不会太昂贵。

如果你做到了所有,那么你就不必改变你的页面了。

【讨论】:

  • 感谢您的精彩建议。但似乎需要重新编码的页面太多,因为有相当多的页面使用 submit_num 检索数据。谢谢你的解释。非常感谢
  • @CatifyAuthent 检查附录 1。
  • 谢谢。起初这很难理解,但现在我明白了。看来您的解决方案需要相当长的时间。我没有太多时间,因为我只能在客户公司修改代码和数据库。他们不允许远程。但我确实有源代码和数据库的副本。将尝试在我的本地主机上实现这一点。如果它很好,那么当我再次来到这里时,我会实施它。那将是从现在开始的 1 个月。 叹息
【解决方案2】:

我不知道某些查询是否可以处理这个问题,但我有一个简单的方法。将整数部分加1后可以再次检查,如果没有像结果一样的第二个主键,则可以存储数据。如果结果有第二个主键,您可以再次将整数部分增加1。是的,你需要循环过程来进行这个检查

【讨论】:

  • 那么在检查和插入之间可能会出现同样的问题。
  • 即使您的编辑不起作用,您仍然可以得到重复。你只能通过自动递增字段、锁或事务来解决这个问题。
  • 你好。感谢你的回答。是的,我同意每个人的观点。同样的问题仍然可能发生。因为我可以修改客户公司的代码,因为我无法远程访问(而且我可能只能在 1 个月后再次来到这里),所以我现在实现了你的想法,除了每个循环脚本将随机休眠时间在 1 到 5 秒之间。我相信这会减少获得重复提交编号的机会,但会减慢提交过程。我现在坚持这个解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 2011-05-02
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
相关资源
最近更新 更多