女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

主鍵不用隨機(jī)字符串用什么?主鍵自增?

dyquk4xk2p3d ? 來(lái)源:江南一點(diǎn)雨 ? 2023-05-09 09:04 ? 次閱讀

主鍵不用隨機(jī)字符串用什么?主鍵自增?主鍵自增就是最佳方案嗎?有沒(méi)有其他坑?今天我們就來(lái)討論下這個(gè)話題。

1. 為什么不用 UUID

經(jīng)過(guò)上篇文章的介紹,我們知道在 MySQL 中,主鍵索引就是聚簇索引,MySQL 表中的數(shù)據(jù)是根據(jù)主鍵值聚集在一起的,聚簇索引是一棵 B+Tree,這棵樹(shù)中的數(shù)據(jù)是有序的。

所以,如果我們使用 UUID 字符串作為主鍵,那么就會(huì)導(dǎo)致每次數(shù)據(jù)插入的時(shí)候,都需要在 B+Tree 中尋找到適合它自己的位置,找到之后就有可能要挪動(dòng)后面的節(jié)點(diǎn)(就像在數(shù)組中插入一條記錄),挪動(dòng)后面的節(jié)點(diǎn),就有可能涉及到頁(yè)分裂,插入效率就會(huì)降低。

另一方面,在非聚簇索引中,葉子結(jié)點(diǎn)保存的是主鍵值,主鍵如果是一個(gè)很長(zhǎng)的 UUID 字符串,就會(huì)占據(jù)較大的存儲(chǔ)空間(相對(duì) int 而言),那么同一個(gè)葉子結(jié)點(diǎn)能夠保存的主鍵值數(shù)量就會(huì)減少,進(jìn)而可能會(huì)導(dǎo)致樹(shù)變高,樹(shù)變高,意味著查詢(xún)的時(shí)候 IO 次數(shù)增加,查詢(xún)效率降低。

基于上面的分析,我們?cè)?MySQL 中盡量不使用 UUID 作為主鍵,不用 UUID,可能會(huì)有小伙伴想到,那我使用主鍵自增行不行?

對(duì)于上面提到的兩個(gè)使用 UUID 作為主鍵的問(wèn)題,使用主鍵自增顯然都可以解決。主鍵自增,每次只需要往樹(shù)的末尾添加就行了,基本上不會(huì)涉及到頁(yè)分裂問(wèn)題;主鍵自增意味著主鍵是數(shù)字,占用的存儲(chǔ)空間相對(duì)來(lái)說(shuō)就比較小,對(duì)非聚簇索引的影響也會(huì)小一些。

那么主鍵自增就是最佳方案嗎?主鍵自增有沒(méi)有一些需要注意的問(wèn)題?

2. 主鍵自增的問(wèn)題

以下內(nèi)容,有一個(gè)共同的大前提,就是我們的表設(shè)置了主鍵自增。

一般來(lái)說(shuō),主鍵自增是沒(méi)有什么問(wèn)題的。但是,如果在高并發(fā)環(huán)境下,就會(huì)有問(wèn)題了。

首先最容易想到的就是在高并發(fā)插入的時(shí)候產(chǎn)生的尾部熱點(diǎn)問(wèn)題,并發(fā)插入時(shí),大家都需要去查詢(xún)這個(gè)值然后計(jì)算出自己的主鍵值,那么主鍵的上界就會(huì)成為熱點(diǎn)數(shù)據(jù),并發(fā)插入時(shí)這里會(huì)產(chǎn)生鎖競(jìng)爭(zhēng)。

為了解決這個(gè)問(wèn)題,我們就需要選擇適合自己的innodb_autoinc_lock_mode。

2.1 數(shù)據(jù)插入的三種形式

首先,我們?cè)谙驍?shù)據(jù)表中插入數(shù)據(jù)的時(shí)候,一般來(lái)說(shuō)有三種不同的形式,分別如下:

insert into user(name) values('javaboy')或者replace into user(name) values('javaboy'),這種沒(méi)有嵌套子查詢(xún)并且能夠確定具體插入多少行的插入叫做simple insert,不過(guò)需要注意的是INSERT ... ON DUPLICATE KEY UPDATE不算是simple insert。

load data或者insert into user select ... from ....,這種都是批量插入,叫做bulk insert,這種批量插入有一個(gè)特點(diǎn)就是插入多少條數(shù)據(jù)在一開(kāi)始是未知的。

insert into user(id,name) values(null,'javaboy'),(null,'江南一點(diǎn)雨'),這種也是批量插入,但是跟第二種又不太一樣,這種里邊包含了一些自動(dòng)生成的值(本案例中的主鍵自增),并且能夠確定一共插入多少行,這種稱(chēng)之為mixed insert,對(duì)于前面第一點(diǎn)提到的INSERT ... ON DUPLICATE KEY UPDATE也算是一種mixed insert。

將數(shù)據(jù)插入分為這三類(lèi),主要是因?yàn)樵谥麈I自增的時(shí)候,鎖的處理方案不同,我們繼續(xù)往下看。

2.2 innodb_autoinc_lock_mode

我們可以通過(guò)控制 innodb_autoinc_lock_mode 變量的值,來(lái)控制在主鍵自增的時(shí)候,MySQL 鎖的處理思路。

innodb_autoinc_lock_mode 變量一共有三個(gè)不同的取值:

0: 這個(gè)表示 traditional,在這種模式下,我們上面提到的三種不同的插入 SQL,對(duì)于自增鎖的處理方案是一致的,都是在插入 SQL 語(yǔ)句開(kāi)始的時(shí)候,獲取到一個(gè)表級(jí)的 AUTO-INC 鎖,然后當(dāng)插入 SQL 執(zhí)行完畢之后,再釋放掉這把鎖,這樣做的好處是可以確保在批量插入的時(shí)候,自增主鍵是連續(xù)的。

1: 這個(gè)表示 consecutive,在這種模式下,對(duì)simple insert(能夠確定具體插入行數(shù)的,對(duì)應(yīng)上面 1、3 兩種情況)做了一些優(yōu)化,由于simple insert插入多少行這個(gè)很好計(jì)算,于是可以一次性生成幾個(gè)連續(xù)的值用在對(duì)應(yīng)的插入 SQL 語(yǔ)句上,這樣就可以提前釋放掉 AUTO-INC 鎖,可以減少鎖等待,提高并發(fā)插入效率。

2: 這個(gè)表示 interleaved,這種情況下不存在 AUTO-INC 鎖,來(lái)一個(gè)處理一個(gè),批量插入的時(shí)候,就有可能出現(xiàn)主鍵雖然自增,但是不連續(xù)的問(wèn)題。

從上面的介紹中小伙伴們可以看到,實(shí)際上第三種,也就是 innodb_autoinc_lock_mode 取值為 2 的情況下,并發(fā)效率是最強(qiáng)的,那么我們是不是就應(yīng)該設(shè)置 innodb_autoinc_lock_mode=2 呢?

這得看情況。

松哥之前寫(xiě)過(guò)一篇文章和小伙伴們介紹 MySQL binlog 日志文件的三種格式:

row:binlog 中記錄的是具體的值而不是原始的 SQL,舉一個(gè)簡(jiǎn)單例子,假設(shè)表中有一個(gè)字段是 UUID,用戶(hù)執(zhí)行的 SQL 是insert into user(username,uuid) values('javaboy',uuid()),那么最終記錄到 binlog 中的 SQL 是insert into user(username,uuid) values('javaboy',‘0212cfa0-de06-11ed-a026-0242ac110004’)。

statement:binlog 中記錄的就是原始的 SQL 了,以 row 中的為例,最終 binlog 中記錄的就是insert into user(username,uuid) values('javaboy',uuid())。

mixed:在這種模式下,MySQL 會(huì)根據(jù)具體的 SQL 語(yǔ)句來(lái)決定日志的形式,也就是在 statement 和 row 之間選擇一種。

對(duì)于這三種不同的模式,很明顯,在主從復(fù)制的時(shí)候,statement 模式可能會(huì)導(dǎo)致主從數(shù)據(jù)不一致,所以現(xiàn)在 MySQL 默認(rèn)的 binlog 格式都是 row。

回到我們的問(wèn)題:

如果 binlog 格式是 row,那么我們就可以設(shè)置 innodb_autoinc_lock_mode 的值為 2,這樣就能盡最大程度保證數(shù)據(jù)并發(fā)插入的能力,同時(shí)不會(huì)發(fā)生主從數(shù)據(jù)不一致的問(wèn)題。

如果 binlog 格式是 statement,那么我們最好設(shè)置 innodb_autoinc_lock_mode 的值為 1,這樣對(duì)于simple insert的并發(fā)插入能力進(jìn)行了提高,批量插入還是先獲取 AUTO-INC 鎖,等插入成功之后再釋放,這樣也能避免主從數(shù)據(jù)不一致,保證數(shù)據(jù)復(fù)制的安全性。

以上兩點(diǎn)主要是針對(duì) InnoDB 存儲(chǔ)引擎,如果是 MyISAM 存儲(chǔ)引擎,都是先獲取 AUTO-INC 鎖,插入完成再釋放,相當(dāng)于 innodb_autoinc_lock_mode 變量的取值對(duì) MyISAM 不生效。

2.3 實(shí)踐

接下來(lái)我們來(lái)通過(guò)一個(gè)簡(jiǎn)單的 SQL 來(lái)和小伙伴們演示一下 innodb_autoinc_lock_mode 不同取值對(duì)應(yīng)不同結(jié)果的情況。

首先,我們可以通過(guò)如下 SQL 查看當(dāng)前 innodb_autoinc_lock_mode 的取值:

97387408-edf9-11ed-90ce-dac502259ad0.png

可以看到,我使用的 8.0.32 這個(gè)版本目前默認(rèn)值是 2。

我先把它改成 0,修改方式就是在/etc/my.cnf文件中添加一行innodb_autoinc_lock_mode=0:

9747ca0c-edf9-11ed-90ce-dac502259ad0.png

改完之后再重啟查看,如下:

976346d8-edf9-11ed-90ce-dac502259ad0.png

可以看到,現(xiàn)在就已經(jīng)改過(guò)來(lái)了。

現(xiàn)在假設(shè)我有如下表:

CREATETABLE`user`(
`id`intunsignedNOTNULLAUTO_INCREMENT,
`username`varchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciDEFAULTNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=100DEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_unicode_ci;

這個(gè)自增是從 100 開(kāi)始計(jì)的,現(xiàn)在假設(shè)我有如下插入 SQL:

insertintouser(id,username)values(1,'javaboy'),(null,'江南一點(diǎn)雨'),(3,'www.javaboy.org'),(null,'lisi');

插入完成之后,我們來(lái)看查詢(xún)結(jié)果:

97767c9e-edf9-11ed-90ce-dac502259ad0.png

按照我們前文的介紹,這個(gè)情況應(yīng)該是可以解釋的通的,我這里不再贅述。

接下來(lái),我把 innodb_autoinc_lock_mode 取值改為 1,如下:

978a2352-edf9-11ed-90ce-dac502259ad0.png

還是上面相同的 SQL,我們?cè)賵?zhí)行一遍。執(zhí)行完成之后結(jié)果也和上文相同。

但是!!!當(dāng)上面的 SQL 執(zhí)行完畢之后,如果我們還想再插入數(shù)據(jù),并且新插入的 ID 不指定值,則我們發(fā)現(xiàn)自動(dòng)生成的 ID 值為 104。這就是因?yàn)槲覀冊(cè)O(shè)置了 innodb_autoinc_lock_mode=1,此時(shí),執(zhí)行simple insert插入的時(shí)候,系統(tǒng)一看我要插入 4 條記錄,就直接給我提前拿了 4 個(gè) ID 出來(lái),分別是 100、101、102 以及 103,結(jié)果該 SQL 實(shí)際上只用了兩個(gè) ID,剩下兩個(gè)沒(méi)用,但是下次插入還是從 104 開(kāi)始了。

3. 小結(jié)

好啦,這就是關(guān)于主鍵自增的一個(gè)小小知識(shí)點(diǎn),小伙伴們一定要根據(jù)實(shí)際情況來(lái)為 innodb_autoinc_lock_mode 屬性取一個(gè)合適的值。?

????????



審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    780

    瀏覽量

    44791
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    849

    瀏覽量

    27499
  • UUID
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    8313
  • INC
    INC
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    5887

原文標(biāo)題:MySQL 主鍵自增,那些奇奇怪怪的坑

文章出處:【微信號(hào):良許Linux,微信公眾號(hào):良許Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    阿里云mysql數(shù)據(jù)庫(kù)怎么設(shè)置主鍵和時(shí)間格式怎么顯示時(shí)分秒?

    `需要將測(cè)試的數(shù)據(jù)保存到阿里云mysql數(shù)據(jù)庫(kù)上,利用NI的數(shù)據(jù)庫(kù)工具包怎么創(chuàng)建表實(shí)現(xiàn)主鍵?還有保存的時(shí)間數(shù)據(jù)只顯示日期,不顯示時(shí)分秒(DB Tools Format Datet
    發(fā)表于 11-13 10:39

    labview向oracle插入數(shù)據(jù),怎樣可以主鍵1?如果不插入主鍵的字段,會(huì)報(bào)插入的數(shù)目與表中的數(shù)據(jù)不相等

    本帖最后由 電子人steve 于 2018-5-23 20:30 編輯 labview向oracle數(shù)據(jù)庫(kù)插入數(shù)據(jù)時(shí),怎樣可以主鍵1啊,服務(wù)器數(shù)據(jù)庫(kù)表中設(shè)置了一個(gè)主鍵,如果不
    發(fā)表于 05-23 18:53

    字符串的表示

    字符串的表示  隨著計(jì)算機(jī)在文字處理與信息管理中的廣泛應(yīng)用, 字符串已成為最常用的數(shù)據(jù)類(lèi)型之一, 許多計(jì)算機(jī)中都提供字符串操作功能, 一些計(jì)算機(jī)還給出讀寫(xiě)字
    發(fā)表于 10-13 17:11 ?3200次閱讀
    <b class='flag-5'>字符串</b>的表示

    python字符串拼接方式了解

    python字符串拼接的方式 在Python的實(shí)際開(kāi)發(fā)中,很多都需要用到字符串拼接,python中字符串拼接有很多,今天總結(jié)一下: +符號(hào)拼接
    發(fā)表于 12-06 10:09 ?1090次閱讀

    指針實(shí)現(xiàn)字符串拷貝的程序和字符型指針變量與字符數(shù)組的區(qū)別說(shuō)明

    字符串是存放在字符數(shù)組中的,對(duì)字符數(shù)組中的字符逐個(gè)處理時(shí),前面介紹的指針與數(shù)組之間的關(guān)系完全適用于字符數(shù)組。通常將
    發(fā)表于 11-05 16:15 ?2次下載
    <b class='flag-5'>用</b>指針實(shí)現(xiàn)<b class='flag-5'>字符串</b>拷貝的程序和<b class='flag-5'>字符</b>型指針變量與<b class='flag-5'>字符</b>數(shù)組的區(qū)別說(shuō)明

    什么是復(fù)制字符串?Python如何復(fù)制字符串

    。 在上一篇文章《你真的知道Python的字符串怎么嗎?》里,我突發(fā)奇想,將字符串跟列表做了比較,然后發(fā)現(xiàn)字符串竟然沒(méi)有復(fù)制的方法。當(dāng)時(shí)沒(méi)有細(xì)想,只說(shuō)要擱置疑問(wèn)。過(guò)后,有好學(xué)的小伙伴
    發(fā)表于 11-25 10:32 ?3159次閱讀

    字符串操作

    labview字符串操作
    發(fā)表于 06-28 15:09 ?2次下載

    一文詳解JavaScript字符串

    JavaScript字符串是原始值。此外,字符串是不可變的。這意味著如果你修改一個(gè)字符串,你總是會(huì)得到一個(gè)新的字符串。原始字符串不會(huì)被改變。
    的頭像 發(fā)表于 12-08 16:36 ?1397次閱讀

    MySQL主鍵一定是連續(xù)的嗎?

    眾所周知,主鍵可以讓聚集索引盡量地保持遞增順序插入,避免了隨機(jī)查詢(xún),從而提高了查詢(xún)效率
    的頭像 發(fā)表于 02-20 18:06 ?911次閱讀

    python字符串有哪些特定方法

    python字符串序列操作也適用于列表和元組。 python字符串還有獨(dú)有方法,即字符串對(duì)象的函數(shù),其他對(duì)象不可調(diào)用,只有字符串對(duì)象可調(diào)用。
    的頭像 發(fā)表于 02-23 15:02 ?890次閱讀

    MySQL主鍵一定是連續(xù)的嗎?

    如果你的業(yè)務(wù)設(shè)計(jì)依賴(lài)于主鍵的連續(xù)性,這個(gè)設(shè)計(jì)假設(shè)主鍵是連續(xù)的。但實(shí)際上,這樣的假設(shè)是錯(cuò)的
    的頭像 發(fā)表于 03-21 16:55 ?772次閱讀

    字符串的相關(guān)知識(shí)

    TCL 中的數(shù)據(jù)類(lèi)型只有一種:字符串。這些字符串可以是字母、數(shù)字、布爾值、標(biāo)點(diǎn)符號(hào)等特殊字符的組合。在某些特殊命令的作用下,字符串可以向其他數(shù)據(jù)類(lèi)型轉(zhuǎn)換。下面將系統(tǒng)的講解或回顧下
    的頭像 發(fā)表于 03-29 11:41 ?1324次閱讀

    MySQL主鍵一定是連續(xù)的嗎?

    如果你的業(yè)務(wù)設(shè)計(jì)依賴(lài)于主鍵的連續(xù)性,這個(gè)設(shè)計(jì)假設(shè)主鍵是連續(xù)的。但實(shí)際上,這樣的假設(shè)是錯(cuò)的
    的頭像 發(fā)表于 06-11 11:35 ?659次閱讀
    MySQL<b class='flag-5'>自</b><b class='flag-5'>增</b><b class='flag-5'>主鍵</b>一定是連續(xù)的嗎?

    labview掃描字符串怎么

    LabVIEW是一種圖形化編程語(yǔ)言,用于開(kāi)發(fā)控制、測(cè)量和監(jiān)控系統(tǒng)。雖然它主要用于工程和科學(xué)領(lǐng)域,但也可以用于處理文本和字符串。 在LabVIEW中,可以使用字符串處理函數(shù)來(lái)掃描字符串。以下是一些常用
    的頭像 發(fā)表于 12-26 16:58 ?2619次閱讀

    labview掃描字符串怎么

    LabVIEW 是一種流程化編程語(yǔ)言和開(kāi)發(fā)環(huán)境,主要用于控制、測(cè)量和監(jiān)測(cè)系統(tǒng)。在 LabVIEW 中,掃描字符串是一項(xiàng)常見(jiàn)的任務(wù),它允許用戶(hù)按照一定的模式從輸入字符串中提取所需的信息。下面我將詳細(xì)
    的頭像 發(fā)表于 12-29 10:12 ?2740次閱讀