【问题标题】:Concurrent access PHP+MySQL with ID generation issue并发访问 PHP+MySQL 与 ID 生成问题
【发布时间】:2015-12-24 08:26:42
【问题描述】:

在 InnoDB MySQL 存储引擎中,存储过程用于生成 tbaaa000000 形式的主键值。

密钥生成

因此,主键的格式为: 对于固定长度,例如 l,第一个 two 字符表示 table_name,接下来的 m 是字母,其余 (l-2-m) 是数字(只有数字)。

存储过程已被编码为使用动态 SQL 手动增加最右边的 m+n 块字符。这是通过查找表中存在的最大 ID(比如 tbaaa999999 )并将其递增(到 tbaab000000)来完成的。通过动态 SQL,我的意思是它已被用于在运行时通过在查询中合并变量来动态构建 SQL 语句。

表单提交

假设我们正在尝试为表Table1 生成这个主键。另外,我们还有另一个表(比如Table2),它引用了Table1 的主键(Table2Table1 上有一个外键)。

现在,使用 PHP 脚本将表单提交到服务器,该脚本将表单数据插入 Table1Table2。但是,主键 ID 是在执行 Table1 的查询期间使用存储过程生成的,但是即使对于 Table2 的插入查询,该 ID 也是同时需要的,这在 PHP 脚本中是未知的。

另外,可能有多个客户端试图访问该页面,因此 PHP 脚本会为所有用户运行,因此生成的存储过程可能会为多个用户生成相同的主键 ID。

我的问题:

  1. 由于请求的并发性,我如何管理 Table1 中唯一 ID 的生成和插入?
  2. 如何在 PHP 脚本中获取生成的 Table1 的主键以插入到Table2

SO 鼓励我将我尝试过的内容包括在内,因此我将自己的努力包括在内。但是,我不希望限制答案的范围,所以请在阅读我的试用版之前尝试考虑一种方法。

我想到的方法:

我们可以从 PHP 脚本中调用一个过程,该过程将插入数据作为参数并生成主键 ID Table1 并将数据插入到两个表中。但是,这会失败,因为整个过程仍然可以为并发请求生成相同的 ID。

我还在 PHP 脚本末尾探索了一个 try-catch 方法,该方法将调用一个函数来生成 ID 并将其返回给 PHP 脚本。然后,这将尝试插入Table1,如果相同的 ID 已经存在(可能是由于另一个用户的并发另一个插入处理),这将失败并抛出一个duplicate key exception 并再次尝试生成,从而提供唯一性。但是,我不确定这种方法,因为这可能效率低下并且可能导致性能问题。

【问题讨论】:

    标签: php mysql database concurrency primary-key


    【解决方案1】:

    这就是交易的用途。您需要做的伪代码是:

    1. 开始交易。
    2. 获取表 1 中的最高 ID。
    3. 增加这个。
    4. 将新行存储在表 1 中。
    5. 提交事务。

    如果发生这种情况时另一个客户端尝试访问表 1,它们将被阻止,直到事务提交。

    【讨论】:

    • 谢谢。我探索了这种方法,但需要澄清一下,要让事务工作,我在 MySQL 中必须提到什么?我必须保持交易可序列化吗? this 之类的东西?
    • 我认为默认设置应该可以处理大多数情况。另一个问题中的问题是不同表之间的异常同步,但这对您来说不是问题。
    • 感谢您的讨论!我将尝试测试并发性并在此之后标记此答案已接受:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 2014-11-25
    • 2013-04-09
    相关资源
    最近更新 更多