如何在MySQL中实现事务安全的随机序列

时间:2012-05-02 02:18:02

标签: php mysql transactions innodb sequence

所以我的应用需要让用户生成随机字母数字代码,如A6BU31,38QV3B,R6RK7T。目前它们由6个字符组成,而I和O不使用(因此我们有34 ^ 6种可能性)。然后打印出这些代码并用于其他内容。

我现在必须确保许多用户可以为每个请求“保留”最多100个代码,因此用户A可能想要获得50个代码,用户B想要生成10个代码,依此类推。这些代码在所有用户中必须是唯一的,因此用户A和用户B可能都不会同时接收代码ABC123。

我目前的方法(使用PHP和MySQL)是为了拥有两个InnoDB表:

  • 一个(“存储库”)包含大量预先生成的代码(因为冲突的可能性会随着时间的推移而增加,我不想去try-insert-if-failed-try-another-code方法)。存储库只包含代码和自动递增的ID(因此我可以对它们进行排序,见下文)。
  • 另一个表包含保留密钥(即代码+拥有用户)。

每当用户想要保留N个密钥时,我计划执行以下操作

BEGIN;
INSERT INTO revered_codes (code,user_id)
  SELECT code FROM repository WHERE 1 ORDER BY id LIMIT N;
DELETE FROM repository WHERE 1 ORDER BY id LIMIT N;
COMMIT;

这个应该有效,但我不确定。好像我正在构建一个WTF解决方案。

插入后,我必须选择刚刚保留的代码,以便向用户显示。这是棘手的部分,因为在我的交易完成后我真的不知道如何识别刚刚保留的代码。我当然可以在我的reserved_codes表中添加另一列,保留某种随机令牌,但这看起来更像WTFy。

我最喜欢的解决方案是使用随机数序列,以便我可以在INSERT表中执行reserved_codes次操作。

那么,如何在MySQL中执行这个独特,随机和事务安全的序列?一个想法是在reserved_codes表上进行常规自动增量,并从该数字列中导出随机代码值,但我想知道是否有更好的方法。

更新:我忘了提到有一个相当小的保留代码表是有利的,因为我后来必须再次找到单个代码来更新它们(reserved_codes已经还有几个属性)。因此,让保留表缓慢增长是好的(而不是在预生成的代码上有大量索引)。

1 个答案:

答案 0 :(得分:3)

如果您已有一个存储库表,我只需添加一个用户列,然后运行此查询:

UPDATE repository SET user_id = ? WHERE user_id IS NULL LIMIT N;

之后,您可以再次选择记录。这有两个明显的缺点:

  • 您需要user_id
  • 上的索引
  • 除了将其绑定到用户之外,您不能将表中的代码用于其他任何内容。