PHP - uniqid("")是一个很好的实用解决方案,可以生成一个独特的顺序密钥服务器端吗?

JDe*_*age 2 php mysql optimization

所有,

我想在注册期间为服务器端生成用户ID.此id应该是顺序的,以允许聚簇索引.显然,它也必须是独一无二的.

我可以uniqid("")在多大程度上用于此目的?我不是在构建Google,我认为2个用户在同一微秒注册的风险接近于nill - 但我没有实际经验可以作为自己的基础.SQL将拒绝重复的id,我可以在我的php代码中有一个循环,在碰撞/数据输入失败时继续发送新的注册条目,但如果碰撞很少,这只是一个很好的方法.

或者,我可以添加一个随机的postcript uniqid("",TRUE),但是如果2个用户在相同的微秒内注册,则键不能再是连续的.

解决我难题的最佳实用方法是什么?我是否想过这个?

谢谢,

JDelage

Cha*_*les 7

uniqid只不过是一个接口microtime(这就是它生成顺序ID的原因),因此,它可以是可预测的并且可以创建重复.

此id应该是顺序的,以允许聚簇索引.显然,它也必须是独一无二的.[...]我是否过度思考这个?

大多数数据库(包括MySQL)都包含事务安全序列生成器. MySQL的实现,AUTO_INCREMENT相当原始,但也很有效.auto-inc主键可以确保唯一性,更重要的是,并不奇怪.

也就是说,只需确保表中的id列是主键即可完全防御重复ID.

  • 如果您在代码中执行此操作而不是让数据库处理它,则无法保证在涉及事务时的合理性.您需要担心锁定,死锁和回滚.如果您让数据库为您处理,您将不必担心任何问题.在数据库之外做自己的标识符是*insanity*.相信我,我继承了一个代码库生成代码端标识符的代码库,处理结果边缘情况是一个彻头彻尾的噩梦. (3认同)
  • 这不是查询的成本,而是设计的成本.您必须获取下一个可用标识符,执行一些操作,然后执行插入操作.如果另一个进程同时运行并且碰巧正在执行相同的操作,那么在执行之前它实际上可能会在插入处成功.这意味着如果您处于事务中,则插入将立即失败并出现重复键错误.然后,您的代码必须清理混乱并尝试获取下一个id以进行插入的另一次尝试.这里唯一的解决方法是*独占表锁*.(继续) (3认同)
  • 所有这些工作*只是为了避免使用数据库的内置,事务安全,保证唯一的序列生成机制?这完全不值得努力.如果您需要标识符来执行密码保存,请将密码字段设置为可空,并使用加密密码执行插入后更新.空密码也可以是一个方便的"您不能登录"标志.(我继承的代码库由于多主复制而自行生成标识符,在MySQL 5.x之前自动递增不能很好地完成复制.) (3认同)
  • 从管理的角度来看,可以禁用这些用户帐户。想一想被网站禁止。或被解雇。存储“帐户处于活动状态”状态的一种方法是仅具有用于此目的的标志。只需重新使用密码字段即可达到相同的效果。毕竟,“ null”密码将始终阻止用户登录。请记住,对于这种“特定”情况,这只是一个方便的事情。 (2认同)

Ahm*_*gle 6

在数据库理论中,假设没有事件发生在同一时间量子,在你的情况下是微秒.许多数据库概念建立在这个假设之上.

我没有听到uniqid顺序请求生成相同的哈希值.因为,它的种子是微秒,并且很可能你的处理器在一微秒内或多或少地执行机器指令,处理两个请求之间有太多的时间(即使它们在单个CPU中同时运行).

如果您认为可能存在512位散列(32个十六进制字符)的冲突,那么您可以构建自己的摘要函数,该函数利用字母表和标点符号中的更多字符,因为正如我之前所说,我们解决了时间种子问题,所有你应该担心的必须是充分利用种子和降低碰撞概率.

如果你想确定,你可以以互斥的方式提供请求,然后在你提出请求之后,你可以向数据库插入一行(假设用户注册,你将用户记录插入到用户表中)和使用PHP函数,mysql_insert_id()然后您可以继续提供其他请求,以便您可以使用最近插入的记录ID作为种子(对于任何两个连续的请求,它将始终不同).

根据要求对最后一段进行澄清: 正如我之前所说,根据服务理论,在数据库中没有任何同时发生的事情.总是,其中一个先服务.因此,您可以在数据库中启动事务.假设您正在注册新用户.你会说INSERT INTO users (username, password) VALUES (?, ?).你去了,你已经插入了一个新用户.当这个数据库查询发生时,你应该实现一个互斥锁(mutex),我不知道它是如何在PHP中完成的.如果您实现了互斥锁,则第二个请求将等到第一个请求完成处理.在数据库上插入行后,您将使用$i = mysql_insert_id()检索刚插入的行的ID!当你说$i+1第二个用户的ID时,它将是唯一的.因为第一个用户是让我们说的300,那么第二个用户就是301.

实际上,数据库自动增量ID始终是唯一的.如果您想为用户提供唯一的字符串哈希,这是一个方法.

  1. 插入用户.(上述查询)
  2. 获取用户的ID $i = mysql_insert_id()
  3. 然后用一些摘要算法加密这个id $d = strrev(md5($i))
  4. 然后将此值放在带有查询unique_idusers表的列上UPDATE user SET unique_id='$d' where id=$i.
  5. 你去,你有每个人的独特字符串.