【问题标题】:Mysql – Detecting changes in data with a hash function over a part of tableMysql – 使用散列函数检测部分表的数据变化
【发布时间】:2011-03-07 09:19:25
【问题描述】:

我需要对表中的某些数据生成单个哈希

CREATE TABLE Table1
(
       F1             INT          UNSIGNED NOT NULL AUTO_INCREMENT,
       F2              INT          default     NULL,
       F3               Varchar(50)  default     NULL,
      ..
       FN              INT          default     NULL,
       PRIMARY KEY (F1)
);

即F1, F3,FN 其中 F2=10

SELECT md5(CONCAT_WS('#',F1,F3,FN)) FROM Tabe1 WHERE F2=10

为表中的每一行提供一个哈希。

问题

1) 如何获得整个表的单个哈希?

2) 使用 MD5、SHA1、SHA 或任何其他算法的快速散列算法是什么?

编辑:

已使用 Mysql 4.1 - 它确实支持触发器

【问题讨论】:

  • 为什么需要这些哈希值?可能有比散列所有数据更好的方法来实现您的需求。
  • @Ben - 哈希用于检测表中的数据变化
  • 他们为什么不使用触发器? dev.mysql.com/doc/refman/5.0/en/triggers.html
  • Charles 是正确的,在非常宽的表上计算 rowhash 可以大大加快检测更改的过程。我来这里是为了弄清楚如何在 MySQL 中实现这一点。我通常在 SQL Server 中完成此操作。

标签: mysql hash md5 sha1


【解决方案1】:

1)

SELECT MD5( GROUP_CONCAT( CONCAT_WS('#',F1,F3,FN) SEPARATOR '##' ) ) FROM Table1

2) 速度并不重要,因为一个函数只需要运行一次,并且所有哈希函数都足够快

【讨论】:

  • 是否可以选择所有列而不是列出每一列?
  • @Stefan - 使用动态 sql 和信息架构。
【解决方案2】:

我会使用MySQL Trigger 来检测插入、删除、更新等方面的更改。

【讨论】:

    【解决方案3】:

    至于速度,你应该试试。这取决于功能的实现方式。

    但是,您可能会发现速度差异很小。您引用的散列函数都比普通磁盘可以喷出的要快,所以问题并不是真正的“什么散列函数会使代码运行得最快?”但是“什么哈希函数会让 CPU 在等待来自磁盘的数据时最空闲?”。

    在主频为 2.4 GHz(64 位模式)的 Intel Core2 Q6600 上,使用我自己的 C 实现散列函数,我得到以下散列速度:

    • MD5:411 MB/秒
    • SHA-1:336 MB/秒
    • SHA-256:145 MB/秒
    • SHA-512:185 MB/秒

    这仅使用一个核心。我的硬盘最高速度约为 100 MB/s,因此可以说即使使用 SHA-256,散列过程使用的机器 CPU 功率也不会超过 17%。当然,没有什么能保证 MySQL 使用的实现会那么快,这就是你应该尝试的原因。此外,在 32 位模式下,SHA-512 性能下降不少。

    从密码学上讲,MD5 和 SHA-1 中发现了(严重的)弱点,因此如果您在与安全相关的环境中工作(即,即使有人可以选择某些更改,您也想检测更改,并且宁愿您不检测到上述更改),您应该坚持使用 SHA-256 或 SHA-512,据我们所知,它们足够强大。不过,MD5 和 SHA-1 在非安全情况下仍然可以使用。

    【讨论】:

      【解决方案4】:

      虽然这个帖子很旧,但也许这就是你需要的: http://dev.mysql.com/doc/refman/5.0/en/checksum-table.html

      【讨论】:

        【解决方案5】:

        参见 BIT_XOR: http://dev.mysql.com/doc/refman/5.6/en/group-by-functions.html “返回 expr 中所有位的按位异或。计算以 64 位 (BIGINT) 精度执行。如果没有匹配的行,此函数返回 0。” 有关使用示例,请查看 pt-table-sync。

        【讨论】:

          【解决方案6】:

          如果出于任何原因您不能使用触发器,另一种方法是使用 CONCAT 选项,例如:

          SELECT MD5( GROUP_CONCAT( CONCAT_WS('',F1,F3,FN) SEPARATOR ',' ) ) FROM Table1;
          

          但请注意,如果表有数据分配,查询会很慢!如果可能,请尝试从 CONCACT 中排除不必要的列。

          还要注意默认情况下 MySQL Max CONCACT 是 1024,可能需要先运行以下查询来更改它:

          SET group_concact_max_len = 18446744073709547520;
          

          请注意,18446744073709547520 是最大值,您可以使用其他值!

          【讨论】:

          • 你能不能运行:SELECT MD5( GROUP_CONCAT(MD5( CONCAT_WS('',F1,F3,FN) SEPARATOR ',')))) FROM Table1 对于那些有大表行(超过 32 个字符)的人,以进一步降低达到 group_concact_max_len 限制的可能性?应该允许大约 558,992,240,000,000,000 行 (18446744073709547520 / 33)。
          • 请注意,CONCAT_WS 会跳过空列,因此如果您的表有空列,这将为行生成相同的行哈希:null,2,null2, null, nullnull, null, 2,这可能会导致更多问题.要解决此问题,您需要使用 COALESCE([column name], 'NULL') 包装每一列
          猜你喜欢
          • 2010-09-09
          • 1970-01-01
          • 1970-01-01
          • 2010-10-22
          • 2011-12-03
          • 2015-08-14
          • 1970-01-01
          • 2010-10-19
          • 2015-02-13
          相关资源
          最近更新 更多