如何對MySQL中的大表進行數據歸檔


使用MySQL的過程,經常會遇到一個問題,比如說某張”log”表,用於保存某種記錄,隨着時間的不斷的累積數據,但是只有最新的一段時間的數據是有用的;這個時候會遇到性能和容量的瓶頸,需要將表中的歷史數據進行歸檔。

下面描述一種典型的做法:

比如說表結構如下:

CREATE TABLE `history` (
  `id` int(11) NOT NULL,
  `value` text,
  `addtime` timestamp default current_timestamp,
  PRIMARY KEY (`id`),
  index idx_addtime(`addtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

 

這張表中保存有2012年2013年兩年的數據,現在需要將2012年的數據備份歸檔起來,但是2013年年初的數據還需要被查詢,因此不能簡單的進行如下的動作:

create table history_tmp like history;
rename table history to history_2012,history_tmp to history;

 

需要在新表中保留2013年年初的數據,可以參照下面的流程進行:

create table history_tmp like history;
maxid=select max(id) from history;
minid=select id from history where addtime>"2013-01-01 00:00" order by addtime asc limit 1;
last=0;
set autocommit=1;
for(i=minid;i<maxid+1000;i+=1000)
{
  insert into history_tmp select * from history where id>=last and id<i lock in share mode;
  last=i;
}
begin;
lock table history_tmp write,history write;
maxid=select max(id) from history;
insert into history_tmp select * from history where id>=last and id<=maxid;
alter table history rename to history_2012;
alter table history_tmp rename to history;
unlock tables;
commit;

 

說明:

  1. 使用alter table xx rename to xx,而不是rename是因為mysql的一個bug, bug地址,直接rename會出現”ERROR 1192 (HY000): Can’t execute the given command because you have active locked tables or an active transaction”錯誤.
  2. 需要使用lock history write來防止新的寫入。
  3. 這個方式是假設這個表在有插入和查詢操作,如果有update、delete操作可以通過類似OSC的算法使用trigger來實現。
  4. 不能直接使用insert select where id>minid這種方式,因為這樣會導致slave的延遲,而且遲遲不能提交的事務會導致undo log無法purge。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM