MySQL MyISAM和Innodb表生成序列

来源:https://www.cnblogs.com/YangJiaXin/archive/2020/03/31/12609240.html
-Advertisement-
Play Games

[toc] 背景 應用端需要生成依次遞增的序列來做流水序號等,方案有1、redis /MySQL SEQUENCE引擎生成序列;2、MySQL中myisam表 replace into方式;3、MySQL中innodb表INSERT ... ON DUPLICATE KEY方式 分析 redis / ...


目錄


背景

應用端需要生成依次遞增的序列來做流水序號等,方案有1、redis /MySQL SEQUENCE引擎生成序列;2、MySQL中myisam表 replace into方式;3、MySQL中innodb表INSERT ... ON DUPLICATE KEY方式

分析

  • redis /MySQL SEQUENCE引擎生成序列,但多個MySQL集群都有生成序列的需求,若出問題,影響範圍大;redis /MySQL SEQUENCE中生成序列也增加了研發修改代碼的成本,新項目可以使用這種方式

  • MySQL中myisam表 replace into 是我們目前使用生成序列的方式(雖然是表鎖,每秒生成的序列也滿足得了需求),使用方式為
CREATE TABLE `test_sequence` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `val` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `val` (`val`)
) ENGINE=MyISAM;

>replace into test_sequence(val) values(99);
Query OK, 1 row affected (0.00 sec)

>select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)

>replace into test_sequence(val) values(99);
Query OK, 2 rows affected (0.00 sec)

>select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

但存在問題:
myisam表非事務存儲引擎,備份存在不一致(恢復還原數據有不一致風險);
myisam也不是crash-safe的;
gtid模式下,同一個事務中不能操作myisam表和innodb表

為什麼不用innodb表replace into方式了?
該方式併發大時,存在發生死鎖的風險


  • MySQL中事務性 innodb表INSERT ... ON DUPLICATE KEY,是crash-safe ,看起來myisam生成序列的存在的問題它都沒有!實際情況了?
    使用方式:
CREATE TABLE `test_sequence2` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `val` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `val` (`val`)
) ENGINE=InnoDB;

00>insert into test_sequence2(val) values(99) on duplicate key update id=id+1;
Query OK, 1 row affected (0.00 sec)

39>select id from test_sequence2;
+---------+
| id |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

22>insert into test_sequence2(val) values(99) on duplicate key update id=id+1;
Query OK, 2 rows affected (0.00 sec)

25>select id from test_sequence2;
+---------+
| id |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)

測試

普通機械磁碟機器
MySQL5.7.16
RR隔離級別
sysbench 自定義sql語句測試tps(每秒生成多少序列)

  • myisam replace into 方式
cd /usr/share/sysbench/tests
sysbench  ./test_myisam.lua  --mysql-host=127.0.0.1  --mysql-port=3701 --mysql-db=test --mysql-user=sysbench --mysql-password=sysbench  --tables=1 --threads=10 --time=30 --report-interval=5  run
  • innodb INSERT ... ON DUPLICATE KEY UPDATE方式
cd /usr/share/sysbench/tests
sysbench  ./test_innodb.lua  --mysql-host=127.0.0.1  --mysql-port=3701 --mysql-db=test --mysql-user=sysbench --mysql-password=sysbench  --tables=1 --threads=10 --time=30 --report-interval=5  run 
myisam replace into innodb insert..on duplicate
1併發線程 124 tps 122 tps
10併發線程 123 tps 121 tps
20併發線程 125 tps 104 tps
30併發線程 127 tps 67 tps
40併發線程 127 tps 33 tps
  • 可見myisam隨著併發線程數的增加,replace into tps保持不變,原因是myisam是表鎖,同一時刻,該表只能寫或者只能讀
  • innodb表隨著併發數的上升,insert..on duplicate tps不升反降,行鎖之前的爭用變大了 造成鎖等待
  • 本次測試機器配置差,結果有些參考性,線上機器配置更好

註意 mysqlslap 壓測innodb表40個併發線程時可能會出現死鎖(RC隔離級別也是),死鎖詳細見最後
為什麼sysbench40 併發線程測試沒有出現過死鎖?難道sysbench併發線程不是同一時刻發出的?_

/usr/local/mysql/bin/mysqlslap  -usysbench -h127.0.0.1 -P3701 -p  --concurrency=40 --iterations=1 --create-schema=test  --query='insert into test_sequence2(val) values(99) on duplicate key update id=id+1;select id from test_sequence2;'

/usr/local/mysql/bin/mysqlslap: Cannot run query insert into test_sequence2(val) values(99) on duplicate key update id=id+1;select id from test_sequence2; ERROR : Deadlock found when trying to get lock; try restarting transaction

結論

  • myisam表 replace into生成序列是穩定的方法,不管併發線程數多少,生成序列速度是穩定的,但myisam表存在缺陷問題
  • innodb表 inert on duplicate 生成序列適合併發線程數少情況,併發線程數多會出現死鎖 生成序列速度下降情況
  • 若要求生成序列的速度快,可用redis /MySQL SEQUENCE方式

死鎖日誌

LATEST DETECTED DEADLOCK
------------------------
2020-02-11 11:03:11 0x7f6a0c643700
*** (1) TRANSACTION:
TRANSACTION 39260727, ACTIVE 1 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 28 lock struct(s), heap size 3520, 26 row lock(s), undo log entries 1
MySQL thread id 460828, OS thread handle 140093451958016, query id 21296424 127.0.0.1 root update
insert into test_sequence2(val) values(99) on duplicate key update id=id+1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 48 page no 4 n bits 72 index val of table `test`.`test_sequence2` trx id 39260727 lock_mode X waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex e3; asc  ;;
 1: len 8; hex 000000000000001a; asc         ;;

*** (2) TRANSACTION:
TRANSACTION 39260729, ACTIVE 1 sec updating or deleting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
29 lock struct(s), heap size 3520, 27 row lock(s), undo log entries 1
MySQL thread id 460835, OS thread handle 140093451155200, query id 21296425 127.0.0.1 root update
insert into test_sequence2(val) values(99) on duplicate key update id=id+1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 48 page no 4 n bits 72 index val of table `test`.`test_sequence2` trx id 39260729 lock_mode X
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex e3; asc  ;;
 1: len 8; hex 000000000000001a; asc         ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 48 page no 3 n bits 168 index PRIMARY of table `test`.`test_sequence2` trx id 39260729 lock_mode X waiting
Record lock, heap no 37 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 8; hex 000000000000001b; asc         ;;
 1: len 6; hex 000002571237; asc    W 7;;
 2: len 7; hex b6000001680110; asc     h  ;;
 3: len 1; hex e3; asc  ;;

*** WE ROLL BACK TRANSACTION (1)

自定義sysbench腳本
less test_myisam/innodb.lua

require("oltp_common")


function thread_init(thread_id)
 drv=sysbench.sql.driver()
 con=drv:connect()
end

function event(thread_id)
local vid1
local dbprefix

con:query('replace into test_sequence(val) values(99)')
con:query('select last_insert_id()')

##innodb insert..on duplicate 語句
#con:query('insert into test_sequence2(val) values(99) on duplicate key update id=id+1')
#con:query('select id from test_sequence2;')

end

function thread_done()
 con:disconnect()
end

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

-Advertisement-
Play Games
更多相關文章
  • 假如有這麼一個數據網關服務服務,客戶端有三種賬號角色(普通用戶、管理員用戶、超級管理員用戶),數據網關針對這三種角色用戶分配不同的數據訪問許可權,那怎麼樣通過IdentityServer4 來實現角色的授權呢?它又是怎樣的一個過程? ...
  • ==耗時8小時左右== 總體設計 ansible playbook目錄結構 入口文件 因為不同的主機配置不同,所以按主機分類設置了3個role NFS服務playbook結構 WEB服務playbook結構 Keepalived+LVS服務playbook結構 執行過程 結果測試 1.查看浮動ip ...
  • 使用方法: 使用示例: ...
  • yum部署zabbix-server4.2 前面寫到過在已有的lnmp環境下源碼部署zabbix-server4.0,這次就寫一篇yum部署zabbix-server+mysql的結合。 環境說明: 1.這裡我所使用的MySQL版本為8版本,系統版本為CentOS7.4系列操作系統 部署MySQL ...
  • 痞子衡前段時間在支持一個i.MXRT1060客戶項目時遇到了LCD顯示有異常亮點的問題,這個問題的定位和排查花了一點時間,整個過程現在回想起來仍覺得有意思。做嵌入式(尤其是軟體)這行主要工作除了寫代碼就是解Bug了,而且很多時候往往是寫代碼容易,解Bug難,所以解Bug能力是衡量一個工程師是否資深的... ...
  • 嵌入式實時操作系統RTOS里實時的衡量指標到底是什麼呢?1s肯定達不到實時,那需要多快呢?100ms,10ms,1ms,還是100us,10us? 還有這些指標是如何測量的呢? 一個關於1553B匯流排消息周期實時性指標的例子 一篇論文中關於1553B匯流排消息周期實時性的指標,從這個例子中可以看出,對 ...
  • 本文(面對的是程式員而非專業資料庫管理員DBA)以MySQL資料庫為研究對象,討論與資料庫索引相關的一些話題。特別需要說明的是,MySQL支持諸多存儲引擎,而各種存儲引擎對索引的支持也各不相同,因此MySQL資料庫支持多種索引類型,如BTree索引,哈希索引,全文索引等等。為了避免混亂,本文將只關註 ...
  • 今天技術討論群里 “一切隨遇而安”同學看書時出現一個疑問,一個MySQL的表中到底可以有多少個欄位?帶著這個疑問,我們展開了探討,也接著討論了一個單欄位長度的問題。 1. 官方文檔說明 官方文檔的內容如下,主要意思是欄位個數限制達不到理想的4096個,且和欄位類型有關,innodb引擎的欄位上限是1 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...