并发访问PHP + MySQL与ID生成问题

时间:2015-12-24 08:26:43

标签: php mysql database concurrency primary-key

在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。但是,在执行Table1的查询期间,使用存储过程生成了主键ID,但是即使对于Table2的插入查询,也会同时需要此ID。 PHP脚本。

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

我的问题:

  1. 由于请求的并发性,如何在Table1中管理仅生成和插入唯一ID?
  2. 如何在PHP脚本中返回Table1生成的主键以插入Table2
  3. SO鼓励我把我尝试过的东西包括在内,所以我已经把我的努力包括在内了。但是,我不希望答案的范围受到限制,所以请在阅读我的试用版之前尝试一种方法。

    我想到的方法:

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

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

1 个答案:

答案 0 :(得分:1)

这是交易的目的。您需要做的伪代码是:

  1. 开始交易。
  2. 获取表1中的最高ID。
  3. 增加这个。
  4. 将新行存储在表1中。
  5. 提交交易。
  6. 如果另一个客户端在发生这种情况时尝试访问表1,它们将被阻止,直到提交事务为止。