中国人与黑人牲交FREE欧美_丰满熟妇XXXX_婷婷久久综合九色综合97_免费无码成人AV在线播软件_免费AV 中文字幕 在线

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

2023-03-26 07:01:27

概述

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


【資料圖】

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

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

全局鎖

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

全局鎖命令:

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

全局鎖的典型使用場(chǎng)景是,做全庫(kù)邏輯備份。也就是把整庫(kù)每個(gè)表都 select 出來(lái)存成文本。

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

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

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

表級(jí)鎖

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

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

另一類(lèi)表級(jí)的鎖是 MDL(metadata lock)。

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

表級(jí)鎖分讀鎖和寫(xiě)鎖,1)讀鎖,在進(jìn)行讀鎖時(shí),讀不會(huì)受到影響但是會(huì)阻塞其他進(jìn)程的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 | 學(xué)習(xí) C++   | 菜鳥(niǎo)教程  | 2023-03-22      ||         2 | 學(xué)習(xí) PHP   | 菜鳥(niǎo)教程  | 2023-03-22      ||         3 | 學(xué)習(xí) PHP   | 菜鳥(niǎo)教程  | 2023-03-22      |+-----------+--------------+---------------+-----------------+3 rows in set (0.02 sec)//寫(xiě)操作mysql> INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES ("學(xué)習(xí) PHP", "菜鳥(niǎo)教程", NOW());2013 - Lost connection to server during querymysql> UPDATE runoob_tbl SET runoob_title="學(xué)習(xí) C++" WHERE runoob_id=1;2013 - Lost connection to server during query

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

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 的行鎖是在引擎層由各個(gè)引擎自己實(shí)現(xiàn)的,但并不是所有的引擎都支持行鎖,比如 MyISAM 引擎就不支持行鎖。

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

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

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

Mvcc

因?yàn)榧渔i會(huì)影響效率,MVCC全稱多版本并發(fā)控制(Multiversion concurrency control, MCC 或 MVCC),是數(shù)據(jù)庫(kù)管理系統(tǒng)常用的一種并發(fā)控制,理念是維持一個(gè)數(shù)據(jù)的多個(gè)版本,使得讀寫(xiě)操作沒(méi)有沖突的解決并發(fā)的數(shù)據(jù)庫(kù)方案。

當(dāng)前讀和快照讀

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

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

事務(wù)的隔離解決有四種,可重復(fù)讀(RR)、讀已提交(RC)、讀未提交、序列化,查看全局隔離權(quán)限語(yǔ)句,舊版的myql使用tx開(kāi)頭,否則報(bào)錯(cuò)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         |+-------------------------+

如果沒(méi)有設(shè)置隔離級(jí)別,可使用下面語(yǔ)句進(jìn)行設(shè)置。

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

MVCC的實(shí)現(xiàn)原理

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

每行記錄除了我們自定義的字段外,還有數(shù)據(jù)庫(kù)隱式定義的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ù)在快照時(shí)產(chǎn)生的讀視圖。

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

Mvcc判斷的規(guī)則:

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

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

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

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

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

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

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

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

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

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

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

6.寫(xiě)入binlog

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

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

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

事務(wù)

事務(wù)的特性:

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

問(wèn)題

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

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

標(biāo)簽:

x 廣告
x 廣告

Copyright ©  2015-2022 太平洋文旅網(wǎng)版權(quán)所有  備案號(hào):豫ICP備2022016495號(hào)-17   聯(lián)系郵箱:93 96 74 66 9@qq.com