独特但现实的对象哈希码

Unique, but realistic, object hash code

好的,我正在设计一款软件,可以使一个系统与另一个系统保持同步。问题是原始系统是一些遗留的 DB2 噩梦,我只有只读访问权限,而表没有任何时间戳功能,这意味着无法检测哪些行已更改。

我的想法是只加载所有行(总共我将有大约 60000 行,每半小时同步一次)计算它们的哈希值,同时在我的集成数据库中保留 <ID, hash> 元组。然后,更改检测成为比较哈希和更新目标系统中哈希不匹配或元组完全丢失的记录的工作。 忘了说读源很便宜,更新目标很贵,它是一个有很多后台处理的网络服务,所以我会避免每次都更新。

现在,我的问题是,c# 内置哈希码声称它不适合此目的(相等的哈希并不意味着相等的对象),并且加密哈希看起来像是 256 位以上哈希的大杀伤力。我认为不需要超过 64 位,这将使我在 1010 的情况下发生碰撞的几率为 1010

那么我应该使用什么来生成唯一哈希值?

在您的暂存 SQL 表中,使用 SQL's checksum 函数添加一个 'checksum' 列;

像这样;

更新 mysourcetable set check = checksum(id, field1, field2, field3, field4 ...)

澄清

您提到有一个集成数据库;我的想法是,您可以将数据从 DB2 读入临时数据库,例如 SQL 服务器,您已经在其中存储了 ID/hash 对。如果您从 DB2 中复制了所有数据,而不仅仅是 ID,那么您可以在集成数据库中计算校验和。

另一种选择;使用这样的函数在 C# 中计算哈希;

private readonly System.Security.Cryptography.HashAlgorithm hash = System.Security.Cryptography.SHA1.Create();

public static string CalculateSignature(IEnumerable<object> values)
{
    var sb = new StringBuilder();
    foreach (var value in values)
    {
        string valueToHash = value == null ? ">>null<<" : Convert.ToString(value, CultureInfo.InvariantCulture);
        sb.Append(valueToHash).Append(char.ConvertFromUtf32(0));
    }
    var signature = sb.ToString();
    var bytesToHash = Encoding.UTF8.GetBytes(signature);
    var hashedBytes = hash.ComputeHash(bytesToHash);
    signature = Encoding.UTF8.GetString(hashedBytes);

    return signature;
}

编辑:哈希分析测试

为了展示 SHA1 散列的速度,这里有一个快速测试。在我的开发机器上,我在 176 毫秒内获得了 60,000 个哈希值。 MD5取161

var hash = System.Security.Cryptography.MD5.Create();

var stringtoHash = "3490518cvm90wg89puse5gu3tgu3v0afgmvkldfjgmvvvvvsh,9semc9petgucm9234ucv0[vhd,flhgvzemgu904vq2m0";

var sw = System.Diagnostics.Stopwatch.StartNew();
for(var i = 0; i < 60000; i++)
{
    var bytesToHash = Encoding.UTF8.GetBytes(stringtoHash);
    var hashedBytes = hash.ComputeHash(bytesToHash);
    var signature = Encoding.UTF8.GetString(hashedBytes);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);