日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL

發布時間:2023/12/10 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

索引

1.什么是索引

索引是一種數據結構,用于幫助我們在大量數據中快速定位到我們想要查找的數據。
索引最形象的比喻就是圖書的目錄了。注意這里的大量,數據量大了索引才顯得有意義,如果我想要在 [1,2,3,4] 中找到 4 這個數據,直接對全數據檢索也很快,沒有必要費力氣建索引再去查找。

25.為什么引入索引?

為了提高數據查詢的效率。索引對數據庫查詢良好的性能非常關鍵,當表中數據量越來越大,索引對性能的影響越重要。

26.Mysql有哪些常見索引類型?

  • 數據結構角度
    B-Tree索引 哈希索引 R-Tree索引 全文索引
  • 物理存儲角度
    主鍵索引(聚簇索引):葉子節點存的是整行的數據 非主鍵索引(二級索引):葉子節點存的主鍵的值

Mysql索引使用的數據結構主要有BTree索引哈希索引 。對于哈希索引來說,底層的數據結構就是哈希表,因此在絕大多數需求為單條記錄查詢的時候,可以選擇哈希索引,查詢性能最快;其余大部分場景,建議選擇BTree索引。

Mysql的BTree索引使用的是B數中的B+Tree,但對于主要的兩種存儲引擎的實現方式是不同的。

MyISAM: B+Tree葉節點的data域存放的是數據記錄的地址。在索引檢索的時候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址讀取相應的數據記錄。這被稱為“非聚簇索引”。

InnoDB: 其數據文件本身就是索引文件。相比MyISAM,索引文件和數據文件是分離的,其表數據文件本身就是按B+Tree組織的一個索引結構,樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這被稱為“聚簇索引(或聚集索引)”。而其余的索引都作為輔助索引,輔助索引的data域存儲相應記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據主索引搜索時,直接找到key所在的節點即可取出數據;在根據輔助索引查找時,則需要先取出主鍵的值,在走一遍主索引。 因此,在設計表的時候,不建議使用過長的字段作為主鍵,也不建議使用非單調的字段作為主鍵,這樣會造成主索引頻繁分裂。

27.簡述B-Tree與B+樹

B-Tree 是一種自平衡的樹。每個非葉子節點至多有兩個子節點。每個節點都存儲關鍵字值。其左子節點的關鍵字值小于該節點關鍵字值,且右子節點的關鍵字值大于或等于該節點關鍵字值。

B+樹也是是一種自平衡的樹。其基本定義與B樹相同,不同點在于數據只出現在葉子節點,所有葉子節點增加了一個鏈指針,方便進行范圍查詢。

B+樹中間節點不存放數據,所以同樣大小的磁盤頁上可以容納更多節點元素,訪問葉子節點上關聯的數據也具有更好的緩存命中率。并且數據順序排列并且相連,所以便于區間查找和搜索。

B樹每一個節點都包含key和value,查詢效率比B+樹高。

5.B+樹索引

二叉查找樹

首先,讓我們先看一張圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cCKCHaGe-1630242223264)(Mysql.assets/1.jpg)]

從圖中可以看到,我們為 user 表(用戶信息表)建立了一個二叉查找樹的索引。

圖中的圓為二叉查找樹的節點,節點中存儲了鍵(key)和數據(data)。鍵對應 user 表中的 id,數據對應 user 表中的行數據。

二叉查找樹的特點就是任何節點的左子節點的鍵值都小于當前節點的鍵值,右子節點的鍵值都大于當前節點的鍵值。頂端的節點我們稱為根節點,沒有子節點的節點我們稱之為葉節點。

如果我們需要查找 id=12 的用戶信息,利用我們創建的二叉查找樹索引,查找流程如下:

  • 將根節點作為當前節點,把 12 與當前節點的鍵值 10 比較,12 大于 10,接下來我們把當前節點>的右子節點作為當前節點。
  • 繼續把 12 和當前節點的鍵值 13 比較,發現 12 小于 13,把當前節點的左子節點作為當前節點。
  • 把 12 和當前節點的鍵值 12 對比,12 等于 12,滿足條件,我們從當前節點中取出 data,即 id=12,name=xm。

利用二叉查找樹我們只需要 3 次即可找到匹配的數據。如果在表中一條條的查找的話,我們需要 6 次才能找到。

平衡二叉樹

上面我們講解了利用二叉查找樹可以快速的找到數據。但是,如果上面的二叉查找樹是這樣的構造:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f0rJmvb7-1630242223266)(Mysql.assets/2.jpg)]

這個時候可以看到我們的二叉查找樹變成了一個鏈表。如果我們需要查找 id=17 的用戶信息,我們需要查找 7 次,也就相當于全表掃描了。

導致這個現象的原因其實是二叉查找樹變得不平衡了,也就是高度太高了,從而導致查找效率的不穩定。

為了解決這個問題,我們需要保證二叉查找樹一直保持平衡,就需要用到平衡二叉樹了。

平衡二叉樹又稱 AVL 樹,在滿足二叉查找樹特性的基礎上,要求每個節點的左右子樹的高度差不能超過 1。

下面是平衡二叉樹和非平衡二叉樹的對比:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vOoLIUFC-1630242223269)(Mysql.assets/3.jpg)]

由平衡二叉樹的構造我們可以發現第一張圖中的二叉樹其實就是一棵平衡二叉樹。

平衡二叉樹保證了樹的構造是平衡的,當我們插入或刪除數據導致不滿足平衡二叉樹不平衡時,平衡二叉樹會進行調整樹上的節點來保持平衡。具體的調整方式這里就不介紹了。

平衡二叉樹相比于二叉查找樹來說,查找效率更穩定,總體的查找速度也更快。

B 樹

因為內存的易失性。一般情況下,我們都會選擇將 user 表中的數據和索引存儲在磁盤這種外圍設備中。

但是和內存相比,從磁盤中讀取數據的速度會慢上百倍千倍甚至萬倍,所以,我們應當盡量減少從磁盤中讀取數據的次數。

另外,從磁盤中讀取數據時,都是按照磁盤塊來讀取的,并不是一條一條的讀。

如果我們能把盡量多的數據放進磁盤塊中,那一次磁盤讀取操作就會讀取更多數據,那我們查找數據的時間也會大幅度降低。

如果我們用樹這種數據結構作為索引的數據結構,那我們每查找一次數據就需要從磁盤中讀取一個節點,也就是我們說的一個磁盤塊。

我們都知道平衡二叉樹可是每個節點只存儲一個鍵值和數據的。那說明什么?說明每個磁盤塊僅僅存儲一個鍵值和數據!那如果我們要存儲海量的數據呢?

可以想象到二叉樹的節點將會非常多,高度也會極其高,我們查找數據時也會進行很多次磁盤 IO,我們查找數據的效率將會極低!

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VUZ7BwiR-1630242223271)(Mysql.assets/4.jpg)]

為了解決平衡二叉樹的這個弊端,我們應該尋找一種單個節點可以存儲多個鍵值和數據的平衡樹。也就是我們接下來要說的 B 樹。

B 樹(Balance Tree)即為平衡樹的意思,下圖即是一棵 B 樹:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0Dw8kpvs-1630242223272)(Mysql.assets/5.jpg)]

圖中的 p 節點為指向子節點的指針,二叉查找樹和平衡二叉樹其實也有,因為圖的美觀性,被省略了。

圖中的每個節點稱為頁,頁就是我們上面說的磁盤塊,在 MySQL 中數據讀取的基本單位都是頁,所以我們這里叫做頁更符合 MySQL 中索引的底層數據結構。

從上圖可以看出,B 樹相對于平衡二叉樹,每個節點存儲了更多的鍵值(key)和數據(data),并且每個節點擁有更多的子節點,子節點的個數一般稱為階,上述圖中的 B 樹為 3 階 B 樹,高度也會很低。

基于這個特性,B 樹查找數據讀取磁盤的次數將會很少,數據的查找效率也會比平衡二叉樹高很多。

假如我們要查找 id=28 的用戶信息,那么我們在上圖 B 樹中查找的流程如下:

  • 先找到根節點也就是頁 1,判斷 28 在鍵值 17 和 35 之間,那么我們根據頁 1 中的指針 p2 找到頁 3。
  • 將 28 和頁 3 中的鍵值相比較,28 在 26 和 30 之間,我們根據頁 3 中的指針 p2 找到頁 8。
  • 將 28 和頁 8 中的鍵值相比較,發現有匹配的鍵值 28,鍵值 28 對應的用戶信息為(28,bv)。

B+ 樹

B+ 樹是對 B 樹的進一步優化。讓我們先來看下 B+ 樹的結構圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Pc9feq6q-1630242223273)(Mysql.assets/6.jpg)]

BTREE和B+TREE區別是什么?

  • B+Tree 關鍵字的搜索采用的是左閉合區間,之所以采用左閉合區間是因為他要最好的去支持自增id,這也是mysql的設計初衷。即,如果id = 1命中,會繼續往下查找,直到找到葉子節點中的1。
  • B+Tree 根節點和支節點沒有數據區,關鍵字對應的數據只保存在葉子節點中。即只有葉子節點中的關鍵字數據區才會保存真正的數據內容或者是內容的地址。而在B樹種,如果根節點命中,則會直接返回數據。
  • 在B+Tree中,葉子節點不會去保存子節點的引用。
  • B+Tree葉子節點是順序排列的,并且相鄰的節點具有順序引用的關系,如上圖中葉子節點之間有指針相連接。

MySQL為什么最終要去選擇B+Tree?

  • B+Tree是B TREE的變種,B TREE能解決的問題,B+TREE也能夠解決(降低樹的高度,增大節點存儲數據量)
  • B+Tree掃庫和掃表能力更強。如果我們要根據索引去進行數據表的掃描,對B TREE進行掃描,需要把整棵樹遍歷一遍,而B+TREE只需要遍歷他的所有葉子節點即可(葉子節點之間有引用)。
  • B+TREE磁盤讀寫能力更強。他的根節點和支節點不保存數據區,所以根節點和支節點同樣大小的情況下,保存的關鍵字要比B TREE要多。而葉子節點不保存子節點引用,能用于保存更多的關鍵字和數據。所以,B+TREE讀寫一次磁盤加載的關鍵字比B TREE更多。
  • B+Tree排序能力更強。上面的圖中可以看出,B+Tree天然具有排序功能。
  • B+Tree查詢性能穩定。B+Tree數據只保存在葉子節點,每次查詢數據,查詢IO次數一定是穩定的。當然這個每個人的理解都不同,因為在B TREE如果根節點命中直接返回,確實效率更高。

28.簡述Hash索引

哈希索引(hash index)基于哈希表實現,只有精確匹配索引所有列的查詢才有效。對于每一行數據,存儲引擎都會對所有的索引列計算一個哈希碼(hash code),哈希碼是一個較小的值,并且不同鍵值的行計算出來的哈希碼也不一樣。哈希索引將所有的哈希碼存儲在索引中,同時在哈希表中保存指向每個數據行的指針。只有 Memory 引擎顯式支持哈希索引。

哈希索引也有幾個缺點:

  • 索引存放的是hash值,所以僅支持 < = > 以及 IN 操作
  • hash索引無法通過操作索引來排序,因為存放的時候經過hash計算,但是計算的hash值和存放的不一定相等,所以無法排序
  • 不能避免全表掃描,只是由于在memory表里支持非唯一值hash索引,就是不同的索引鍵,可能存在相同的hash值
  • 如果哈希碰撞很多的話,性能也會變得很差
  • 哈希索引無法被用來避免數據的排序操作

29.簡述自適應Hash索引

InnoDB對于頻繁使用的某些索引值,會在內存中基于 B-Tree 索引之上再創鍵一個哈希索引,這也被稱為自適應Hash索引。

30.MySQL B+Tree索引和Hash索引的區別?

Hash 索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節點到枝節點,最后才能訪問到頁節點這樣多次的IO訪問,所以 Hash 索引的查詢效率要遠高于 B-Tree 索引。

可能很多人又有疑問了,既然 Hash 索引的效率要比 B-Tree 高很多,為什么大家不都用 Hash 索引而還要使用 B-Tree 索引呢?任何事物都是有兩面性的,Hash 索引也一樣,雖然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也帶來了很多限制和弊端,主要有以下這些。

(1)Hash 索引僅僅能滿足"=",“IN"和”<=>"查詢,不能使用范圍查詢。

由于 Hash 索引比較的是進行 Hash 運算之后的 Hash 值,所以它只能用于等值的過濾,不能用于基于范圍的過濾,因為經過相應的 Hash 算法處理之后的 Hash 值的大小關系,并不能保證和Hash運算前完全一樣。

(2)Hash 索引無法被用來避免數據的排序操作。

由于 Hash 索引中存放的是經過 Hash 計算之后的 Hash 值,而且Hash值的大小關系并不一定和 Hash 運算前的鍵值完全一樣,所以數據庫無法利用索引的數據來避免任何排序運算;

(3)Hash 索引不能利用部分索引鍵查詢。

對于組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合并后再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。

(4)Hash 索引在任何時候都不能避免表掃描。

前面已經知道,Hash 索引是將索引鍵通過 Hash 運算之后,將 Hash運算結果的 Hash 值和所對應的行指針信息存放于一個 Hash 表中,由于不同索引鍵存在相同 Hash 值,所以即使取滿足某個 Hash 鍵值的數據的記錄條數,也無法從 Hash 索引中直接完成查詢,還是要通過訪問表中的實際數據進行相應的比較,并得到相應的結果。

(5)Hash 索引遇到大量Hash值相等的情況后性能并不一定就會比B-Tree索引高。

對于選擇性比較低的索引鍵,如果創建 Hash 索引,那么將會存在大量記錄指針信息存于同一個 Hash 值相關聯。這樣要定位某一條記錄時就會非常麻煩,會浪費多次表數據的訪問,而造成整體性能低下。

30.簡述聚集索引和稀疏索引

聚集索引按每張表的主鍵構建一棵B+樹,數據庫中的每個搜索鍵值都有一個索引記錄,每個數據頁通過雙向鏈表連接。表數據訪問更快,但表更新代價高。

稀疏索引不會為每個搜索關鍵字創建索引記錄。搜索過程需要,我們首先按索引記錄進行操作,并按順序搜索,直到找到所需的數據為止。

31.簡述輔助索引與回表查詢

輔助索引是非聚集索引,葉子節點不包含記錄的全部數據,包含了一個書簽用來告訴InnoDB哪里可以找到與索引相對應的行數據。

通過輔助索引查詢,先通過書簽查到聚集索引,再根據聚集索引查對應的值,需要兩次,也稱為回表查詢。

32.簡述聯合索引和最左匹配原則

聯合索引是指對表上的多個列的關鍵詞進行索引。

對于聯合索引的查詢,如果精確匹配聯合索引的左邊連續一列或者多列,則mysql會一直向右匹配直到遇到范圍查詢(>,<,between,like)就停止匹配。Mysql會對第一個索引字段數據進行排序,在第一個字段基礎上,再對第二個字段排序。

33.簡述覆蓋索引

覆蓋索引指一個索引包含或覆蓋了所有需要查詢的字段的值,不需要回表查詢,即索引本身存了對應的值。

34.為什么數據庫不用紅黑樹用B+樹

紅黑樹的出度為 2,而 B Tree 的出度一般都非常大。紅黑樹的樹高 h 很明顯比 B Tree 大非常多,IO次數很多,導致會比較慢,因此檢索的次數也就更多。

B+Tree 相比于 B-Tree 更適合外存索引,擁有更大的出度,IO次數較少,檢索效率會更高。

35.基于主鍵索引的查詢和非主鍵索引的查詢有什么區別?

對于select * from 主鍵=XX,基于主鍵的普通查詢僅查找主鍵這棵樹,對于select * from 非主鍵=XX,基于非主鍵的查詢有可能存在回表過程(回到主鍵索引樹搜索的過程稱為回表),因為非主鍵索引葉子節點僅存主鍵值,無整行全部信息。

36.非主鍵索引的查詢一定會回表嗎?

不一定,當查詢語句的要求字段全部命中索引,不用回表查詢。如select 主鍵 from 非主鍵=XX,此時非主鍵索引葉子節點即可拿到主鍵信息,不用回表。

1.分類

  • 首先對mysql鎖進行劃分:
  • 按照鎖的粒度劃分:行鎖、表鎖、頁鎖
  • 按照鎖的使用方式劃分:共享鎖、排它鎖(悲觀鎖的一種實現)
  • 還有兩種思想上的鎖:悲觀鎖、樂觀鎖。
  • InnoDB中有幾種行級鎖類型:Record Lock、Gap Lock、Next
  • key Lock
  • Record Lock:在索引記錄上加鎖
  • Gap Lock:間隙鎖
  • Next-key Lock:Record Lock+Gap Lock
  • 12. 行鎖和表鎖?

    MyISAM和InnoDB存儲引擎使用的鎖:

    • MyISAM采用表級鎖(table-level locking)。

    • InnoDB支持行級鎖(row-level locking)和表級鎖,默認為行級鎖

      表級鎖和行級鎖對比:

    • 表級鎖: Mysql中鎖定 粒度最大 的一種鎖,對當前操作的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。其鎖定粒度最大,觸發鎖沖突的概率最高,并發度最低,MyISAM和 InnoDB引擎都支持表級鎖。

    • 行級鎖: Mysql中鎖定 粒度最小 的一種鎖,只針對當前操作的行進行加鎖。 行級鎖能大大減少數據庫操作的沖突。其加鎖粒度最小,并發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

      InnoDB存儲引擎的鎖的算法有三種:

    • Record lock:單個行記錄上的鎖

    • Gap lock:間隙鎖,鎖定一個范圍,不包括記錄本身

    • Next-key lock:record+gap 鎖定一個范圍,包含記錄本身

    13.行鎖,表鎖和頁鎖

    1.行鎖
    行級鎖是Mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少數據庫操作的沖突。其加鎖粒度最小,但加鎖的開銷也最大。有可能會出現死鎖的情況。 行級鎖按照使用方式分為共享鎖和排他鎖。

    共享鎖用法(S鎖 讀鎖):

    若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。

    select ... lock in share mode;

    共享鎖就是允許多個線程同時獲取一個鎖,一個鎖可以同時被多個線程擁有。

    排它鎖用法(X 鎖 寫鎖):

    若事務T對數據對象A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。

    select ... for update

    排它鎖,也稱作獨占鎖,一個鎖在某一時刻只能被一個線程占有,其它線程必須等待鎖被釋放之后才可能獲取到鎖。

    2.表鎖
    表級鎖是mysql鎖中粒度最大的一種鎖,表示當前的操作對整張表加鎖,資源開銷比行鎖少,不會出現死鎖的情況,但是發生鎖沖突的概率很大。被大部分的mysql引擎支持,MyISAM和InnoDB都支持表級鎖,但是InnoDB默認的是行級鎖。

    共享鎖用法:

    LOCK TABLE table_name [ AS alias_name ] READ

    排它鎖用法:

    LOCK TABLE table_name [AS alias_name][ LOW_PRIORITY ] WRITE

    解鎖用法:

    unlock tables;

    3.頁鎖
    頁級鎖是MySQL中鎖定粒度介于行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但沖突多,行級沖突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。BDB支持頁級鎖

    13.樂觀鎖和悲觀鎖?

    樂觀鎖:每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去更新這個數據。

    悲觀鎖:每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻止,直到這個鎖被釋放。

    數據庫的樂觀鎖需要自己實現,在表里面添加一個 version 字段,每次修改成功值加 1,這樣每次修改的時候先對比一下,自己擁有的 version 和數據庫現在的 version 是否一致,如果不一致就不修改,這樣就實現了樂觀鎖。

    18.MySQL的共享鎖排它鎖

    共享鎖也稱為讀鎖,相互不阻塞,多個客戶在同一時刻可以同時讀取同一個資源而不相互干擾。排他鎖也稱為寫鎖,會阻塞其他的寫鎖和讀鎖,確保在給定時間內只有一個用戶能執行寫入并防止其他用戶讀取正在寫入的同一資源。

    共享鎖又稱為讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務對于同一數據可以共享一把鎖,都能訪問到數據,但是只能讀不能修改。

    排他鎖又稱為寫鎖,簡稱X鎖,顧名思義,排他鎖就是不能與其他所并存,如一個事務獲取了一個數據行的排他鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務是可以對數據就行讀取和修改。

    對于共享鎖大家可能很好理解,就是多個事務只能讀數據不能改數據,對于排他鎖大家的理解可能就有些差別,我當初就犯了一個錯誤,以為排他鎖鎖住一行數據后,其他事務就不能讀取和修改該行數據,其實不是這樣的。排他鎖指的是一個事務在一行數據加上排他鎖后,其他事務不能再在其上加其他的鎖。mysql InnoDB引擎默認的修改數據語句,update,delete,insert都會自動給涉及到的數據加上排他鎖,select語句默認不會加任何鎖類型,如果加排他鎖可以使用select …for update語句,加共享鎖可以使用select … lock in share mode語句。所以加過排他鎖的數據行在其他事務種是不能修改數據的,也不能通過for update和lock in share mode鎖的方式查詢數據,但可以直接通過select …from…查詢數據,因為普通查詢沒有任何鎖機制。

    19.MySQL中的按粒度的鎖分類

    表級鎖: 對當前操作的整張表加鎖,實現簡單,加鎖快,但并發能力低。

    行鎖: 鎖住某一行,如果表存在索引,那么記錄鎖是鎖在索引上的,如果表沒有索引,那么 InnoDB 會創建一個隱藏的聚簇索引加鎖。行級鎖能大大減少數據庫操作的沖突。其加鎖粒度最小,并發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

    Gap 鎖:也稱為間隙鎖: 鎖定一個范圍但不包括記錄本身。其目的是為了防止同一事物的兩次當前讀出現幻讀的情況。

    Next-key Lock: 行鎖+gap鎖。

    20.如何解決數據庫死鎖

  • 預先檢測到死鎖的循環依賴,并立即返回一個錯誤。
  • 當查詢的時間達到鎖等待超時的設定后放棄鎖請求。
  • 其他

    5.簡述事務

    事務內的語句要么全部執行成功,要么全部執行失敗。

    事務滿足如下幾個特性:

    • 原子性(Atomicity):一個事務中的所有操作要么全部完成,要么全部不完成。
    • 一致性(Consistency):事務執行前后數據庫的狀態保存一致。
    • 隔離性(Isolation)多個并發事務對數據庫進行操作,事務間互不干擾。
    • 持久性(Durability)事務執行完畢,對數據的修改是永久的,即使系統故障也不會丟失

    10.數據庫的事務隔離?

    MySQL 的事務隔離是在 MySQL. ini 配置文件里添加的,在文件的最后添加:

    transaction-isolation = REPEATABLE-READ

    可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。

    READ-UNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、臟讀、不可重復讀)。

    READ-COMMITTED:提交讀,一個事務提交后才能被其他事務讀取到(會造成幻讀、不可重復讀)。

    REPEATABLE-READ:可重復讀,默認級別,一個事務執行過程中看到的數據總是和事務啟動時看到的數據是一致的。在這個級別下事務未提交,做出的變更其它事務也看不到。

    保證多次讀取同一個數據時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的數據(會造成幻讀)。

    SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復讀、幻讀。

    臟讀 :表示一個事務能夠讀取另一個事務中還未提交的數據。比如,某個事務嘗試插入記錄 A,此時該事務還未提交,然后另一個事務嘗試讀取到了記錄 A。

    不可重復讀 :是指在一個事務內,多次讀同一數據。

    幻讀 :指同一個事務內多次查詢返回的結果集不一樣。比如同一個事務 A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集里面的數據,同一個記錄的數據內容被修改了,所有數據行的記錄就變多或者變少了。

    1.數據庫的三范式是什么?

    第一范式:強調的是列的原子性,即數據庫表的每一列都是不可分割的原子數據項。

    第二范式:要求實體的屬性完全依賴于主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性。

    第三范式:任何非主屬性不依賴于其它非主屬性。

    2.一張自增表里面總共有 7 條數據,刪除了最后 2 條數據,重啟 MySQL 數據庫,又插入了一條數據,此時 id 是幾?

    表類型如果是 MyISAM ,那 id 就是 8。

    表類型如果是 InnoDB,那 id 就是 6。

    InnoDB 表只會把自增主鍵的最大 id 記錄在內存中,所以重啟之后會導致最大 id 丟失。

    3.如何獲取當前數據庫版本?

    使用 select version() 獲取當前 MySQL 數據庫版本。

    4.說一下 ACID 是什么?

    Atomicity(原子性):一個事務(transaction)中的所有操作,或者全部完成,或者全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被恢復(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。即,事務不可分割、不可約簡。

    Consistency(一致性):在事務開始之前和事務結束以后,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設約束、觸發器、級聯回滾等。

    Isolation(隔離性):數據庫允許多個并發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務并發執行時由于交叉執行而導致數據的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(Serializable)。

    Durability(持久性):事務處理結束后,對數據的修改就是永久的,即便系統故障也不會丟失。

    6.char 和 varchar 的區別是什么?

    char(n) :固定長度類型,比如訂閱 char(10),當你輸入"abc"三個字符的時候,它們占的空間還是 10 個字節,其他 7 個是空字節。

    char 優點:效率高;缺點:占用空間;適用場景:存儲密碼的 md5 值,固定長度的,使用 char 非常合適。

    varchar(n) :可變長度,存儲的值是每個值占用的字節再加上一個用來記錄其長度的字節的長度。

    所以,從空間上考慮 varcahr 比較合適;從效率上考慮 char 比較合適,二者使用需要權衡。

    7.float 和 double 的區別是什么?

    float 最多可以存儲 8 位的十進制數,并在內存中占 4 字節。

    double 最可可以存儲 16 位的十進制數,并在內存中占 8 字節。

    8.MySQL 的內連接、左連接、右連接有什么區別?

    內連接關鍵字:inner join;左連接:left join;右連接:right join。

    內連接是把匹配的關聯數據顯示出來;左連接是左邊的表全部顯示出來,右邊的表顯示出符合條件的數據;右連接正好相反。

    9.怎么驗證 MySQL 的索引是否滿足需求?

    使用 explain 查看 SQL 是如何執行查詢語句的,從而分析你的索引是否滿足需求。

    explain 語法:explain select * from table where type=1。

    11.MySQL 常用的引擎?

    InnoDB 引擎:InnoDB 引擎提供了對數據庫 acid 事務的支持,并且還提供了行級鎖和外鍵的約束,它的設計的目標就是處理大數據容量的數據庫系統。MySQL 運行的時候,InnoDB 會在內存中建立緩沖池,用于緩沖數據和索引。但是該引擎是不支持全文搜索,同時啟動也比較的慢,它是不會保存表的行數的,所以當進行 select count(*) from table 指令的時候,需要進行掃描全表。由于鎖的粒度小,寫操作是不會鎖定全表的,所以在并發度較高的場景下使用會提升效率的。

    MyIASM 引擎:MySQL 的默認引擎,但不提供事務的支持,也不支持行級鎖和外鍵。因此當執行插入和更新語句時,即執行寫操作的時候需要鎖定這個表,所以會導致效率會降低。不過和 InnoDB 不同的是,MyIASM 引擎是保存了表的行數,于是當進行 select count(*) from table 語句時,可以直接的讀取已經保存的值而不需要進行掃描全表。所以,如果表的讀操作遠遠多于寫操作時,并且不需要事務的支持的,可以將 MyIASM 作為數據庫引擎的首選。

    MySQL常見的三種存儲引擎(InnoDB、MyISAM、MEMORY)

    InnoDB:支持事務處理,支持外鍵,支持崩潰修復能力和并發控制。如果需要對事務的完整性要求比較高(比如銀行),要求實現并發控制(比如售票),那選擇InnoDB有很大的優勢。如果需要頻繁的更新、刪除操作的數據庫,也可以選擇InnoDB,因為支持事務的提交(commit)和回滾(rollback)。

    MyISAM:插入數據快,空間和內存使用比較低。如果表主要是用于插入新記錄和讀出記錄,那么選擇MyISAM能實現處理高效率。如果應用的完整性、并發性要求比 較低,也可以使用。

    MEMORY:所有的數據都在內存中,數據的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數據的安全性要求較低,可以選擇MEMOEY。它對表的大小有要求,不能建立太大的表。所以,這類數據庫只使用在相對較小的數據庫表。

    11.的MyISAM與InnoDB

    MyISAM特點

    • 不支持行鎖(MyISAM只有表鎖),讀取時對需要讀到的所有表加鎖,寫入時則對表加排他鎖;
    • 不支持事務
    • 不支持外鍵
    • 不支持崩潰后的安全恢復
    • 在表有讀取查詢的同時,支持往表中插入新紀錄
    • 支持BLOB和TEXT的前500個字符索引,支持全文索引
    • 支持延遲更新索引,極大地提升了寫入性能
    • 對于不會進行修改的表,支持 壓縮表 ,極大地減少了磁盤空間的占用

    InnoDB特點

    • 支持行鎖,采用MVCC來支持高并發,有可能死鎖
    • 支持事務
    • 支持外鍵
    • 支持崩潰后的安全恢復
    • 不支持全文索引

    MyISAM和InnoDB兩者的應用場景:

  • MyISAM管理非事務表。它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那么MyISAM是更好的選擇。
  • InnoDB用于事務處理應用程序,具有眾多特性,包括ACID事務支持。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶并發操作的性能。
  • 但是實際場景中,針對具體問題需要具體分析,一般而言可以遵循以下幾個問題:
    - 數據庫是否有外鍵?
    - 是否需要事務支持?
    - 是否需要全文索引?
    - 數據庫經常使用什么樣的查詢模式?在寫多讀少的應用中還是Innodb插入性能更穩定,在并發情況下也能基本,如果是對讀取速度要求比較快的應用還是選MyISAM。
    - 數據庫的數據有多大? 大尺寸傾向于innodb,因為事務日志,故障恢復。

    14.MySQL 問題排查都有哪些手段?

    使用 show processlist 命令查看當前所有連接信息。

    使用 explain 命令查詢 SQL 語句執行計劃。

    開啟慢查詢日志,查看慢查詢的 SQL。

    15.如何做 MySQL 的性能優化?

    為搜索字段創建索引。

    避免使用 select *,列出需要查詢的字段。

    垂直分割分表。

    選擇正確的存儲引擎。

    16.MySQL的架構

    MySQL可以分為應用層,邏輯層,數據庫引擎層,物理層。

    應用層:負責和客戶端,響應客戶端請求,建立連接,返回數據。

    邏輯層:包括SQK接口,解析器,優化器,Cache與buffer。

    數據庫引擎層:有常見的MyISAM,InnoDB等等。

    物理層:負責文件存儲,日志等等。

    17.執行SQL語言的過程

  • 客戶端首先通過連接器進行身份認證和權限相關
  • 如果是執行查詢語句的時候,會先查詢緩存,但MySQL 8.0 版本后該步驟移除。
  • 沒有命中緩存的話,SQL 語句就會經過解析器,分析語句,包括語法檢查等等。
  • 通過優化器,將用戶的SQL語句按照 MySQL 認為最優的方案去執行。
  • 執行語句,并從存儲引擎返回數據。
  • 21.簡述InnoDB存儲引擎

    InnoDB 是 MySQL 的默認事務型引擎,支持事務,表是基于聚簇索引建立的。支持表級鎖和行級鎖,支持外鍵,適合數據增刪改查都頻繁的情況。

    InnoDB 采用 MVCC 來支持高并發,并且實現了四個標準的隔離級別。其默認級別是 REPEATABLE READ,并通過間隙鎖策略防止幻讀,間隙鎖使 InnoDB 不僅僅鎖定查詢涉及的行,還會對索引中的間隙進行鎖定防止幻行的插入。

    22.簡述MyISAM存儲引擎

    MySQL5.1及之前,MyISAM 是默認存儲引擎。MyISAM不支持事務,Myisam支持表級鎖,不支持行級鎖,表不支持外鍵,該存儲引擎存有表的行數,count運算會更快。適合查詢頻繁,不適合對于增刪改要求高的情況

    23.簡述Memory存儲引擎

    Memory存儲引擎將所有數據都保存在內存,不需要磁盤 IO。支持哈希索引,因此查找速度極快。Memory 表使用表級鎖,因此并發寫入的性能較低。

    37.簡述MySQL使用EXPLAIN 的關鍵字段

    explain關鍵字用于分析sql語句的執行情況,可以通過他進行sql語句的性能分析。

    type:表示連接類型,從好到差的類型排序為

    • system:系統表,數據已經加載到內存里。
    • const:常量連接,通過索引一次就找到。
    • eq_ref:唯一性索引掃描,返回所有匹配某個單獨值的行。
    • ref:非主鍵非唯一索引等值掃描,const或eq_ref改為普通非唯一索引。
    • range:范圍掃描,在索引上掃碼特定范圍內的值。
    • index:索引樹掃描,掃描索引上的全部數據。
    • all:全表掃描。

    key:顯示MySQL實際決定使用的鍵。

    key_len:顯示MySQL決定使用的鍵長度,長度越短越好

    Extra:額外信息

    • Using filesort:MySQL使用外部的索引排序,很慢需要優化。
    • Using temporary:使用了臨時表保存中間結果,很慢需要優化。
    • Using index:使用了覆蓋索引。
    • Using where:使用了where。

    38.簡述MySQL優化流程

  • 通過慢日志定位執行較慢的SQL語句
  • 利用explain對這些關鍵字段進行分析
  • 根據分析結果進行優化
  • 39.簡述MySQL中的日志log

    redo log: 存儲引擎級別的log(InnoDB有,MyISAM沒有),該log關注于事務的恢復.在重啟mysql服務的時候,根據redo log進行重做,從而使事務有持久性。

    undo log:是存儲引擎級別的log(InnoDB有,MyISAM沒有)保證數據的原子性,該log保存了事務發生之前的數據的一個版本,可以用于回滾,是MVCC的重要實現方法之一。

    bin log:數據庫級別的log,關注恢復數據庫的數據。

    40.數據庫中多個事務同時進行可能會出現什么問題?

    • 丟失修改
    • 臟讀:當前事務可以查看到別的事務未提交的數據。
    • 不可重讀:在同一事務中,使用相同的查詢語句,同一數據資源莫名改變了。
    • 幻讀:在同一事務中,使用相同的查詢語句,莫名多出了一些之前不存在的數據,或莫名少了一些原先存在的數據。

    41.什么是MVCC?

    MVCC為多版本并發控制,即同一條記錄在系統中存在多個版本。其存在目的是在保證數據一致性的前提下提供一種高并發的訪問性能。對數據讀寫在不加讀寫鎖的情況下實現互不干擾,從而實現數據庫的隔離性,在事務隔離級別為讀提交和可重復讀中使用到。

    在InnoDB中,事務在開始前會向事務系統申請一個事務ID,該ID是按申請順序嚴格遞增的。每行數據具有多個版本,每次事務更新數據都會生成新的數據版本,而不會直接覆蓋舊的數據版本。數據的行結構中包含多個信息字段。其中實現MVCC的主要涉及最近更改該行數據的事務ID(DB_TRX_ID)和可以找到歷史數據版本的指針(DB_ROLL_PTR)。InnoDB在每個事務開啟瞬間會為其構造一個記錄當前已經開啟但未提交的事務ID的視圖數組。通過比較鏈表中的事務ID與該行數據的值與對應的DB_TRX_ID,并通過DB_ROLL_PTR找到歷史數據的值以及對應的DB_TRX_ID來決定當前版本的數據是否應該被當前事務所見。最終實現在不加鎖的情況下保證數據的一致性。

    42.讀提交和可重復讀都基于MVCC實現,有什么區別?

    在可重復讀級別下,只會在事務開始前創建視圖,事務中后續的查詢共用一個視圖。而讀提交級別下每個語句執行前都會創建新的視圖。因此對于可重復讀,查詢只能看到事務創建前就已經提交的數據。而對于讀提交,查詢能看到每個語句啟動前已經提交的數據。

    43.InnoDB如何保證事務的原子性、持久性和一致性?

    利用undo log保障原子性。該log保存了事務發生之前的數據的一個版本,可以用于回滾,從而保證事務原子性。

    利用redo log保證事務的持久性,該log關注于事務的恢復.在重啟mysql服務的時候,根據redo log進行重做,從而使事務有持久性。

    利用undo log+redo log保障一致性。事務中的執行需要redo log,如果執行失敗,需要undo log 回滾。

    44.MySQL是如何保證主備一致的?

    MySQL通過binlog(二進制日志)實現主備一致。binlog記錄了所有修改了數據庫或可能修改數據庫的語句,而不會記錄select、show這種不會修改數據庫的語句。在備份的過程中,主庫A會有一個專門的線程將主庫A的binlog發送給 備庫B進行備份。其中binlog有三種記錄格式:

  • statement:記錄對數據庫進行修改的語句本身,有可能會記錄一些額外的相關信息。優點是binlog日志量少,IO壓力小,性能較高。缺點是由于記錄的信息相對較少,在不同庫執行時由于上下文的環境不同可能導致主備不一致。
  • row:記錄對數據庫做出修改的語句所影響到的數據行以及對這些行的修改。比如當修改涉及多行數據,會把涉及的每行數據都記錄到binlog。優點是能夠完全的還原或者復制日志被記錄時的操作。缺點是日志量占用空間較大,IO壓力大,性能消耗較大。
  • mixed:混合使用上述兩種模式,一般的語句使用statment方式進行保存,如果遇到一些特殊的函數,則使用row模式進行記錄。MySQL自己會判斷這條SQL語句是否可能引起主備不一致,如果有可能,就用row格式, 否則就用statement格式。但是在生產環境中,一般會使用row模式。
  • 45.redo log與binlog的區別?

  • redo log是InnoDB引擎特有的,只記錄該引擎中表的修改記錄。binlog是MySQL的Server層實現的,會記錄所有引擎對數據庫的修改。
  • redo log是物理日志,記錄的是在具體某個數據頁上做了什么修改;binlog是邏輯日志,記錄的是這個語句的原始邏輯。
  • redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的,binlog文件寫到一定大小后會切換到下一個,并不會覆蓋以前的日志。
  • 46.crash-safe能力是什么?

    InnoDB通過redo log保證即使數據庫發生異常重啟,之前提交的記錄都不會丟失,這個能力稱為crash-safe。

    47.WAL技術是什么?

    WAL的全稱是Write-Ahead Logging,它的關鍵點就是先寫日志,再寫磁盤。事務在提交寫入磁盤前,會先寫到redo log里面去。如果直接寫入磁盤涉及磁盤的隨機I/O訪問,涉及磁盤隨機I/O訪問是非常消耗時間的一個過程,相比之下先寫入redo log,后面再找合適的時機批量刷盤能提升性能。

    48.兩階段提交是什么?

    為了保證binlog和redo log兩份日志的邏輯一致,最終保證恢復到主備數據庫的數據是一致的,采用兩階段提交的機制。

  • 執行器調用存儲引擎接口,存儲引擎將修改更新到內存中后,將修改操作記錄redo log中,此時redo log處于prepare狀態。
  • 存儲引擎告知執行器執行完畢,執行器生成這個操作對應的binlog,并把binlog寫入磁盤。
  • 執行器調用引擎的提交事務接口,引擎把剛剛寫入的redo log改成提交commit狀態,更新完成。
  • 49.只靠binlog可以支持數據庫崩潰恢復嗎?

    不可以。 歷史原因:

  • InnoDB在作為MySQL的插件加入MySQL引擎家族之前,就已經是一個提供了崩潰恢復和事務支持的引擎了。InnoDB接入了MySQL后,發現既然binlog沒有崩潰恢復的能力,那引入InnoDB原有的redo log來保證崩潰恢復能力。 實現原因:
  • binlog沒有記錄數據頁修改的詳細信息,不具備恢復數據頁的能力。binlog記錄著數據行的增刪改,但是不記錄事務對數據頁的改動,這樣細致的改動只記錄在redo log中。當一個事務做增刪改時,其實涉及到的數據頁改動非常細致和復雜,包括行的字段改動以及行頭部以及數據頁頭部的改動,甚至b+tree會因為插入一行而發生若干次頁面分裂,那么事務也會把所有這些改動記錄下來到redo log中。因為數據庫系統進程crash時刻,磁盤上面頁面鏡像可以非常混亂,其中有些頁面含有一些正在運行著的事務的改動,而一些已提交的事務的改動并沒有刷上磁盤。事務恢復過程可以理解為是要把沒有提交的事務的頁面改動都去掉,并把已經提交的事務的頁面改動都加上去這樣一個過程。這些信息,都是binlog中沒有記錄的,只記錄在了存儲引擎的redo log中。
  • 操作寫入binlog可細分為write和fsync兩個過程,write指的就是指把日志寫入到文件系統的page cache,并沒有把數據持久化到磁盤,fsync才是將數據持久化到磁盤的操作。通過參數設置sync_binlog為0的時候,表示每次提交事務都只write,不fsync。此時數據庫崩潰可能導致部分提交的事務以及binlog日志由于沒有持久化而丟失。
  • 50.簡述MySQL主從復制

    MySQL提供主從復制功能,可以方便的實現數據的多處自動備份,不僅能增加數據庫的安全性,還能進行讀寫分離,提升數據庫負載性能。

    主從復制流程:

  • 在事務完成之前,主庫在binlog上記錄這些改變,完成binlog寫入過程后,主庫通知存儲引擎提交事物
  • 從庫將主庫的binlog復制到對應的中繼日志,即開辟一個I/O工作線程,I/O線程在主庫上打開一個普通的連接,然后開始binlog dump process,將這些事件寫入中繼日志。從主庫的binlog中讀取事件,如果已經讀到最新了,線程進入睡眠并等待ma主庫產生新的事件。
  • 讀寫分離:即只在MySQL主庫上寫,只在MySQL從庫上讀,以減少數據庫壓力,提高性能。

    51.緩存

    my.cnf加入以下配置,重啟Mysql開啟查詢緩存

    query_cache_type=1 query_cache_size=600000

    Mysql執行以下命令也可以開啟查詢緩存

    set global query_cache_type=1; set global query_cache_size=600000;

    如上,開啟查詢緩存后在同樣的查詢條件以及數據情況下,會直接在緩存中返回結果。這里的查詢條件包括查詢本身、當前要查詢的數據庫、客戶端協議版本號等一些可能影響結果的信息。因此任何兩個查詢在任何字符上的不同都會導致緩存不命中。此外,如果查詢中包含任何用戶自定義函數、存儲函數、用戶變量、臨時表、Mysql庫中的系統表,其查詢結果也不會被緩存。

    緩存建立之后,Mysql的查詢緩存系統會跟蹤查詢中涉及的每張表,如果這些表(數據或結構)發生變化,那么和這張表相關的所有緩存數據都將失效。

    緩存雖然能夠提升數據庫的查詢性能,但是緩存同時也帶來了額外的開銷,每次查詢后都要做一次緩存操作,失效后還要銷毀。 因此,開啟緩存查詢要謹慎,尤其對于寫密集的應用來說更是如此。如果開啟,要注意合理控制緩存空間大小,一般來說其大小設置為幾十MB比較合適。此外,還可以通過sql_cache和sql_no_cache來控制某個查詢語句是否需要緩存:

    select sql_no_cache count(*) from usr;

    52.大表優化

    當MySQL單表記錄數過大時,數據庫的CRUD性能會明顯下降,一些常見的優化措施如下:

  • 限定數據的范圍: 務必禁止不帶任何限制數據范圍條件的查詢語句。比如:我們當用戶在查詢訂單歷史的時候,我們可以控制在一個月的范圍內。;

  • 讀/寫分離: 經典的數據庫拆分方案,主庫負責寫,從庫負責讀;

  • 緩存: 使用MySQL的緩存,另外對重量級、更新少的數據可以考慮使用應用級別的緩存;

  • 垂直分區:

    根據數據庫里面數據表的相關性進行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。

    簡單來說垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來說大家應該就更容易理解了。

  • 垂直拆分的優點: 可以使得行數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易于維護。

    垂直拆分的缺點: 主鍵會出現冗余,需要管理冗余列,并會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加復雜;

    ? 5. 水平分區:

    保持數據表結構不變,通過某種策略存儲數據分片。這樣每一片數據分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數據量。

    水平拆分是指數據表行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的數據拆成多張表來存放。舉個例子:我們可以將用戶信息表拆分成多個用戶信息表,這樣就可以避免單一表數據量過大對性能造成影響。

    水品拆分可以支持非常大的數據量。需要注意的一點是:分表僅僅是解決了單一表數據過大的問題,但由于表的數據還是在同一臺機器上,其實對于提升MySQL 并發能力沒有什么意義,所以 水品拆分最好分庫

    水平拆分能夠 支持非常大的數據量存儲,應用端改造也少,但 分片事務難以解決 ,跨界點Join 性能較差,邏輯復雜。《Java工程師修煉之道》的作者推薦 盡量不要對數據進行分片,因為拆分會帶來邏輯、部署、運維的各種復雜度 ,一般的數據表在優化得當的情況下支撐千萬以下的數據量是沒有太大問題的。如果實在要分片,盡量選擇客戶端分片架構,這樣可以減少一次和中間件的網絡 I/O。

    下面補充一下數據庫分片的兩種常見方案:

    • 客戶端代理: 分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現。 當當網的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實現。
    • 中間件代理: 在應用和數據中間加了一個代理層。分片邏輯統一維護在中間件服務中。 我們現在談的 Mycat、360的Atlas、網易的DDB等等都是這種架構的實現。

    52.查詢語句不同元素(where、jion、limit、group by、having等等)執行先后順序?

    一個查詢語句同時出現了where,group by,having,order by的時候,執行順序和編寫順序是:

    1.執行where xx對全表數據做篩選,返回第1個結果集。

    2.針對第1個結果集使用group by分組,返回第2個結果集。

    3.針對第2個結果集中的每1組數據執行select xx,有幾組就執行幾次,返回第3個結果集。

    4.針對第3個結集執行having xx進行篩選,返回第4個結果集。

    5.針對第4個結果集排序。

    通過一個順口溜總結下順序:我(W)哥(G)是(SH)偶(O)像。按照執行順序的關鍵詞首字母分別是W(where)->G(Group)->S(Select)->H(Having)->O(Order),對應漢語首字母可以編成容易記憶的順口溜:我(W)哥(G)是(SH)偶(O)像

    53.什么是臨時表,臨時表什么時候刪除?

    什么是臨時表:MySQL用于存儲一些中間結果集的表,臨時表只在當前連接可見,當關閉連接時,Mysql會自動刪除表并釋放所有空間。為什么會產生臨時表:一般是由于復雜的SQL導致臨時表被大量創建

    臨時表分為兩種,一種是內存臨時表,一種是磁盤臨時表。內存臨時表采用的是memory存儲引擎,磁盤臨時表采用的是myisam存儲引擎(磁盤臨時表也可以使用innodb存儲引擎,通過internal_tmp_disk_storage_engine參數來控制使用哪種存儲引擎,從mysql5.7.6之后默認為innodb存儲引擎,之前版本默認為myisam存儲引擎)。分別通過Created_tmp_disk_tables 和 Created_tmp_tables 兩個參數來查看產生了多少磁盤臨時表和所有產生的臨時表(內存和磁盤)。

    內存臨時表空間的大小由兩個參數控制:tmp_table_size 和 max_heap_table_size 。一般來說是通過兩個參數中較小的數來控制內存臨時表空間的最大值,而對于開始在內存中創建的臨時表,后來由于數據太大轉移到磁盤上的臨時表,只由max_heap_table_size參數控制。針對直接在磁盤上產生的臨時表,沒有大小控制。

    下列操作會使用到臨時表:

    • union查詢

    • 對于視圖的操作,比如使用一些TEMPTABLE算法、union或aggregation

    • 子查詢

    • join 包括not in、exist等

    • 查詢產生的派生表

    • 復雜的group by 和 order by

    • Insert select 同一個表,mysql會產生一個臨時表緩存select的行

    • 多個表更新

    • GROUP_CONCAT() 或者 COUNT(DISTINCT) 語句

      Mysql還會阻止內存表空間的使用,直接使用磁盤臨時表:

    • 表中含有BLOB或者TEXT列

    • 使用union或者union all時,select子句有大于512字節的列

    • Show columns或者 desc 表的時候,有LOB或者TEXT

    • GROUP BY 或者 DISTINCT 子句中包含長度大于512字節的列

    54.非關系型數據庫和關系型數據庫區別,優勢比較?

    關系型數據庫和非關系型區別

    關系型數據庫

    關系型數據庫,是指采用了關系模型來組織數據的數據庫,其以行和列的形式存儲數據,以便于用戶理解,關系型數據庫這一系列的行和列被稱為表,一組表組成了數據庫。用戶通過查詢來檢索數據庫中的數據,而查詢是一個用于限定數據庫中某些區域的執行代碼。關系模型可以簡單理解為二維表格模型,而一個關系型數據庫就是由二維表及其之間的關系組成的一個數據組織。

    當前主流的關系型數據庫:
    Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。

    非關系型數據庫

    結構不固定,集合內數據字段可以不一樣,自由度高,可以減少一些時間和空間的開銷。

    四大類型:
    鍵值對存儲(key-value),文檔存儲(document store:mongodb),基于列的數據庫(column-oriented),還有就是圖形數據庫(graph database)

    主流的非關系型數據庫有 NoSql、MongoDB、Cloudant、

    特征:
    1、使用鍵值對存儲數據;
    2、分布式;
    3、一般不支持ACID特性;
    4、非關系型數據庫嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合。

    非關系型數據庫:
    NoSql、Cloudant。
    臨時性鍵值存儲(memcached、Redis)、永久性鍵值存儲(ROMA、Redis)、面向文檔的數據庫(MongoDB、CouchDB)、面向列的數據庫(Cassandra、HBase)

    非關系型數據庫的優勢:
    1、格式靈活:存儲數據的格式可以是key,value形式、文檔形式、圖片形式等等,文檔形式、圖片形式等等,使用靈活,應用場景廣泛,而關系型數據庫則只支持基礎類型。
    2、速度快:nosql可以使用硬盤或者隨機存儲器作為載體,而關系型數據庫只能使用硬盤;
    3、高擴展性,基于鍵值對,數據之間沒有耦合性,所以非常容易水平擴展。
    4、成本低:nosql數據庫部署簡單,基本都是開源軟件。
    5、易于數據的分散,分布式數據庫
    各個數據之間存在關聯是關系型數據庫得名的主要原因,為了進行join處理,關系型數據庫不得不把數據存儲在同一個服務器內,這不利于數據的分散,這也是關系型數據庫并不擅長大數據量的寫入處理的原因。相反NoSQL數據庫原本就不支持Join處理,各個數據都是獨立設計的,很容易把數據分散在多個服務器上,故減少了每個服務器上的數據量,即使要處理大量數據的寫入,也變得更加容易,數據的讀入操作當然也同樣容易。

    缺點:
    1、不提供關系型數據庫對事物的處理。NoSQL數據庫只應用在特定領域,基本上不進行復雜的處理,但它恰恰彌補了之前所列舉的關系型數據庫的不足之處。

    關系型數據庫最典型的數據結構是表,由二維表及其之間的聯系所組成的一個數據組織
    關系型數據庫的優勢:
    1、易于維護:都是使用表結構,格式一致;
    2、使用方便:SQL語言通用,可用于復雜查詢;
    3、復雜操作:支持SQL,可以進行Join等復雜查詢,可用于一個表以及多個表之間非常復雜的查詢。
    \3. 事務支持使得對于安全性能很高的數據訪問要求得以實現。
    \4. 由于以標準化為前提,數據更新的開銷很小(相同的字段基本上都只有一處)

    缺點(不擅長):
    1、讀寫性能比較差,尤其是海量數據的高效率讀寫;
    2、固定的表結構,靈活度稍欠;
    3、高并發讀寫需求,傳統關系型數據庫來說,硬盤I/O是一個很大的瓶頸。

    總結

    以上是生活随笔為你收集整理的MySQL的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。