我有两个表,一个是主表,另一个表只用于缓存。我不时检查缓存表是否是最新的,并且没有丢失的数据。缓存表使用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。它会正常工作,除非会出现性能问题(我每月运行缓存修复程序,所以我认为我可以妥协)。请对此发表评论。
答案 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)
}
}