所以在这个应用程序中,我们有一个简单的auto-increment primary key
的user id
。因为我们不想在客户端公开它,所以我们将使用simple hash
(encryption
不重要,只有obfuscation
)。
所以当一个用户被添加到表中时,我们执行uniqid(). user_id
。这将保证user hash
是足够的random
并且总是unique
。
我的问题是,在插入记录时,我们不知道此时的用户id(不能假设是max(user_id) + 1
),因为可能会提交插入。所以我们正在做一个插入,然后得到last_insert_id then using that for the
user_id ',这增加了一个额外的db查询。那么有没有更好的办法呢?
在实际答案之前,有几件事:在最新版本的MySQL中,使用InnoDB作为默认存储引擎-您总是需要一个整数pk(或著名的auto_increment)。原因主要是性能。要了解更多信息,您可以研究InnoDB集群如何使用PK进行记录以及为什么它如此重要。解决了这个问题后,让我们考虑创建唯一代理键的选项。
选项1
你自己计算,使用PHP和你从MySQL (last_insert_id()
)获得的信息,然后你更新数据库回来。
优点:即使是新手程序员也容易理解,生成简短的代理键。
Cons:对于并发访问来说非常糟糕,您可能会遇到冲突,并且您永远不想使用PHP来计算数据库所需的唯一索引。你不需要这个选项
选项2
为您的查询提供uniqid()
,创建一个AFTER INSERT
触发器,将uniqid()
与auto_increment连接起来。
优点:易于理解,生成简短的代理键。
Cons:要求您创建触发器,实现代码中不直接可见的魔法,这肯定会使继承项目的开发人员在某些时候感到困惑-从经验来看,我敢打赌会发生不好的事情
选项3
使用通用唯一标识符或uuid(也称为GUIDs)。只需提供surrogate_key = UUID()
查询,MySQL就会完成其余的工作。
优点:总是独特的,不需要魔法,容易理解。
Cons: none,除非它占用了36个字符。
选择3
因为我们不想在客户端公开这个
不。
在设计良好的数据库中,用户永远不需要看到主键值。实际上,用户甚至不需要知道主键的存在。
从你的问题来看,似乎你实际上用代理ID替换了正常的自动增量ID列(如果不跳到最后一段)。
尝试用另一个唯一代理ID创建一个列,并在您的前端使用它。你可以保留正常的主id用于关系等。
请记住主键的基本规则之一:
- 主键必须紧凑,包含尽可能少的属性。
整数序列还具有易于使用和实现的优点。根据序列化方法的具体实现,它们还具有快速派生的优点,因为大多数数据库只是将序列号存储在固定位置。这意味着db已经存储了max(id)+1
,并且可以快速自动递增。
我们先执行插入操作,然后获取last_insert_id,然后使用对于theuser_id ',它增加了一个额外的数据库查询。
last_insert_id
实际上不是一个查询,而是在您执行插入查询时在数据库连接中保存的变量。
如果您已经为代理ID设置了第二列,则忽略以上所有内容:
我们先执行插入操作,然后获取last_insert_id,然后使用对于theuser_id ',它添加了一个额外的数据库查询。所以有没有有更好的方法吗?
不,你只能通过查询来获取那个唯一id。
$res = mysql_query('SELECT LAST_INSERT_ID()');
$row = mysql_fetch_array($res);
$lastsurrogateid = $row['surrogate_id'];