在MySQL中,經常使用 AUTO_INCREMENT對主鍵建立自增id的行為,MySQL會自行保證主鍵ID的自增與不重復,使程序不需對ID進行關注。
但是在使用時,MySQL對auto_increment對管理的一些特性可能會導致一些問題,所以需要手工對其進行修改。
修改AUTO_INCREMENT,MySQL只需一條非常簡單的命令:
ALTER TABLE t1 AUTO_INCREMENT = 13;
需要注意,在InnoDB引擎下,如果修改的目標值小於當前數據庫中ID的最大值,則數據庫不會有任何變化。
在MyISAM引擎下,如果修改的目標值小於當前數據庫中ID的最大值,則AUTO_INCREMENT會被設置為該最大值。
在前幾天的工作中,為了保證ID的范圍,對數據庫的AUTO_INCREMENT進行了修改,發現了一些問題。
當在使用ALTER TABLE mytable AUTO_INCREMENT = N修改AUTO_INCREMENT值時,
即使沒有對數據結構進行變化,MySQL服務器(操作的服務器為MySQL5.5,innodb引擎)也會自動建立一個新的表,然后將所有數據復制到新表中,
再將舊表刪除,並重命名新表。
同時,在返回的結果中可以看到,所有的行都被affected。
例如:
mysql> alter table mytable auto_increment=1000000;
Query OK, 512691 rows affected (1 min 4.55 sec)
Records: 512691 Duplicates: 0 Warnings: 0
經過查詢,發現這是在使用ALTER TABLE命令時常見的情況,同時AUTO_INCREMENT在MySQL5.5中不屬於可以跳過重建操作的命令
這就帶來一個問題,在進行修改AUTO_INCREMENT時,整個表會被加鎖,不能修改,影響正常服務。如果表里的數據量非常大,則復制數據會相當的花時間。
同時也可能帶來其他的不可預知的問題,例如硬盤空間被零時表大量占用的問題。
在查詢了MySQL官方文檔與相關資料后發現了一些可以快速解決的方案:
1、如果需要將AUTO_INCREMENT變大,則可以通過很方便的手段進行操作,首先插入一行傀儡數據,插入時將該行數據的ID設置為AUTO_INCREMENT的目標值-1。
進行此操作后,則AUTO_INCREMENT會自動變為你嗦需要設置的目標值。
但是這種方法僅適用於將AUTO_INCREMENT改大的情況,無法將AUTO_INCREMENT改小。
2、如果需要快速的將AUTO_INCREMENT改小,則需要利用innodb的特性。
在InnoDB中,使用的是內存自增計數器,也就是說,AUTO_INCREMENT不會寫入到硬盤中。
每次重啟數據庫服務后,MySQL會自動運行命令
SELECT MAX(ai_col) FROM table_name FOR UPDATE;
以獲取最大的ID,並賦值到AUTO_INCREMENT中作為計數器的新值。
利用這一點,我們就可以快速的修改AUTO_INCREMENT的值:首先刪除所有比目標值大的ID的行,然后重啟數據庫,再使用之前改大的方法設置AUTO_INCREMENT