MySQL 筆記整理(6) --全局鎖和表鎖:給表加個欄位怎麼有這麼多阻礙

来源:https://www.cnblogs.com/dogtwo0214/archive/2019/03/02/10457717.html
-Advertisement-
Play Games

筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 6) --全局鎖和表鎖:給表加個欄位怎麼有這麼多阻礙 資料庫鎖設計的初衷是處理併發問題。作為多用戶共用的資源,當出現併發訪問的時候,資料庫需要合理地控制資源的訪問規則。而鎖就是用來實現這些訪問規則的重要結構。根據加鎖的範圍,MySQL裡面的鎖大 ...


筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》

6) --全局鎖和表鎖:給表加個欄位怎麼有這麼多阻礙

  資料庫鎖設計的初衷是處理併發問題。作為多用戶共用的資源,當出現併發訪問的時候,資料庫需要合理地控制資源的訪問規則。而鎖就是用來實現這些訪問規則的重要結構。根據加鎖的範圍,MySQL裡面的鎖大致可以分為全局鎖,表級鎖和行鎖三類。這篇筆記主要包含全局鎖和表級鎖。行鎖的內容會在之後再進行分享。

全局鎖:

  全局鎖就是對整個資料庫實例加鎖。可以通過命令 Flush tables with read lock (FTWRL)對全局進行加鎖。使用全局鎖後,其他線程的以下語句會被阻塞:數據更新語句(增刪改),數據定義語句(包括建表,修改表結構等)和更新類事務的提交語句。

  全局鎖的典型使用場景是,做全庫邏輯備份。但如果你直接用上面的FTWRL去進行備份,會讓整庫都處於只讀狀態,這光想想就覺得危險。如果你在主庫上備份,那麼在備份期間都不能執行更新,業務基本停擺;如果你在從庫上備份,那麼備份期間從庫不能執行從主庫同步過來的binlog,會導致主從延遲。那麼不加鎖備份資料庫可以嗎?答案是不可以的,比如你有兩張表,餘額表和商品表。如果不加鎖,在備份期間時先備份餘額表,再備份商品表會出現什麼情況呢?假設在這兩張表備份的間隔時間內進行了數據更新,則餘額表數據在備份表中沒有減少,但是商品表在備份表中的數據卻減少了,造成了邏輯上的數據不一致問題。當然這兩張表的備份順序顛倒過來也是一樣會有這個問題。

  官方自帶的邏輯備份工具是mysqldump.當mysqldump使用參數-single-transaction時,備份數據之前會啟動一個事務,來確保拿到一致性視圖。而由於MVCC(多版本併發控制)的支持,這個過程中數據是可以正常更新的。

  至此,你可能會有個疑問,為什麼有了上述這個功能,還需要FTWRL呢?此處有個細節是 可重覆讀是很好,但並不是所有的MySQL引擎支持這個隔離級別的。(如MyISAM這種不支持事務的引擎,就需要執行FTWRL命令了。)所以,single-transaction方法只適用於所有的表使用事務引擎的庫。

  既然要保證備份時全庫只讀,為什麼不使用set global readonly = true的方式呢? 不建議使用這種方式有以下兩方面原因:

  • 在有些系統中,readonly的值會被用來處理其他邏輯。
  • 在異常處理機制上的差異。FTWRL命令後如果客戶端發生異常斷開連接,那麼MySQL會自動釋放這個全局鎖。而readonly=true會保持資料庫長時間處於只讀狀態。

表級鎖:

  MySQL裡面表級別的鎖有兩種:一種是表鎖,一種是元數據鎖(meta data lock,MDL)

  表鎖的語法是 lock tables ... read/write。與FTWRL類似,可以用unlock tables主動釋放鎖,也可以在客戶端斷開的時候自動釋放。需要註意的是,lock tables語法除了會限制別的現成的讀寫外,也限定了本線程接下來的操作對象。在沒有更細粒度的鎖的時候,表鎖是最常用的處理併發的方式。而對於InnoDB這種支持行鎖的引擎,一般不使用lock tables命令來控制併發,畢竟鎖住整個表的影響面還是太大。

  另一類表級鎖MDL不要顯示使用,在訪問一個表的時候會自動加上。它的作用是保證讀寫的正確性。如一個查詢正在遍歷一個表中的數據,而同時另一個線程對這個表結構做了變更,刪了一列,那麼查詢線程拿到的結果就會和表結構對不上,肯定是不行的。因此,在MySQL5.5引入了MDL,當對一個表做增刪改查操作的時候,加MDL讀鎖;當要對錶結構變更時,加MDL寫鎖。

  • 讀鎖之間不互斥,因此可以有多個線程同時對一張表增刪改查。
  • 讀寫鎖之間,寫鎖之間是互斥的。以此來保證變更表結構操作的安全性。因此,如果有兩個線程要同時給一個表加欄位,其中一個要等另一個執行完才能開始執行。

  另外,MDL會知道事務提交才釋放,在做表結構變更的時候,一定要小心不要導致鎖住線上查詢和更新。

  表級鎖一般是在資料庫引擎不支持行鎖的時候才會被用到。如果你發現你的應用程式里有lock tables這樣的語句,你需要追查一下,比較可能的情況是:

  • 你的系統還在使用MyISAM這類不支持事務的引擎,需要安排升級更換引擎了
  • 你的引擎升級了,但是代碼還沒有升級。這樣把lock tables和unlock tables更換成begin和commit,問題就解決了。

上篇問題答案:

  表結構如下所示:

CREATE TABLE `geek` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  `d` int(11) NOT NULL,
  PRIMARY KEY (`a`,`b`),
  KEY `c` (`c`),
  KEY `ca` (`c`,`a`),
  KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;

由於歷史原因, a和b需要做聯合主鍵。那麼既然主鍵包括了a,b這兩個欄位,又單獨在c上創建了一個索引,索引就已經包含了三個欄位了,為什麼還要創建ca,cb索引呢?有人給出的理由是業務里有這樣兩個查詢:

select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;

 這個理由對嗎?為了這兩個查詢,這兩個索引是否都必須呢?為什麼呢?

  我們以一組記錄來回答這個問題。

a b c d
1 2 3 d
1 3 2 d
1 4 3 d
2 1 3 d
2 2 2 d
2 3 4 d

  主鍵a,b的聚簇索引組織順序相當於order by a,b。也就是先按a排序,再按b排序,c無序。

  索引ca的組織順序如下(先按c排序,再按a排序),同時記錄主鍵部分b的值

c a b
2 1 3
2 2 2
3 1 2
3 1 4
3 2 1
4 2 3

  你可能會發現,ca的組織順序和索引c的順序是一模一樣的。

  索引cb的組織順序如下(先按c排序,再按b排序,同時記錄主鍵a)

c b a
2 2 2
2 3 1
3 1 2
3 2 1
3 4 1
4 3 2

  所以,結論是ca可以去掉,cb索引仍要保留。ca去掉的原因是組織順序與索引c相比完全相同。

問題:

  備份一般都會在備庫上執行,你在用-single-transaction方法做邏輯備份的過程中,如果主庫上的一個小表做了一個DDL,比如給一個表上加了一列。這時候,從備庫上會看到什麼現象呢?

 


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

-Advertisement-
Play Games
更多相關文章
  • 轉載請標明出處,維權必究:https://www.cnblogs.com/tangZH/p/10458388.html linux系統下能夠直接用命令行查看so庫的信息,但是window系統下咋辦好呢?涼拌~ 還是找到了辦法,這麼辦: 首先下載cygwin,這個工具到底是啥,其實它能夠讓我們在win ...
  • 在Linux系統中,目錄被組織成一個: 單根倒置樹結構 ,文件系統從根目錄開始,用/來表示。文件名稱 區分大小寫 ( 大小寫敏感還需要看具體的文件系統格式 ),以.開頭的為隱藏文件, 路徑用/來進行分割 (windows中使用\來分割),文件有兩個種類: 元數據與數據本身 .在操作linux系統時, ...
  • 1.在啟動的時候按住方向鍵停留在內核選項頁面,在內核選項出按e鍵 2.進入到另一個頁面後,尋找到以linux16開頭的地方,按end到行後,輸入空格,然後輸入rd.break console=tty0,並按ctrl+x組合鍵進入到GRUB引導頁面 3.進入之後,輸入掛載命令改變根分區的掛載選項,命令 ...
  • 使用命令: 說明:user 為當前用戶; 完畢! ...
  • 1.在Linux系統中的【 ~/.baserc 】文件與【 /etc/profile 】配置環境變數後(可以使任意環境變數)無效的現象,如下為解決辦法: 使用命令: 在 【# User configuration】下添加環境變數; 如圖說明: 2.也可以直接將【 ~/.baserc 】文件或【 /e ...
  • 0x00 ubuntu server 16.04 開啟root密碼登錄由於眾多VPS預設使用證書驗證登錄,雖然安全但使用十分不便,所以特提供開啟root用戶並使用密碼登錄方法。0x01 為root賬戶設置密碼$ sudo passwd root0x02 進入root賬戶$ su root0x03 編... ...
  • 簡介 介紹 Docker的存儲捲稱之為volume,本質上容器上的一個或者多個目錄,而這些目錄繞過了聯合文件系統,與宿主機中的目錄或者其他容器目錄進行了綁定關係,這種綁定關係可以看作Linux的mount操作,當容器中的程式對這些目錄寫入數據時,其實寫入到的是與之綁定的宿主機目錄上,這樣就實現了數據 ...
  • 1、下載python3 2、解壓 先建一個編譯目錄: Python3.7版本需要一個新的依賴包libffi-devel,安裝此包之後再次進行編譯安裝即可。 然後編譯、安裝: 建立軟鏈接: 查看版本: 安裝結束! ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...