Mysql

MariaDB 正在忘記以前的自動增量 ID

  • May 19, 2017

我正在使用MariaDB 5.5.39,如果我從表中刪除所有行,然後在插入另一行之前經過了太多時間,它似乎忘記了自動遞增主鍵的最大 id。這是根據HeidiSQL的架構:

CREATE TABLE `submissionqueue` (
   `SubmissionID` BIGINT(20) NOT NULL AUTO_INCREMENT,
   `JSON` TEXT NULL,
   PRIMARY KEY (`SubmissionID`),
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=354;

原來AUTO_INCREMENT的可能是 1,HeidiSQL 可能只是指示現在創建表的程式碼是什麼。

我將此表用作隊列以保留送出直到批准,其中id列自動遞增。

稍後,處理隊列,使該表為空。當發生新送出時,如果表正常執行,則將新行插入到該表中,並且它會收到一個新的自動增量 ID,該 ID 高於所有先前插入的行的 ID(即使大多數“以前的行”已被刪除)很久以前)。

隨著時間的推移,已從該隊列處理了超過 600,000 行。因此,您希望自動增量 ID 為 600,000。

但是,一段時間以來,自動增量 ID 一直在重置。當我去處理這個隊列時,自動增量 ID 已經從 1 開始。

似乎,當我清空該表時,在添加另一行之前經過了太多時間,MariaDB 忘記了之前在該表中的最大自動增量 ID,而是從 1 開始。

這是一個問題,因為在處理過程中,任何刪除的行都會首先移動到具有完全相同架構的另一個表中。因為自動增量 ID 已經重新開始,所以程序會出錯,因為相對於所有先前處理的行來說,ID 不再是唯一的。

多年來,該程序完美執行,但在某些時候數據庫開始忘記正確的自動 ID,而是從 1 重新開始。

這張桌子,我正在經歷這個,從來沒有被丟棄過。我唯一要做的就是在每次處理隊列時刪除表中的所有行。在此之後,如果我立即插入一行,它將收到正確的自動增量 ID(尊重以前在表中的所有 ID)。但是,再次,如果在插入發生之前經過了太多時間,則增量會重新開始,而不是尊重先前存在的行的自動 ID。

我只是使用普通的舊刪除語句,例如:

delete from tableName where id < 600000

不,這不是 的保證AUTO_INCREMENT。它只保證唯一性。它不能保證刪除的號碼不會再次出現。

在這種情況下(可能還有其他)舊數字將復活:

  1. DELETE最高的序列號。(或TRUNCATEROLLBACK,…)
  2. 重啟mysqld(或者斷電,…)
  3. InnoDB 在打開表時計算下一個 id 用作MAX(id)

您需要另一種機制,例如

CREATE TABLE seq (
   id INT UNSIGNED AUTO_INCREMENT NOT NULL,
   code CHAR(1) NOT NULL,
   PRIMARY KEY(id),
   UNIQUE(code)
) ENGINE=InnoDB;

INSERT INTO seq (code) VALUE ('a');   -- initialize only

To get next number:
INSERT INTO seq (code) VALUE ('a')
   ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id+1);
then use LAST_INSERT_ID() to retrieve the new number: SELECT LAST_INSERT_ID();

筆記:

  • 這允許多個序列,基於code.
  • nums 將單調增加(永不重複,永不減少)。
  • 它將提供連續的數字(沒有間隙)。
  • 它不會回填。
  • 它會在崩潰中倖存下來;從您的表中刪除;等等。
  • 如果您在事務中獲得新編號,則複製可能會生成不按時間順序排列的 id。
  • 如果您在事務之外獲得一個新號碼(自動送出),那麼如果發生某些故障,您可以“燒掉”這個號碼(創建一個間隙)。

(可能有更簡單的東西。)

只有重新啟動才能解釋這一點(據我所知)。因此,正如您所說, “如果在插入發生之前經過了太多時間”,並且此時發生重新啟動,表中沒有行並且引擎再次從 1 開始自動增量(自動增量值僅儲存在記憶體中,不幸的是沒有儲存在任何持久儲存中)-ypercubeᵀᴹ


手冊

只要伺服器執行,InnoDB 就會使用記憶體中的自動增量計數器。當伺服器停止並重新啟動時,InnoDB 重新初始化每個表的計數器,以便第一次插入到表中,如前所述。

這就是 InnoDB 的行為方式,也許您的表以前是 MyISAM?- jkavalik


我想我可以做的一種解決方法(為了保持正確的自動增量 id)是始終保留表中的最高(id)行,然後在下次處理隊列時忽略該行。-朗尼·貝斯特


或者在停止伺服器之前記錄它,然後在開始時設置它ALTER TABLE。請參閱更改自動遞增起始編號?關於堆棧溢出。- 杰納斯


根據對該問題的評論創建的社區 Wiki 答案

引用自:https://dba.stackexchange.com/questions/120889