MySQL 8 新特性之自增主鍵的持久化

来源:https://www.cnblogs.com/ivictor/archive/2018/05/30/9110994.html
-Advertisement-
Play Games

自增主鍵沒有持久化是個比較早的bug,這點從其在官方bug網站的id號也可看出(https://bugs.mysql.com/bug.php?id=199)。由Peter Zaitsev(現Percona CEO)於2003年提出。歷史悠久且臭名昭著。 首先,直觀的重現下。 雖然id為3的記錄刪除了 ...


自增主鍵沒有持久化是個比較早的bug,這點從其在官方bug網站的id號也可看出(https://bugs.mysql.com/bug.php?id=199)。由Peter Zaitsev(現Percona CEO)於2003年提出。歷史悠久且臭名昭著。 


首先,直觀的重現下。

mysql> create table t1(id int auto_increment primary key);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(null),(null),(null);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
3 rows in set (0.00 sec)

mysql> delete from t1 where id=3;
Query OK, 1 row affected (0.36 sec)

mysql> insert into t1 values(null);
Query OK, 1 row affected (0.35 sec)

mysql> select * from t1;
+----+
| id |
+----+
|  1 |
|  2 |
|  4 |
+----+
3 rows in set (0.01 sec)

 

雖然id為3的記錄刪除了,但再次插入null值時,並沒有重用被刪除的3,而是分配了4。   刪除id為4的記錄,重啟資料庫,重新插入一個null值。  
mysql> delete from t1 where id=4;
# service mysqld restart
mysql> insert into t1 values(null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
3 rows in set (0.00 sec)

 

可以看到,新插入的null值分配的是3,按照重啟前的操作邏輯,此處應該分配5啊。   這就是自增主鍵沒有持久化的bug。究其原因,在於自增主鍵的分配,是由InnoDB數據字典內部一個計數器來決定的,而該計數器只在記憶體中維護,並不會持久化到磁碟中。當資料庫重啟時,該計數器會通過下麵這種方式初始化。
SELECT MAX(ai_col) FROM table_name FOR UPDATE;

 

MySQL 8.0的解決思路   將自增主鍵的計數器持久化到redo log中。每次計數器發生改變,都會將其寫入到redo log中。如果資料庫發生重啟,InnoDB會根據redo log中的計數器信息來初始化其記憶體值。為了儘量減小對系統性能的影響,計數器寫入到redo log中,並不會馬上刷新。具體可參考:https://dev.mysql.com/worklog/task/?id=6204     因自增主鍵沒有持久化而出現問題的常見場景: 1. 業務將自增主鍵作為業務主鍵,同時,業務上又要求主鍵不能重覆。 2. 數據會被歸檔。在歸檔的過程中有可能會產生主鍵衝突。   所以,強烈建議不要使用自增主鍵作為業務主鍵。刨除這兩個場景,其實,自增主鍵沒有持久化的問題並不是很大,遠沒有想象中的”臭名昭著“。   最後,給出一個歸檔場景下的解決方案,   創建一個存儲過程,根據table2(歸檔表)自增主鍵的最大值來初始化table1(線上表)。這個存儲過程可放到init_file參數指定的文件中,該文件中的SQL會在資料庫啟動時執行。
DELIMITER ;;
CREATE PROCEDURE `auto_increment_fromtable2`(IN table1 VARCHAR(255), IN table2 VARCHAR(255))
BEGIN
set @qry = concat('SELECT @max1 := (`id` + 1) FROM `',table1,'` ORDER BY `id` DESC LIMIT 1;');
    prepare stmt from @qry;
execute stmt;
deallocate prepare stmt;
    set @qry = concat('SELECT @max2 := (`id` + 1) FROM `',table2,'` ORDER BY `id` DESC LIMIT 1;');
    prepare stmt from @qry;
execute stmt;
deallocate prepare stmt;
IF @max1 < @max2 THEN
    set @qry = concat('alter table `',table1,'` auto_increment=',@max2);prepare stmt from @qry;execute stmt;deallocate prepare stmt;
SELECT 'updated' as `status`;
else
SELECT 'no update needed' as `status`;
END IF;
END ;;
DELIMITER ;

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 接觸 mongodb 已經有一段時間了,從一開始的不瞭解,到現在已慢慢適應這個nosql領域的佼佼者,還是經歷了不少波折。 在進行資料庫選型的時候,許多人總是喜歡拿 mongodb和mysql、oracle做比較,並總結出一套非常詳盡的分析結果。 但是這種分析往往改變不了管理者(或是架構師)的 ...
  • 1.UPPER和UCASE返回字元串str,根據當前字元集映射(預設是ISO-8859-1 Latin1)把所有的字元改變成大寫。該函數對多位元組是可靠的。2.LOWER和LCASE返回字元串str,根據當前字元集映射(預設是ISO-8859-1 Latin1)把所有的字元改變成小寫。該函數對多位元組是 ...
  • 1.查省SELECT * FROM china WHERE china.Pid=02.查市SELECT * FROM chinaWHERE china.Pid=3300003.查區SELECT * FROM china WHERE china.Pid = 3301004.Mysql腳本 DROP T ...
  • 一. 概述 sql server作為關係型資料庫,需要進行數據存儲, 那在運行中就會不斷的與硬碟進行讀寫交互。如果讀寫不能正確快速的完成,就會出現性能問題以及資料庫損壞問題。下麵講講引起I/O的產生,以及分析優化。 二.sql server 主要磁碟讀寫的行為 2.1 從數據文件(.mdf)里, 讀 ...
  • 1.本地資料庫導入導出1.導出(運行 cmd中操作)exp 用戶名/密碼@資料庫實例名file=本地存放路徑eg: exp jnjp/jnjp@ORCL file=C:/jnjp.dmp 2.導入imp 用戶名/密碼@資料庫實例名file=本地資料庫文件存放路徑full=y ignore=yeg: ...
  • 一、創建表空間create tablespace atp logging datafile 'D:\oracle\oradata\orcl\atp.dbf' size 50m autoextend on next 50m maxsize 20480m extent management local; ...
  • zkServer.sh start //啟動zk進程 zkServer.sh stop //關閉zk進程 zkServer.sh status //查看zk狀態 zkCli.sh //啟動本地zk客戶端 zkCli.sh -server localhost:2181 //啟動遠程zk客戶端 ====... ...
  • MySQL資料庫對大小寫不敏感,如id和ID,select和SELECT.。 1.資料庫 create database <資料庫名> 創建資料庫 use <資料庫名> 連接資料庫 註:use表示當前連接上了哪個資料庫,並不會影響對其他資料庫的訪問 如: use db_1; select * fro ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...