我已经有一段时间陷入这种困境,但找不到任何提示,尽管似乎有人已经做到了。
我需要用加密安全(即非连续!)ID 替换顺序 AUTO_INCREMENT(或等效)主键,但同时我想保持顺序 PK 的性能优势:保证未使用的下一个 ID,聚类性等
一个简单的方法似乎是实现一个密码伪随机置换生成器,以将 2^N 空间唯一地映射到 2^N,而不会发生冲突并使用初始化向量 (IV)。
虽然这可以在外部实现,但这确实需要存储和原子访问状态(排列位置或最后一个 id),这意味着在外部实现将非常低效(相当于运行后续的 UPDATE table SET crypto_id = FN_CRYPTO(autoincrement_id) WHERE autoincrement_id=LAST_INSERT_ID()
用于每个 INSERT
)。
您是否知道在商业用途的数据库中有上述任何此类实现?
最佳答案
While this could be implemented externally, this does need to store and atomically access state (the permutation position or last id), which means implementing externally would be grossly inefficient (it's the equivalent of running a subsequent
UPDATE table SET crypto_id = FN_CRYPTO(autoincrement_id) WHERE autoincrement_id=LAST_INSERT_ID()
您可以使用生成的/虚拟的列来避免为每个插入运行建议的更新:
-- pseudocode
CREATE TABLE tab(
autoincrement_id INT AUTO_INCREMENT,
crypto_id <type> GENERATED ALWAYS AS (FN_CRYPTO(autoincrement_id)) STORED
);
-- SQL Server example, SHA function is an example and should be replaced
CREATE TABLE tab(
autoincrement_id INT IDENTITY(1,1),
crypto_id AS (HASHBYTES('SHA2_256',CAST(autoincrement_id AS NVARCHAR(MAX)))) PERSISTED
);
更多信息:
Dinu 编辑
如果您使用 SHA,请不要忘记将 secret 盐连接到 autoincrement_id
;或者,您可以使用即 AES128 使用 secret 密码和 IV 加密 autoincrement_id
。
另外值得注意:任何有权访问表 DDL 的数据库用户都可以访问您的 secret 盐/ key /iv。如果您担心这一点,您可以使用参数化存储过程,即 FN_CRYPTO(id,key,iv)
,并将它们与每个插入一起发送。
要在应用端检索 crypto_id
而无需后续查询,您需要在应用端复制加密函数以在返回的 autoincrement_id
上运行。注意:如果使用 autoincrement_id
作为 AES128 的字节数组,请非常注意字节顺序,它可能与 DB 和应用程序端不同。唯一的选择是使用 mssql 的 OUTPUT
语法,但这是特定于 mssql 的,它需要运行 ExecuteScalar
API 而不是 ExecuteNonQuery
。
关于sql - 生成加密安全 ID 而不是顺序身份/自动递增,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57085075/