穿戴式跳d放在里面逛超市的_av无码网站在线_国产午夜亚洲欧美家园美丽_久久无码一二三四_精品久久香蕉国产线看观看亚洲

Top
首頁>即刻 > 正文

消息!Mysql高可用高性能存儲應(yīng)用系列2 - 深入理解鎖和Mvcc

發(fā)布時間:2023-03-25 18:13:53        來源:騰訊云

概述

Mysql數(shù)據(jù)庫在處理并發(fā)中下了很多功夫,鎖是為了更好的保護數(shù)據(jù)的正確和可靠,Mvcc是維持一個數(shù)據(jù)的多個版本,使得讀寫操作沒有沖突的解決并發(fā)的數(shù)據(jù)庫方案。

當數(shù)據(jù)訪問多了,就會出現(xiàn)并發(fā)的問題,Mysql鎖設(shè)計的初衷是處理并發(fā)問題。作為多用戶共享的資源,當出現(xiàn)并發(fā)訪問的時候,數(shù)據(jù)庫需要合理地控制資源的訪問規(guī)則。而鎖就是用來實現(xiàn)這些訪問規(guī)則的重要數(shù)據(jù)結(jié)構(gòu)。


(資料圖)

根據(jù)加鎖的范圍,MySQL 里面的鎖大致可以分成全局鎖、表級鎖和行鎖三類。

全局鎖

全局鎖就是對整個數(shù)據(jù)庫實例加鎖,當你需要讓整個庫處于只讀狀態(tài)的時候,可以使用這個命令,之后其他線程的以下語句會被阻塞:數(shù)據(jù)更新語句(數(shù)據(jù)的增刪改)、數(shù)據(jù)定義語句(包括建表、修改表結(jié)構(gòu)等)和更新類事務(wù)的提交語句。

全局鎖命令:

//加鎖Flush tables with read lock;//釋放鎖命令unlock tables;

全局鎖的典型使用場景是,做全庫邏輯備份。也就是把整庫每個表都 select 出來存成文本。

mysql> UPDATE runoob_tbl SET runoob_title="學習 C++" WHERE runoob_id=1;2013 - Lost connection to server during querymysql> INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES ("學習 PHP", "菜鳥教程", NOW());2013 - Lost connection to server during querymysql> SELECT * FROM runoob_tbl;+-----------+--------------+---------------+-----------------+| runoob_id | runoob_title | runoob_author | submission_date |+-----------+--------------+---------------+-----------------+|         1 | Go 學習    | 菜鳥教程  | 2023-03-22      |+-----------+--------------+---------------+-----------------+1 row in set (0.01 sec)

釋放全局鎖后,所有的進程得到釋放,需要注意的是如果是終端操作需要清空鏈接緩存,或者打開新鏈接重試,mysql釋放鎖在當前的鏈接中是不生效的。

mysql> use mysql2;Database changedmysql> INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES ("學習 PHP", "菜鳥教程", NOW());Query OK, 1 row affected (0.03 sec)

表級鎖

MySQL 里面表級別的鎖有兩種:一種是表鎖,一種是元數(shù)據(jù)鎖(meta data lock,MDL)。

表鎖是最常用的處理并發(fā)的方式。而對于 InnoDB 這種支持行鎖的引擎,一般不使用 lock tables 命令來控制并發(fā),畢竟鎖住整個表的影響面還是太大。

另一類表級的鎖是 MDL(metadata lock)。

//加鎖lock tables 表名 ... read/write;//釋放鎖unlock tables;

表級鎖分讀鎖和寫鎖,1)讀鎖,在進行讀鎖時,讀不會受到影響但是會阻塞其他進程的insert、update操作。

mysql> lock tables runoob_tbl read;Query OK, 0 rows affected (0.05 sec) mysql> select * from runoob_tbl;+-----------+--------------+---------------+-----------------+| runoob_id | runoob_title | runoob_author | submission_date |+-----------+--------------+---------------+-----------------+|         1 | 學習 C++   | 菜鳥教程  | 2023-03-22      ||         2 | 學習 PHP   | 菜鳥教程  | 2023-03-22      ||         3 | 學習 PHP   | 菜鳥教程  | 2023-03-22      |+-----------+--------------+---------------+-----------------+3 rows in set (0.02 sec)//寫操作mysql> INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES ("學習 PHP", "菜鳥教程", NOW());2013 - Lost connection to server during querymysql> UPDATE runoob_tbl SET runoob_title="學習 C++" WHERE runoob_id=1;2013 - Lost connection to server during query

2)寫鎖,對指定表加了寫鎖,會阻塞右側(cè)客戶端的讀和寫。

mysql> lock tables runoob_tbl write;Query OK, 0 rows affected (0.02 sec)mysql> unlock tables;Query OK, 0 rows affected (0.03 sec)

行鎖

MySQL 的行鎖是在引擎層由各個引擎自己實現(xiàn)的,但并不是所有的引擎都支持行鎖,比如 MyISAM 引擎就不支持行鎖。

行鎖就是針對數(shù)據(jù)表中行記錄的鎖。這很好理解,比如事務(wù) A 更新了一行,而這時候事務(wù) B 也要更新同一行,則必須等事務(wù) A 的操作完成后才能進行更新。

兩階段鎖協(xié)議:在 InnoDB 事務(wù)中,行鎖是在需要的時候才加上的,但并不是不需要了就立刻釋放,而是要等到事務(wù)結(jié)束時才釋放。這個就是兩階段鎖協(xié)議。

每個新來的被堵住的線程,都要判斷會不會由于自己的加入導(dǎo)致了死鎖,這是一個時間復(fù)雜度是 O(n) 的操作,要耗費大量的 CPU 資源,應(yīng)該在邏輯上進行優(yōu)化。

Mvcc

因為加鎖會影響效率,MVCC全稱多版本并發(fā)控制(Multiversion concurrency control, MCC 或 MVCC),是數(shù)據(jù)庫管理系統(tǒng)常用的一種并發(fā)控制,理念是維持一個數(shù)據(jù)的多個版本,使得讀寫操作沒有沖突的解決并發(fā)的數(shù)據(jù)庫方案。

當前讀和快照讀

Mvcc 把事務(wù)的執(zhí)行語句分為當前讀和快照讀。

當前讀:總是讀取最新的版本的記錄。快照讀:讀取歷史版本的記錄,歷史版本保存在undo Log(回滾日志)中,快照讀就是MySQL為我們實現(xiàn)MVCC理想模型的其中一個具體非阻塞讀功能。
//select * from Table //快照讀//Insert Update Delete //當前讀//Select ... lock in share mode //當前讀//Select ... for update //當前讀

事務(wù)的隔離解決有四種,可重復(fù)讀(RR)、讀已提交(RC)、讀未提交、序列化,查看全局隔離權(quán)限語句,舊版的myql使用tx開頭,否則報錯1193 - Unknown system variable "tx_isolation"。

mysql> show variables like "transaction_isolation";+-----------------------+-----------------+| Variable_name         | Value           |+-----------------------+-----------------+| transaction_isolation | REPEATABLE-READ |+-----------------------+-----------------+1 row in set (0.07 sec)mysql> select @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| REPEATABLE-READ         |+-------------------------+

如果沒有設(shè)置隔離級別,可使用下面語句進行設(shè)置。

mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;Query OK, 0 rows affected (0.03 sec)

MVCC的實現(xiàn)原理

MVCC的目的就是多版本并發(fā)控制,在數(shù)據(jù)庫中的實現(xiàn),就是為了解決讀寫沖突,它的實現(xiàn)原理主要是依賴記錄中的 3個隱式字段,undo日志 ,Read View 來實現(xiàn)的。

每行記錄除了我們自定義的字段外,還有數(shù)據(jù)庫隱式定義的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段。

DB_TRX_ID : 創(chuàng)建或最后修改記錄的事務(wù)IDDB_ROW_ID : 隱藏主鍵DB_ROLL_PTR :Undo Log里的回滾指針,7byte大小

read-view:事務(wù)在快照時產(chǎn)生的讀視圖。

trx_list : 系統(tǒng)活躍的事務(wù)IDup_limit_id : 列表中事務(wù)最小的IDlow_limit_id : 系統(tǒng)尚未分配的下一個事務(wù)ID

Mvcc判斷的規(guī)則:

1.比較DB_TRX_ID和up_limit_id,如果小于,則當前事務(wù)能看到DB_TRX_ID的記錄,如果大于和等于,則進入下一個判斷

2.比較DB_TRX_ID和low_limit_id,如果大于等于則代表DB_TRX_ID的記錄在read-view生成后出現(xiàn)的,那么對于當前事務(wù)不可見。如果小于,則進入下一個判斷。

3.判斷DB_TRX_ID是否在活躍事務(wù)中,如果在,代表read-view生成時,事務(wù)還在活躍狀態(tài),修改的數(shù)據(jù)當前的事務(wù)是看不到的,如果不在,說明事務(wù)在read-view之前就commit了,那么修改的結(jié)果就是可見的。

可重復(fù)讀(repeatable read):每次進行快照讀時都生成讀視圖。

讀已提交(read committed):只有第一次時生成讀視圖,之后沒次都使用第一次時的讀視圖。

Mysql ( Innodb引擎 ) 保證數(shù)據(jù)的一致性

1.執(zhí)行更新語句update table set a= 1 where id = 2

2.將id=2的行上的列值改為1

3.將修改更新到內(nèi)存中

4.記錄在第N個Page的地方做修改,并將這行記錄狀態(tài)為prepare

5.修改好了,可以提交事務(wù)了

6.寫入binlog

7.commit,提交事務(wù)

8.將redo log里這個事務(wù)的相關(guān)記錄狀態(tài)置為commit狀態(tài)

這個數(shù)據(jù)提交過程,就是兩階段提交,在恢復(fù)數(shù)據(jù)時,用binlog和redolog兩部分來比較做數(shù)據(jù)恢復(fù)就可以了。

事務(wù)

事務(wù)的特性:

原子性:UndoLog 隔離性:Mvcc持久性:RedoLog一致性:以上3個共同保證了一致性

問題

1.既然有了redolog,為什么還要有binlog呢?

redolog依賴于搜索引擎層,并不是每一個引擎都有redolog,binlog是屬于MysqlServer層。

關(guān)鍵詞:

相關(guān)新聞