MySQL比较两个表的行哈希

时间:2010-11-10 13:52:32

标签: mysql

我有两个表,一个是主表,另一个表只用于缓存。我不时检查缓存表是否是最新的,并且没有丢失的数据。缓存表使用MyISAM引擎,主表使用InnoDB引擎。

为了更详细地解释它,我举一个例子

缓存表包含以下两个表中的字段

product_categories (cat-id, cat_name, parent_cat_id DEFAULT NULL, parent_cat_name DEFAULT NULL) 

products (product_num, product_name, product_desc, price, image, product_date, availability)

缓存表可能不包含产品,也可能包含产品数据,但可能不准确。

在这个问题Compare two MySQL databases中,一个用于MySQL的Toad工具已经提到了,但我想用PHP来做。

缓存表架构

products_cache | CREATE TABLE `products_cache` (
  `product_num` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `cat_id` int(10) unsigned NOT NULL,
  `parent_cat_id` int(10) unsigned DEFAULT NULL,
  `cat_name` varchar(50) NOT NULL,
  `parent_cat_name` varchar(50) DEFAULT NULL,
  `product_desc` text NOT NULL,
  `price` float(10) unsigned NOT NULL,
  `image` varchar(65) NOT NULL DEFAULT '',
  `product_date` DATE DEFAULT NULL, 
  `availability` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`product_num`),
) ENGINE=MyISAM

可能的解决方案

计算字段的md5并将其存储在缓存表中,然后如果数据发生更改,则下次检查缓存表中的md5。它会正常工作,除非会出现性能问题(我每月运行缓存修复程序,所以我认为我可以妥协)。请对此发表评论。

1 个答案:

答案 0 :(得分:1)

不是每个月为所有数据计算MD5总和,而是使用触发器简单地记录对表的更改。

CREATE TABLE changes (
  table char(30) NOT NULL, -- TODO use an enum for better performance
  id int NOT NULL,
  UNIQUE KEY tableId (table, id),
) 

CREATE TRIGGER insert_products AFTER INSERT ON products FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("products", OLD.id);
CREATE TRIGGER update_products AFTER UPDATE ON products FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("products", OLD.id);
CREATE TRIGGER delete_products AFTER DELETE ON products FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("products", OLD.id);

CREATE TRIGGER insert_product_categories AFTER INSERT ON product_categories FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("product_categories", OLD.id);
CREATE TRIGGER update_product_categories AFTER UPDATE ON product_categories FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("product_categories", OLD.id);
CREATE TRIGGER delete_product_categories AFTER DELETE ON product_categories FOR EACH ROW INSERT IGNORE INTO changes (table, id) values ("product_categories", OLD.id);

-- do this for every involved table

偶尔,您可以更新已更改的行(在夜间批处理作业中)(伪代码):

for {table,id} in query(select table, id from changes) {
  cacheRow = buildCacheRow($table, $id)
  doInTransaction {
    query(replace into product_cache values $cacheRow)
    query(delete from changes where table = $table and id = $id)
  }
}