2014-02-21 73 views
2

我有一個父表和兩個子表。我們使用mysql的AUTO_INCREMENT來增加主鍵。最近我們決定將父表和子表中的數據存檔到相應的存檔表(存檔表與當前表相同)。此活動的目的是減少當前表格的數據集。因爲我們使用INNO DB,在mysql restart,主鍵開始重用(說ID 2的記錄被歸檔並且隨後mysql重新啓動,'id'2被重用)。當數據現在歸檔時,由於primary key(重新使用)的重複,歸檔表上的完整性約束失敗。System.nanoTime作爲Inno數據庫表上的主鍵

可能的解決方案是停止使用AUTO_INCREMENT。主鍵而不是時代。由於我的應用程序是用java編寫的,因此我決定使用System.nanotime()來生成我的PRIMARY key。這是一個好的解決方案嗎?

本來可以更容易地使用[System.nanoTime() + a random string]來絕對確保密鑰的唯一性。但我不想更改ID字段定義爲BIGINT的生產系統。

任何好主意/建議?

爲了清楚起見,讓我舉另一個例子。 說有三條記錄在藝術家表

藝術家表

ID名稱時間
1 JIM 2010年1月2日
2馬克2013年1月1日
約翰三書1975年1月1日

在時間T1之後,管家進入並且算法決定其將時間歸檔到具有ID3的記錄.S0它將記錄移動到歸檔表

Artist_Archive

ID名稱時間
約翰三書1975年1月1日

注意存檔表的ID是不是AUTO_INCREMENT。這是當前表格的精確副本。這是因爲我想保持子表的存檔邏輯簡單。

在時間T2 mysql重新啓動作爲計劃維護的一部分。 在時間T3,插入新記錄(ID = 3再次)。所以錶快照是

藝術家表

ID NAME TIME
1 JIM 2010年1月2日
2標記2013年1月1日
3彼得1980年1月10日

在時間T4,家政再次開始並決定將時間歸檔至記錄3。這是問題出現的地方。請記住,檔案表已經有一個ID爲3 的條目。它只是拒絕違反約束條件的記錄。

這是我想到使用timestap作爲PK的地方。這確保我永遠不會有重複的PK。

+2

的'id'在服務器重新啓動後重復使用?聽起來像是你的設置錯誤: - /導致重用id的事件序列是什麼? –

+0

是的,同意約阿希姆... AUTO_INCREMENT _should_ be fine –

+0

假設我有一個表'藝術家有'id'(AUTO_INCREMENT)和'name'兩個字段。可以說我插入了一條記錄。 id = 1 name =「jim」。大約一個小時後,數據就被存放在一個存檔表中。數據移動到arhive表時,原始表現在爲空。出於某種原因,mysql重新啓動。重新啓動後插入的下一個數據使用相同的ID(1,'標記)。請記住,我正在使用INNO-DB引擎。 –

回答

0

在以下鏈接的評論部分中,提供了一種解決方法來克服此限制。

https://dev.mysql.com/doc/refman/5.0/en/innodb-auto-increment-handling.html

*由於InnoDB的服務器重啓之後忘記它的最高AUTO_INCREMENT,你可以重新設置它,如果你已經存儲在任何地方它。如果將數據存檔在歸檔表中,然後將其刪除並重新啓動mysql,通常會發生這種情況。當再次存檔時會導致重複的鍵入。 若要解決此您可以創建一個觸發器,它可以確保你的AUTO_INCREMENT比你的檔案表的AUTO_INCREMENT更高:*

delimiter // 
drop trigger if exists trigger_autoinc_tbl; 
CREATE TRIGGER trigger_autoinc_tbl BEFORE INSERT ON tbl 
FOR EACH ROW 
BEGIN 
declare auto_incr1 BIGINT; 
declare auto_incr2 BIGINT; 
SELECT AUTO_INCREMENT INTO auto_incr1 FROM information_schema.TABLES WHERE table_schema=DATABASE() AND table_name='tbl'; 
SELECT AUTO_INCREMENT INTO auto_incr2 FROM information_schema.TABLES WHERE table_schema=DATABASE() AND table_name='tbl_archiv'; 
IF (auto_incr2 > auto_incr1 and NEW.id<auto_incr2) THEN 
SET NEW.id = auto_incr2; 
END IF; 
END;// 
delimiter ; 
0

根據MySQL manual,如果該表爲空,則只將計數器初始化爲1。因此,您可以將最高ID的行保留在表中,迫使MySQL將計數器初始化爲下一個可能的值,即MAX_ID + 1。

+0

更新了說明。看一看。 –