bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

mysql行鎖怎么理解,哪些屬于mysql行鎖

一文詳解-MySQL 事務(wù)和鎖

當(dāng)多個(gè)用戶訪問同一份數(shù)據(jù)時(shí),一個(gè)用戶在更改數(shù)據(jù)的過程中,可能有其他用戶同時(shí)發(fā)起更改請(qǐng)求,為保證數(shù)據(jù)庫記錄的更新從一個(gè)一致性狀態(tài)變?yōu)榱硗庖粋€(gè)一致性狀態(tài),使用事務(wù)處理是非常必要的,事務(wù)具有以下四個(gè)特性:

創(chuàng)新互聯(lián)建站專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、莊浪網(wǎng)絡(luò)推廣、小程序開發(fā)、莊浪網(wǎng)絡(luò)營銷、莊浪企業(yè)策劃、莊浪品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)建站為所有大學(xué)生創(chuàng)業(yè)者提供莊浪建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:vcdvsql.cn

MySQL 提供了多種事務(wù)型存儲(chǔ)引擎,如 InnoDB 和 BDB 等,而 MyISAM 不支持事務(wù)。為了支持事務(wù),InnoDB 存儲(chǔ)引擎引入了與事務(wù)處理相關(guān)的 REDO 日志和 UNDO 日志,同時(shí)事務(wù)依賴于 MySQL 提供的鎖機(jī)制

事務(wù)執(zhí)行時(shí)需要將執(zhí)行的事務(wù)日志寫入日志文件,對(duì)應(yīng)的文件為 REDO 日志。當(dāng)每條 SQL 進(jìn)行數(shù)據(jù)更新操作時(shí),首先將 REDO 日志寫進(jìn)日志緩沖區(qū)。當(dāng)客戶端執(zhí)行 COMMIT 命令提交時(shí),日志緩沖區(qū)的內(nèi)容將被刷新到磁盤,日志緩沖區(qū)的刷新方式或者時(shí)間間隔可以通過參數(shù) innodb_flush_log_at_trx_commit 控制

REDO 日志對(duì)應(yīng)磁盤上的 ib_logifleN 文件,該文件默認(rèn)為 5MB,建議設(shè)置為 512MB,以便容納較大的事務(wù)。MySQL 崩潰恢復(fù)時(shí)會(huì)重新執(zhí)行 REDO 日志的記錄,恢復(fù)最新數(shù)據(jù),保證已提交事務(wù)的持久性

與 REDO 日志相反,UNDO 日志主要用于事務(wù)異常時(shí)的數(shù)據(jù)回滾,具體內(nèi)容就是記錄數(shù)據(jù)被修改前的信息到 UNDO 緩沖區(qū),然后在合適的時(shí)間將內(nèi)容刷新到磁盤

假如由于系統(tǒng)錯(cuò)誤或者 rollback 操作而導(dǎo)致事務(wù)回滾,可以根據(jù) undo 日志回滾到?jīng)]修改前的狀態(tài),保證未提交事務(wù)的原子性

與 REDO 日志不同的是,磁盤上不存在單獨(dú)的 UNDO 日志文件,所有的 UNDO 日志均存在表空間對(duì)應(yīng)的 .ibd 數(shù)據(jù)文件中,即使 MySQL 服務(wù)啟動(dòng)了獨(dú)立表空間

在 MySQL 中,可以使用 BEGIN 開始事務(wù),使用 COMMIT 結(jié)束事務(wù),中間可以使用 ROLLBACK 回滾事務(wù)。MySQL 通過 SET AUTOCOMMIT、START TRANSACTION、COMMIT 和 ROLLBACK 等語句支持本地事務(wù)

MySQL 定義了四種隔離級(jí)別,指定事務(wù)中哪些數(shù)據(jù)改變其他事務(wù)可見、哪些數(shù)據(jù)該表其他事務(wù)不可見。低級(jí)別的隔離級(jí)別可以支持更高的并發(fā)處理,同時(shí)占用的系統(tǒng)資源更少

InnoDB 系統(tǒng)級(jí)事務(wù)隔離級(jí)別可以使用以下語句設(shè)置:

查看系統(tǒng)級(jí)事務(wù)隔離級(jí)別:

InnoDB 會(huì)話級(jí)事務(wù)隔離級(jí)別可以使用以下語句設(shè)置:

查看會(huì)話級(jí)事務(wù)隔離級(jí)別:

在該隔離級(jí)別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果。讀取未提交的數(shù)據(jù)稱為臟讀(Dirty Read),即是:首先開啟 A 和 B 兩個(gè)事務(wù),在 B 事務(wù)更新但未提交之前,A 事務(wù)讀取到了更新后的數(shù)據(jù),但由于 B 事務(wù)回滾,導(dǎo)致 A 事務(wù)出現(xiàn)了臟讀現(xiàn)象

所有事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變,此級(jí)別可以解決臟讀,但也會(huì)導(dǎo)致不可重復(fù)讀(Nonrepeatable Read):首先開啟 A 和 B 兩個(gè)事務(wù),A事務(wù)讀取了 B 事務(wù)的數(shù)據(jù),在 B 事務(wù)更新并提交后,A 事務(wù)又讀取到了更新后的數(shù)據(jù),此時(shí)就出現(xiàn)了同一 A 事務(wù)中的查詢出現(xiàn)了不同的查詢結(jié)果

MySQL 默認(rèn)的事務(wù)隔離級(jí)別,能確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí)看到同樣的數(shù)據(jù)行,理論上會(huì)導(dǎo)致一個(gè)問題,幻讀(Phontom Read)。例如,第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)做了修改,這種修改會(huì)涉及表中的全部數(shù)據(jù)行,同時(shí)第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這次的修改是向表中插入一行新數(shù)據(jù),此時(shí)就會(huì)發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行

InnoDB 通過多版本并發(fā)控制機(jī)制(MVCC)解決了該問題:InnoDB 通過為每個(gè)數(shù)據(jù)行增加兩個(gè)隱含值的方式來實(shí)現(xiàn),這兩個(gè)隱含值記錄了行的創(chuàng)建時(shí)間、過期時(shí)間以及每一行存儲(chǔ)時(shí)間發(fā)生時(shí)的系統(tǒng)版本號(hào),每個(gè)查詢根據(jù)事務(wù)的版本號(hào)來查詢結(jié)果

通過強(qiáng)制事務(wù)排序,使其不可能相互沖突,從而解決幻讀問題。簡而言之,就是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖實(shí)現(xiàn),這個(gè)級(jí)別會(huì)導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競爭,一般不推薦使用

為了解決數(shù)據(jù)庫并發(fā)控制問題,如走到同一時(shí)刻客戶端對(duì)同一張表做更新或者查詢操作,需要對(duì)并發(fā)操作進(jìn)行控制,因此產(chǎn)生了鎖

共享鎖的粒度是行或者元組(多個(gè)行),一個(gè)事務(wù)獲取了共享鎖以后,可以對(duì)鎖定范圍內(nèi)的數(shù)據(jù)執(zhí)行讀操作

排他鎖的粒度與共享鎖相同,一個(gè)事務(wù)獲取排他鎖以后,可以對(duì)鎖定范圍內(nèi)的數(shù)據(jù)執(zhí)行寫操作

有兩個(gè)事務(wù) A 和 B,如果事務(wù) A 獲取了一個(gè)元組的共享鎖,事務(wù) B 還可以立即獲取這個(gè)元組的共享鎖,但不能獲取這個(gè)元組的排他鎖,必須等到事務(wù) A 釋放共享鎖之后。如果事務(wù) A 獲取了一個(gè)元組的排他鎖,事務(wù) B 不能立即獲取這個(gè)元組的共享鎖,也不能立即獲取這個(gè)元組的排他鎖,必須等到 A 釋放排他鎖之后

意向鎖是一種表鎖,鎖定的粒度是整張表,分為意向共享鎖和意向排他鎖。意向共享鎖表示一個(gè)事務(wù)有意對(duì)數(shù)據(jù)上共享鎖或者排他鎖。有意表示事務(wù)想執(zhí)行操作但還沒真正執(zhí)行

鎖的粒度主要分為表鎖和行鎖

表鎖的開銷最小,同時(shí)允許的并發(fā)量也是最小。MyISAM 存儲(chǔ)引擎使用該鎖機(jī)制。當(dāng)要寫入數(shù)據(jù)時(shí),整個(gè)表記錄被鎖,此時(shí)其他讀/寫動(dòng)作一律等待。一些特定的動(dòng)作,如 ALTER TABLE 執(zhí)行時(shí)使用的也是表鎖

行鎖可以支持最大的并發(fā),InnoDB 存儲(chǔ)引擎使用該鎖機(jī)制。如果要支持并發(fā)讀/寫,建議采用 InnoDB 存儲(chǔ)引擎

MySQL如何鎖定一行及如何分析行鎖定

注意事項(xiàng):session1中沒有commit之前,該數(shù)據(jù)行是鎖定的,其他的session修改該行數(shù)據(jù)時(shí)會(huì)進(jìn)入堵塞狀態(tài)。

MySQL簡單介紹——換個(gè)角度認(rèn)識(shí)MySQL

1、InnoDB存儲(chǔ)引擎

Mysql版本=5.5 默認(rèn)的存儲(chǔ)引擎,MySQL推薦使用的存儲(chǔ)引擎。支持事務(wù),行級(jí)鎖定,外鍵約束。事務(wù)安全型存儲(chǔ)引擎。更加注重?cái)?shù)據(jù)的完整性和安全性。

存儲(chǔ)格式 : 數(shù)據(jù),索引集中存儲(chǔ),存儲(chǔ)于同一個(gè)表空間文件中。

InnoDB的行鎖模式及其加鎖方法: InnoDB中有以下兩種類型的行鎖:共享鎖(讀鎖: 允許事務(wù)對(duì)一條行數(shù)據(jù)進(jìn)行讀取)和 互斥鎖(寫鎖: 允許事務(wù)對(duì)一條行數(shù)據(jù)進(jìn)行刪除或更新), 對(duì)于update,insert,delete語句,InnoDB會(huì)自動(dòng)給設(shè)計(jì)的數(shù)據(jù)集加互斥鎖,對(duì)于普通的select語句,InnoDB不會(huì)加任何鎖。

InnoDB行鎖的實(shí)現(xiàn)方式: InnoDB行鎖是通過給索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的,如果沒有索引,InnoDB將通過隱藏的聚簇索引來對(duì)記錄加鎖。InnoDB這種行鎖實(shí)現(xiàn)特點(diǎn)意味著:如果不通過索引條件檢索數(shù)據(jù),那么InnoDB將對(duì)表中的所有記錄加鎖,實(shí)際效果跟表鎖一樣。

(1)在不通過索引條件查詢時(shí),InnoDB會(huì)鎖定表中的所有記錄。

(2)Mysql的行鎖是針對(duì)索引加的鎖,不是針對(duì)記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果使用相同的索引鍵,是會(huì)出現(xiàn)沖突的。

(3)當(dāng)表有多個(gè)索引的時(shí)候,不同的事務(wù)可以使用不同的索引鎖定不同的行,但都是通過行鎖來對(duì)數(shù)據(jù)加鎖。

優(yōu)點(diǎn):

1、支持事務(wù)處理、ACID事務(wù)特性;

2、實(shí)現(xiàn)了SQL標(biāo)準(zhǔn)的四種隔離級(jí)別( 原子性( Atomicity )、一致性( Consistency )、隔離性(Isolation )和持續(xù)性(Durability ));

3、支持行級(jí)鎖和外鍵約束;

4、可以利用事務(wù)日志進(jìn)行數(shù)據(jù)恢復(fù)。

5、鎖級(jí)別為行鎖,行鎖優(yōu)點(diǎn)是適用于高并發(fā)的頻繁表修改,高并發(fā)是性能優(yōu)于 MyISAM。缺點(diǎn)是系統(tǒng)消耗較大。

6、索引不僅緩存自身,也緩存數(shù)據(jù),相比 MyISAM 需要更大的內(nèi)存。

缺點(diǎn):

因?yàn)樗鼪]有保存表的行數(shù),當(dāng)使用COUNT統(tǒng)計(jì)時(shí)會(huì)掃描全表。

使用場景:

(1)可靠性要求比較高,或者要求事務(wù);(2)表更新和查詢都相當(dāng)?shù)念l繁,并且表鎖定的機(jī)會(huì)比較大的情況。

2、 MyISAM存儲(chǔ)引擎

MySQL= 5.5 MySQL默認(rèn)的存儲(chǔ)引擎。ISAM:Indexed Sequential Access Method(索引順序存取方法)的縮寫,是一種文件系統(tǒng)。擅長與處理,高速讀與寫。

功能:

(1)支持?jǐn)?shù)據(jù)壓縮存儲(chǔ),但壓縮后的表變成了只讀表,不可寫;如果需要更新數(shù)據(jù),則需要先解壓后更新。

(2)支持表級(jí)鎖定,不支持高并發(fā);

(3)支持并發(fā)插入。寫操作中的插入操作,不會(huì)阻塞讀操作(其他操作);

優(yōu)點(diǎn):

1.高性能讀取;

2.因?yàn)樗4媪吮淼男袛?shù),當(dāng)使用COUNT統(tǒng)計(jì)時(shí)不會(huì)掃描全表;

缺點(diǎn):

1、鎖級(jí)別為表鎖,表鎖優(yōu)點(diǎn)是開銷小,加鎖快;缺點(diǎn)是鎖粒度大,發(fā)生鎖沖動(dòng)概率較高,容納并發(fā)能力低,這個(gè)引擎適合查詢?yōu)橹鞯臉I(yè)務(wù)。

2、此引擎不支持事務(wù),也不支持外鍵。

3、INSERT和UPDATE操作需要鎖定整個(gè)表;

使用場景:

(1)做很多count 的計(jì)算;(2)插入不頻繁,查詢非常頻繁;(3)沒有事務(wù)。

InnoDB和MyISAM一些細(xì)節(jié)上的差別:

1、InnoDB不支持FULLTEXT類型的索引,MySQL5.6之后已經(jīng)支持(實(shí)驗(yàn)性)。

2、InnoDB中不保存表的 具體行數(shù),也就是說,執(zhí)行select count() from table時(shí),InnoDB要掃描一遍整個(gè)表來計(jì)算有多少行,但是MyISAM只要簡單的讀出保存好的行數(shù)即可。注意的是,當(dāng)count()語句包含 where條件時(shí),兩種表的操作是一樣的。

3、對(duì)于AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯(lián)合索引。

4、DELETE FROM table時(shí),InnoDB不會(huì)重新建立表,而是一行一行的刪除。

5、LOAD TABLE FROM MASTER操作對(duì)InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導(dǎo)入數(shù)據(jù)后再改成InnoDB表,但是對(duì)于使用的額外的InnoDB特性(例如外鍵)的表不適用。

6、另外,InnoDB表的行鎖也不是絕對(duì)的,如果在執(zhí)行一個(gè)SQL語句時(shí)MySQL不能確定要掃描的范圍,InnoDB表同樣會(huì)鎖全表。

1.索引概述

利用關(guān)鍵字,就是記錄的部分?jǐn)?shù)據(jù)(某個(gè)字段,某些字段,某個(gè)字段的一部分),建立與記錄位置的對(duì)應(yīng)關(guān)系,就是索引。索引的關(guān)鍵字一定是排序的。索引本質(zhì)上是表字段的有序子集,它是提高查詢速度最有效的方法。一個(gè)沒有建立任何索引的表,就相當(dāng)于一本沒有目錄的書,在每次查詢時(shí)就會(huì)進(jìn)行全表掃描,這樣會(huì)導(dǎo)致查詢效率極低、速度也極慢。如果建立索引,那么就好比一本添加的目錄,通過目錄的指引,迅速翻閱到指定的章節(jié),提升的查詢性能,節(jié)約了查詢資源。

2.索引種類

從索引的定義方式和用途中來看:主鍵索引,唯一索引,普通索引,全文索引。

無論任何類型,都是通過建立關(guān)鍵字與位置的對(duì)應(yīng)關(guān)系來實(shí)現(xiàn)的。索引是通過關(guān)鍵字找對(duì)應(yīng)的記錄的地址。

以上類型的差異:對(duì)索引關(guān)鍵字的要求不同。

關(guān)鍵字:記錄的部分?jǐn)?shù)據(jù)(某個(gè)字段,某些字段,某個(gè)字段的一部分)。

普通索引,index:對(duì)關(guān)鍵字沒有要求。

唯一索引,unique index:要求關(guān)鍵字不能重復(fù)。同時(shí)增加唯一約束。

主鍵索引,primary key:要求關(guān)鍵字不能重復(fù),也不能為NULL。同時(shí)增加主鍵約束。

全文索引,fulltext key:關(guān)鍵字的來源不是所有字段的數(shù)據(jù),而是從字段中提取的特別關(guān)鍵詞。

PS:這里主鍵索引和唯一索引的區(qū)別在于:主鍵索引不能為空值,唯一索引允許空值;主鍵索引在一張表內(nèi)只能創(chuàng)建一個(gè),唯一索引可以創(chuàng)建多個(gè)。主鍵索引肯定是唯一索引,但唯一索引不一定是主鍵索引。

3.索引原則

如果索引不遵循使用原則,則可能導(dǎo)致索引無效。

(1)列獨(dú)立

如果需要某個(gè)字段上使用索引,則需要在字段參與的表達(dá)中,保證字段獨(dú)立在一側(cè)。否則索引不會(huì)用到索引, 例如這條sql就不會(huì)用到索引:select * from A where id+1=10;

(2)左原則

Like:匹配模式必須要左邊確定不能以通配符開頭。例如:select * from A where name like '%小明%' ,不會(huì)用到索引,而select * from A where name like '小明%' 就可以用到索引(name字段有建立索引),如果業(yè)務(wù)上需要用到'%小明%'這種方式,有兩種方法:1.可以考慮全文索引,但mysql的全文索引不支持中文;2.只查詢索引列或主鍵列,例如:select name from A where name like '%小明%' 或 select id from A where name like '%小明%' 或 select id,name from A where name like '%小明%' 這三種情況都會(huì)用到name的索引;

復(fù)合索引:一個(gè)索引關(guān)聯(lián)多個(gè)字段,僅僅針對(duì)左邊字段有效果,添加復(fù)合索引時(shí),第一個(gè)字段很重要,只有包含第一個(gè)字段作為查詢條件的情況才會(huì)使用復(fù)合索引(必須用到建索引時(shí)選擇的第一個(gè)字段作為查詢條件,其他字段的順序無關(guān)),而且查詢條件只能出現(xiàn)and拼接,不能用or,否則則無法使用索引.

(3)OR的使用

必須要保證 OR 兩端的條件都存在可以用的索引,該查詢才可以使用索引。

(4)MySQL智能選擇

即使?jié)M足了上面說原則,MySQL也能棄用索引,例如:select * from A where id 1;這里棄用索引的主要原因:查詢即使使用索引,會(huì)導(dǎo)致出現(xiàn)大量的隨機(jī)IO,相對(duì)于從數(shù)據(jù)記錄的第一條遍歷到最后一條的順序IO開銷,還要大。

4.索引的使用場景

(1)索引檢索:檢索數(shù)據(jù)時(shí)使用索引。

(2)索引排序: 如果order by 排序需要的字段上存在索引,則可能使用到索引。

(3)索引覆蓋: 索引擁有的關(guān)鍵字內(nèi)容,覆蓋了查詢所需要的全部數(shù)據(jù),此時(shí),就不需要在數(shù)據(jù)區(qū)獲取數(shù)據(jù),僅僅在索引區(qū)即可。覆蓋就是直接在索引區(qū)獲取內(nèi)容,而不需要在數(shù)據(jù)區(qū)獲取。例如: select name from A where name like '小明%';

建立索引索引時(shí),不能僅僅考慮where檢索,同時(shí)考慮其他的使用場景。(在所有的where字段上增加索引,就是不合理的)

5.前綴索引

前綴索引是建立索引關(guān)鍵字一種方案。通常會(huì)使用字段的整體作為索引關(guān)鍵字。有時(shí),即使使用字段前部分?jǐn)?shù)據(jù),也可以去識(shí)別某些記錄。就比如一個(gè)班級(jí)里,我要找王xx,假如姓王的只有1個(gè)人,那么就可以建一個(gè)關(guān)鍵字為'王'的前綴索引。語法:Index `index_name` (`index_field`(N))使用index_name前N個(gè)字符建立的索引。

6.索引失效

(1) 應(yīng)盡量避免在 where 子句中使用 != 或 操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描;

(2) 應(yīng)盡量避免在 where 子句中使用 or 來連接條件,如果一個(gè)字段有索引,一個(gè)字段沒有索引,將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;

(3) 應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;

(4)應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;如select id from t where num/2 = 100;

(5) 應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;如:select id from t where substring(name,1,3) = ’abc’ ;

(6)應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行類型轉(zhuǎn)換,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描; 如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號(hào)引用起來,如select id from t where id = 1;如果id字段在表設(shè)計(jì)中是varchar類型,那么即使id列上存的是數(shù)字,在查詢時(shí)也一定要用varchar去匹配,sql應(yīng)改為select id from t where id = '1';

(7)應(yīng)盡量避免在where子句中單獨(dú)引用復(fù)合索引里非第一位置的索引;

join 的兩種算法:BNL 和 NLJ

NLJ(Nested Loop Join)嵌套循環(huán)算法;以如下 SQL 為例:

select * from t1 join t2 on t1.a=t2.a

SQL 執(zhí)行時(shí)內(nèi)部流程是這樣的:

1. 先從 t1(假設(shè)這里 t1 被選為驅(qū)動(dòng)表)中取出一行數(shù)據(jù) X;

2. 從 X 中取出關(guān)聯(lián)字段 a 值,去 t2 中進(jìn)行查找,滿足條件的行取出;

3. 重復(fù)1、2步驟,直到表 t1 最后一行循環(huán)結(jié)束。

這就是一個(gè)嵌套循環(huán)的過程,如果在被驅(qū)動(dòng)表上查找數(shù)據(jù)時(shí)可以使用索引,總的對(duì)比計(jì)算次數(shù)等于驅(qū)動(dòng)表滿足 where 條件的行數(shù)。假設(shè)這里 t1、t2都是1萬行,則只需要 1萬次計(jì)算,這里用到的是Index Nested-Loops Join(INLJ,基于索引的嵌套循環(huán)聯(lián)接)。

如果 t1、t2 的 a 字段都沒有索引,還按照上述的嵌套循環(huán)流程查找數(shù)據(jù)呢?每次在被驅(qū)動(dòng)表上查找數(shù)據(jù)時(shí)都是一次全表掃描,要做1萬次全表掃描,掃描行數(shù)等于 1萬+1萬*1萬,這個(gè)效率很低,如果表行數(shù)更多,掃描行數(shù)動(dòng)輒幾百億,所以優(yōu)化器肯定不會(huì)使用這樣的算法,而是選擇 BNL 算法;

BNLJ(Block Nested Loop Join)塊嵌套循環(huán)算法;

1. 把 t1 表(假設(shè)這里 t1 被選為驅(qū)動(dòng)表)滿足條件的數(shù)據(jù)全部取出放到線程的 join buffer 中;

2. 每次取 t2 表一行數(shù)據(jù),去 joinbuffer 中進(jìn)行查找,滿足條件的行取出,直到表 t2 最后一行循環(huán)結(jié)束。

這個(gè)算法下,執(zhí)行計(jì)劃的 Extra 中會(huì)出現(xiàn) Using join buffer(Block Nested Loop),t1、t2 都做了一次全表掃描,總的掃描行數(shù)等于 1萬+1萬。但是由于 joinbuffer 維護(hù)的是一個(gè)無序數(shù)組,每次在 joinbuffer 中查找都要遍歷所有行,總的內(nèi)存計(jì)算次數(shù)等于1萬*1萬。另外如果 joinbuffer 不夠大放不下驅(qū)動(dòng)表的數(shù)據(jù),則要分多次執(zhí)行上面的流程,會(huì)導(dǎo)致被驅(qū)動(dòng)表也做多次全表掃描。

BNLJ相對(duì)于NLJ的優(yōu)點(diǎn)在于,驅(qū)動(dòng)層可以先將部分?jǐn)?shù)據(jù)加載進(jìn)buffer,這種方法的直接影響就是將大大減少內(nèi)層循環(huán)的次數(shù),提高join的效率。

例如:

如果內(nèi)層循環(huán)有100條記錄,外層循環(huán)也有100條記錄,這樣的話,每次外層循環(huán)先將10條記錄放到buffer中,內(nèi)層循環(huán)的100條記錄每條與這個(gè)buffer中的10條記錄進(jìn)行匹配,只需要匹配內(nèi)層循環(huán)總記錄數(shù)次即可結(jié)束一次循環(huán)(在這里,即只需要匹配100次即可結(jié)束),然后將匹配成功的記錄連接后放入結(jié)果集中,接著,外層循環(huán)繼續(xù)向buffer中放入10條記錄,同理進(jìn)行匹配,并將成功的記錄連接后放入結(jié)果集。后續(xù)循環(huán)以此類推,直到循環(huán)結(jié)束,將結(jié)果集發(fā)給client為止。

可以發(fā)現(xiàn),若用NLJ,則需要100 * 100次才可結(jié)束,BNLJ則需要100 / block_size * 100 = 10 * 100次就可結(jié)束,大大減少了循環(huán)次數(shù)。

JOIN 按照功能大致分為如下三類:

JOIN、STRAIGHT_JOIN、INNER JOIN(內(nèi)連接,或等值連接):取得兩個(gè)表中存在連接匹配關(guān)系的記錄。

LEFT JOIN(左連接):取得左表(table1)完全記錄,即是右表(table2)并無對(duì)應(yīng)匹配記錄。

RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)并無匹配對(duì)應(yīng)記錄。

注意:mysql不支持Full join,不過可以通過UNION 關(guān)鍵字來合并 LEFT JOIN 與 RIGHT JOIN來模擬FULL join。

mysql 多表連接查詢方式,因?yàn)閙ysql只支持NLJ算法,所以如果是小表驅(qū)動(dòng)大表則效率更高;反之則效率下降;因此mysql對(duì)內(nèi)連接或等值連接的方式做了一個(gè)優(yōu)化,會(huì)去判斷join表的數(shù)據(jù)行大小,然后取數(shù)據(jù)行小的表為驅(qū)動(dòng)表。

INNER JOIN、JOIN、WHERE等值連接和STRAIGHT_JOIN都能表示內(nèi)連接,那平時(shí)如何選擇呢?一般情況下用INNER JOIN、JOIN或者WHERE等值連接,因?yàn)镸ySQL 會(huì)按照"小表驅(qū)動(dòng)大表的策略"進(jìn)行優(yōu)化。當(dāng)出現(xiàn)需要排序時(shí),才考慮用STRAIGHT_JOIN指定某張表為驅(qū)動(dòng)表。

兩表JOIN優(yōu)化

a.當(dāng)無order by條件時(shí),根據(jù)實(shí)際情況,使用left/right/inner join即可,根據(jù)explain優(yōu)化 ;

b.當(dāng)有order by條件時(shí),如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解釋語句;

1)如果第一行的驅(qū)動(dòng)表為a,則效率會(huì)非常高,無需優(yōu)化;

2)否則,因?yàn)橹荒軐?duì)驅(qū)動(dòng)表字段直接排序的緣故,會(huì)出現(xiàn)using temporary,所以此時(shí)需要使用STRAIGHT_JOIN明確a為驅(qū)動(dòng)表,來達(dá)到使用a.col上index的優(yōu)化目的;或者使用left join且Where條件中不含b的過濾條件,此時(shí)的結(jié)果集為a的全集,而STRAIGHT_JOIN為inner join且使用a作為驅(qū)動(dòng)表。注:使用STRAIGHT_JOIN雖然不會(huì)using temporary,但也不是一定就能提高效率,如果a表數(shù)據(jù)遠(yuǎn)遠(yuǎn)超過b表,那么有可能使用STRAIGHT_JOIN時(shí)比原來的sql效率更低,所以怎么使用STRAIGHT_JOIN,還是要視情況而定。

在使用left join(或right join)時(shí),應(yīng)該清楚的知道以下幾點(diǎn):

(1). on與 where的執(zhí)行順序

ON 條件(“A LEFT JOIN B ON 條件表達(dá)式”中的ON)用來決定如何從 B 表中檢索數(shù)據(jù)行。如果 B 表中沒有任何一行數(shù)據(jù)匹配 ON 的條件,將會(huì)額外生成一行所有列為 NULL 的數(shù)據(jù),在匹配階段 WHERE 子句的條件都不會(huì)被使用。僅在匹配階段完成以后,WHERE 子句條件才會(huì)被使用。它將從匹配階段產(chǎn)生的數(shù)據(jù)中檢索過濾。

所以我們要注意:在使用Left (right) join的時(shí)候,一定要在先給出盡可能多的匹配滿足條件,減少Where的執(zhí)行。

(2).注意ON 子句和 WHERE 子句的不同

即使右表的數(shù)據(jù)不滿足ON后面的條件,也會(huì)在結(jié)果集拼接一條為NULL的數(shù)據(jù)行,但WHERE后面的條件不一樣,右表不滿足WHERE的條件,左表關(guān)聯(lián)的數(shù)據(jù)也會(huì)被過濾掉。

(3).盡量避免子查詢,而用join

往往性能這玩意兒,更多時(shí)候體現(xiàn)在數(shù)據(jù)量比較大的時(shí)候,此時(shí),我們應(yīng)該避免復(fù)雜的子查詢。

(1)in 和 not in 要慎用,如:select id from t where num in(1,2,3)對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in:select id from t where num between 1 and 3很多時(shí)候用 exists 代替 in 是一個(gè)好的選擇:select num from a where num in(select num from b)用下面的語句替換:select num from a where exists(select 1 from b where num=a.num)

(2)Update 語句,如果只更改1、2個(gè)字段,不要Update全部字段,否則頻繁調(diào)用會(huì)引起明顯的性能消耗,同時(shí)帶來大量日志。

(3)join語句,MySQL里面的join是用小表去驅(qū)動(dòng)大表,而由于MySQL join實(shí)現(xiàn)的原理就是做循環(huán),比如left join就是對(duì)左邊的數(shù)據(jù)進(jìn)行循環(huán)去驅(qū)動(dòng)右邊的表,左邊有m條記錄匹配,右邊有n條記錄那么就是做m次循環(huán),每次掃描n行數(shù)據(jù),總掃面行數(shù)是m*n行數(shù)據(jù)。左邊返回的結(jié)果集的大小就決定了循環(huán)的次數(shù),故單純的用小表去驅(qū)動(dòng)大表不一定的正確的,小表的結(jié)果集可能也大于大表的結(jié)果集,所以寫join的時(shí)候盡可能的先估計(jì)兩張表的可能結(jié)果集,用小結(jié)果集去驅(qū)動(dòng)大結(jié)果集.值得注意的是在使用left/right join的時(shí)候,從表的條件應(yīng)寫在on之后,主表應(yīng)寫在where之后.否則MySQL會(huì)當(dāng)作普通的連表查詢;

(4)select count(*) from table;這樣不帶任何條件的count會(huì)引起全表掃描,并且沒有任何業(yè)務(wù)意義,是一定要杜絕的;

(5)select * from t 這種語句要盡量避免,使用具體的字段代替*,更有實(shí)際意義,需要什么字段就返回什么字段;

(6)數(shù)據(jù)量大的情況下,limit要慎用,因?yàn)槭褂胠imit m,n方式分頁時(shí),mysql每次都是查詢前m+n條,然后舍棄前m條,所以m越大,偏移量越大,性能就越差。比如:select * from A limit 1000000,20這鐘,查詢效率就會(huì)非常低,當(dāng)分頁的頁數(shù)大于一定的數(shù)量之后,就可以換種方式來分頁:select * from A a join (select id from A limit 1000000,20) b on a.id=b.id;

面試你應(yīng)該知道的 MySQL 的鎖

背景

數(shù)據(jù)庫的鎖是在多線程高并發(fā)的情況下用來保證數(shù)據(jù)穩(wěn)定性和一致性的一種機(jī)制。MySQL 根據(jù)底層存儲(chǔ)引擎的不同,鎖的支持粒度和實(shí)現(xiàn)機(jī)制也不同。MyISAM 只支持表鎖,InnoDB 支持行鎖和表鎖。目前 MySQL 默認(rèn)的存儲(chǔ)引擎是 InnoDB,這里主要介紹 InnoDB 的鎖。

使用 InnoDB 的兩大優(yōu)點(diǎn):一是支持事務(wù);二是支持行鎖。

在高并發(fā)的情況下事務(wù)的并發(fā)處理會(huì)帶來幾個(gè)問題

由于高并發(fā)事務(wù)帶來這幾個(gè)問題,所以就產(chǎn)生了事務(wù)的隔離級(jí)別

舉個(gè)例子

按照上面 1,2,3,4 的順序執(zhí)行會(huì)發(fā)現(xiàn)第 4 步被阻塞了,必須執(zhí)行完第 5 步后才能插入成功。這里我們會(huì)很奇怪明明鎖住的是uid=6 的這一行,為什么不能插入 5 呢?原因就是這里采用了 next-key 的算法,鎖住的是(3,10)整個(gè)區(qū)間。感興趣的可以試一下。

今天給大家分享了一下 MySQL 的 InnoDB 的事務(wù)以及鎖的一些知識(shí),通過自己的實(shí)際上手實(shí)踐對(duì)這塊更加熟悉了,希望大家在看的時(shí)候也可以動(dòng)手試試,這樣更能體會(huì),理解的更深刻。

深入理解MySQL數(shù)據(jù)庫各種鎖(總結(jié))

MyISAM和InnoDB存儲(chǔ)引擎使用的鎖:

封鎖粒度小:

由于InnoDB存儲(chǔ)引擎支持的是行級(jí)別的鎖,因此意向鎖(因?yàn)橐庀蜴i是表鎖)其實(shí)不會(huì)阻塞除全表掃以外的任何請(qǐng)求。故表級(jí)意向鎖與行級(jí)鎖的兼容性如下所示

參考

參考

行鎖的三種算法:

這條語句阻止其他事務(wù)插入10和20之間的數(shù)字,無論這個(gè)數(shù)字是否存在。 間隙可以跨越0個(gè),單個(gè)或多個(gè)索引值。

共享鎖:

排他鎖:

樂觀鎖:總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改(天真), 操作數(shù)據(jù)時(shí)不會(huì)上鎖 ,但是 更新時(shí)會(huì)判斷在此期間有沒有別的事務(wù)更新這個(gè)數(shù)據(jù),若被更新過,則失敗重試 ;適用于讀多寫少的場景。

樂觀鎖的實(shí)現(xiàn)方式 有:

關(guān)閉自動(dòng)提交后,我們需要手動(dòng)開啟事務(wù)。

上述就實(shí)現(xiàn)了悲觀鎖,悲觀鎖就是悲觀主義者,它會(huì)認(rèn)為我們?cè)谑聞?wù)A中操作數(shù)據(jù)1的時(shí)候,一定會(huì)有事務(wù)B來修改數(shù)據(jù)1,所以,在第2步我們將數(shù)據(jù)查詢出來后直接加上排它鎖(X)鎖,防止別的事務(wù)來修改事務(wù)1,直到我們commit后,才釋放了排它鎖。

新聞名稱:mysql行鎖怎么理解,哪些屬于mysql行鎖
鏈接URL:http://vcdvsql.cn/article48/dsisjhp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google標(biāo)簽優(yōu)化云服務(wù)器響應(yīng)式網(wǎng)站靜態(tài)網(wǎng)站移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)