替换MySQL的UUID版本1功能?

Eva*_*ski 12 php mysql uuid

上下文

Web应用程序,PHP 5,MySQL 5.0.91

问题

我最近从使用自动递增的整数切换到UUID作为我的一些表的主键.通过MySQL的UUID()函数生成UUID时,它们彼此非常相似:

| uuid                                 |
----------------------------------------
| 1e5988da-afec-11e1-9877-5464f7aa6d24 |
| 408092aa-afad-11e1-9877-5464f7aa6d24 |
  ^------^   ^^
  1      8   11-12
Run Code Online (Sandbox Code Playgroud)

如您所见,只有前8个字符和第11个和第12个字符不同.据我所知,UUID版本1使用时间戳和硬件MAC地址来生成UUID.但是,由于这些相似之处(以及在我的情况下MAC地址永远不会改变的事实),我对使用版本1犹豫不决.此外,如果MAC地址永远不会改变,大多数UUID都是无用的并且浪费空间.

我的自定义UUID功能

作为一个实验,我用PHP编写了一个自定义UUID生成器:

public static function GenerateUUID()
{
    return
    substr(sha1(Account::GetUsername() . Account::GetUserID()), 18, 8) . "-" .
    substr(md5(time()), rand() % 28, 4) . "-" . 
    substr(md5(date("Y")), rand() % 28, 4) . "-" . 
    substr(sha1(rand()), 20, 4) . "-" . 
    substr(sha1(rand() % PHP_INT_MAX), 17, 12);
}
Run Code Online (Sandbox Code Playgroud)

结果样本:

| uuid                                 |
----------------------------------------
| 574d18c2-5080-bac9-5597-45435f363ea1 |
| 574d18c2-30d4-8b5b-4ffd-001744d3d287 |
Run Code Online (Sandbox Code Playgroud)

这里,前8个字符对于同一用户是相同的.这是有意的,但不是必需的.

问题

是否有首选/推荐的方法在MySQL查询中生成版本4或版本5 UUID ?

如果没有,是否可以在PHP(如上所述)中生成不符合规范的自定义UUID?

限制

  • 我正在使用具有命令行访问权限的共享主机方案,但无法修改现有的MySQL安装.
  • 我宁愿避免使用第三方软件包/库.

笔记

  • 我不会也不会执行需要包含MAC地址的GUID的合并,同步或其他操作.这不是问题所在.

col*_*fix 11

您担心"大多数UUID无用且浪费空间"是数据类型大小所固有的.您将无法在数据库中拥有尽可能多的条目,因为16字节的理论限制允许.

实际上,如果您将UUID用作表ID,则V1 UUID比V4更合适 - 因为它使用MAC地址和时间戳来防止冲突.在V4中没有这样的机制,虽然实际上你不需要太担心冲突:)如果你需要你的UUID是不可预测的,你应该使用V4 UUID而不是V1.

另外,请注意,组合例如4x4字节随机值可能与创建16字节随机值不同.与加密和随机性一样:我不愿意实现你自己的UUID :: V4例程.

如果安装在您的计算机上,您可以使用该php-uuid程序包.

可以在此处找到示例代码(可以在您的应用程序中使用):http: //rommelsantor.com/clog/2012/02/23/generate-uuid-in-php/

像这样使用它:

$uuid = uuid_create(1);
Run Code Online (Sandbox Code Playgroud)

能够在其Web服务器上安装软件包的用户可以安装所需的软件包,例如:(此处为ubuntu)

apt-get install php5-dev uuid-dev
pecl install uuid
Run Code Online (Sandbox Code Playgroud)


sta*_*cke 4

欣赏拥有“相似的部分”实际上是一个相当好的主意。它将允许您利用 MAC 地址来识别“我的哪台服务器生成了此 UUID?”...这在远程位置之间迁移数据时非常有用。您甚至可以通过这种方式执行“这是我的测试数据”和“这是我的生产数据”。

PHP 拥有大量 UUID 生成器库。

这是 PECL/PEAR 的一个东西(我从未使用过它):

http://pecl.php.net/package/uuid

来自 CakePHP 框架:

http://api.cakephp.org/class/string#method-Stringuuid(蛋糕2.x) http://api13.cakephp.org/class/string#method-Stringuuid(蛋糕1.3)

最后一个生成器选项:

考虑使用 Linux 命令行uuid程序,该程序具有-v版本控制标志和相关选项,并使用它来提供数据库。这有点低效,但至少您不必编写自己的生成器函数。

http://linux.die.net/man/1/uuid - 手册页

uuidDebian 包)

我注意到,对于命名空间版本,您将生成大量“长人名”以转换为 uuid。只要不和他们发生冲突,可能会很甜蜜。例如,使用电子邮件地址注册的用户...获取该电子邮件地址的 v5 uuid...您总会找到那个人!它似乎每次都会吐出相同的 UUID,并且 UUID 将代表 bob@bob.com 与 example.com 作为成员的唯一关系。

uuid -v5 ns:URL "http://example.com/member/bob@bob.com/"

评论:

另外,UUID,您存储它们的方式,是 CHAR(36) 吗?一旦比较运算符启动,您可能会后悔。

Postgres 会将 UUID 视为 128 位值(并且可能会执行优化的二进制操作),而 MYSQL 的 CHAR(36) 解决方案则将 36 字节 = 288 位 ANSI 或 576 位 UTF8 加减位/字节视为 Office -keeping(并且可能执行速度慢得多的多字节字符逐多字节字符字符串例程)。

实际上,我已经对 MySQL 加 UUID 的问题进行了很多考虑...我的结论是,您需要编写一个存储函数,将十六进制表示形式转换为二进制表示形式以进行存储,这将使所有“select”语句都需要转换回十六进制表示形式...谁知道其中的效率如何...所以最后只需切换到 Postgres。XD

如果您确实想切换到 Postgres,请在现有服务器(如果它们是生产服务器)上安装它时务必小心。就像...在实际进行迁移之前创建一个克隆来测试迁移过程。我以某种方式设法杀死了我的系统,因为“安装这个软件包将删除大量重要的其他软件包”(我不知道安装程序是如何做出这些决定的)。

或者,如果您准备最终付给他们很多钱来操作数据库,那么可以使用 Microsoft SQL 来获得其 GUID 等效项...

目前使用 UUID 和 MySQL 往往不是一个好主意。

  • 您应该将 UUID 存储为 BINARY(16) - 我从未尝试过在 MySQL 中使用 UUID 列作为主键,但我认为它可以有效地处理二进制键。令人烦恼的是,这意味着将“uuid()”的输出十六进制解析为二进制,例如[执行此操作的函数](http://forums.mysql.com/read.php?98,49626,51650#msg-51650) (2认同)
  • 您可以使用 `uuid=UNHEX(REPLACE(?,"-",""))` 作为将字符串转换为二进制版本的方法。无需在那里编写存储过程。 (2认同)