我想我已經找到了解決辦法。一段時間以來,我一直在尋找Percona Server來替換我的MySQL服務器,現在我認爲這是一個很好的理由。
Percona服務器引入了許多新的INFORMATION_SCHEMA表,如INNODB_TABLE_STATS,這在標準MySQL服務器中是不可用的。 當你這樣做:
SELECT rows, modified FROM information_schema.innodb_table_stats WHERE table_schema='db' AND table_name='table'
你得到實際的行數和計數器。該Official documentation說,有關這一領域的以下內容:
如果修改列的值超過「行/ 16」或20億,當innodb_stats_auto_update == 1 我們可以估算的故鄉的的 統計重新計算完成按此值統計。
所以這個計數器每隔一段時間就會包裝一次,但是您可以對行數和計數器進行校驗和,然後在每次修改表格時都會得到一個唯一的校驗和。例如: -
SELECT MD5(CONCAT(rows,'_',modified)) AS checksum FROM information_schema.innodb_table_stats WHERE table_schema='db' AND table_name='table';
我會盡我的服務器升級到Percona的服務器反正所以這個邊界不是我的問題。管理數百個觸發器並向表中添加字段對於此應用程序來說是一大痛苦,因爲它在開發中已經很晚了。
這是PHP函數,我拿出來確保表可以校驗和任何引擎和服務器使用:
function checksum_table($input_tables){
if(!$input_tables) return false; // Sanity check
$tables = (is_array($input_tables)) ? $input_tables : array($input_tables); // Make $tables always an array
$where = "";
$checksum = "";
$found_tables = array();
$tables_indexed = array();
foreach($tables as $table_name){
$tables_indexed[$table_name] = true; // Indexed array for faster searching
if(strstr($table_name,".")){ // If we are passing db.table_name
$table_name_split = explode(".",$table_name);
$where .= "(table_schema='".$table_name_split[0]."' AND table_name='".$table_name_split[1]."') OR ";
}else{
$where .= "(table_schema=DATABASE() AND table_name='".$table_name."') OR ";
}
}
if($where != ""){ // Sanity check
$where = substr($where,0,-4); // Remove the last "OR"
$get_chksum = mysql_query("SELECT table_schema, table_name, rows, modified FROM information_schema.innodb_table_stats WHERE ".$where);
while($row = mysql_fetch_assoc($get_chksum)){
if($tables_indexed[$row[table_name]]){ // Not entirely foolproof, but saves some queries like "SELECT DATABASE()" to find out the current database
$found_tables[$row[table_name]] = true;
}elseif($tables_indexed[$row[table_schema].".".$row[table_name]]){
$found_tables[$row[table_schema].".".$row[table_name]] = true;
}
$checksum .= "_".$row[rows]."_".$row[modified]."_";
}
}
foreach($tables as $table_name){
if(!$found_tables[$table_name]){ // Table is not found in information_schema.innodb_table_stats (Probably not InnoDB table or not using Percona Server)
$get_chksum = mysql_query("CHECKSUM TABLE ".$table_name); // Checksuming the old-fashioned way
$chksum = mysql_fetch_assoc($get_chksum);
$checksum .= "_".$chksum[Checksum]."_";
}
}
$checksum = sprintf("%s",crc32($checksum)); // Using crc32 because it's faster than md5(). Must be returned as string to prevent PHPs signed integer problems.
return $checksum;
}
您可以使用它像這樣:
// checksum a signle table in the current db
$checksum = checksum_table("test_table");
// checksum a signle table in db other than the current
$checksum = checksum_table("other_db.test_table");
// checksum multiple tables at once. It's faster when using Percona server, because all tables are checksummed via one select.
$checksum = checksum_table(array("test_table, "other_db.test_table"));
我希望這可以爲遇到同樣問題的其他人節省一些麻煩。
重複:http://dba.stackexchange.com/questions/9569/fastest-way-to-check-if-innodb-table-has-changed – 2011-12-27 09:35:42
你可能想看看[這個問題/答案]( http://stackoverflow.com/questions/2785429/how-can-i-determine-when-an-innodb-table-was-last-changed)(如果你還沒有這樣做)。 – 2011-12-27 09:36:18
啊,好吧,這也是我的線索,但我不認爲這是同一個網站......對不起,我是新來的。 – Jacket 2011-12-27 09:37:56