全局鎖
全局鎖就是對(duì)整個(gè)數(shù)據(jù)庫(kù)實(shí)例加鎖,
實(shí)現(xiàn)一:命令是 Flush tables with read lock (FTWRL)黍图,讓整個(gè)庫(kù)處于只讀狀態(tài)的時(shí)候顽馋,使用場(chǎng)景:引擎不支持事務(wù)和措,做數(shù)據(jù)庫(kù)備份
實(shí)現(xiàn)二:mysqldump 使用參數(shù)–single-transaction,通過(guò)視圖求冷,需要數(shù)據(jù)庫(kù)支持事務(wù):innodb
表級(jí)鎖
實(shí)現(xiàn)一:表鎖朽褪, lock tables … read/write語(yǔ)法,與FTWRL類(lèi)似犁嗅,可以用unlock tables 主動(dòng)釋放边涕,與客戶(hù)端斷開(kāi)的時(shí)候自動(dòng)釋放。
缺點(diǎn):對(duì)于 InnoDB 這種支持行鎖的引擎褂微,一般不使用 lock tables 命令來(lái)控制并發(fā)功蜓,畢竟鎖住整個(gè)表的影響面還是太大。
實(shí)現(xiàn)二:元數(shù)據(jù)鎖MDL(metadata lock)宠蚂,MDL 不需要顯式使用式撼,在訪(fǎng)問(wèn)一個(gè)表的時(shí)候會(huì)被自動(dòng)加上。當(dāng)對(duì)一個(gè)表做增刪改查操作的時(shí)候求厕,加 MDL 讀鎖著隆;當(dāng)要對(duì)表做結(jié)構(gòu)變更操作的時(shí)候,加 MDL 寫(xiě)鎖呀癣。
1.讀鎖之間不互斥美浦,因此你可以有多個(gè)線(xiàn)程同時(shí)對(duì)一張表增刪改查。
2.讀寫(xiě)鎖之間项栏、寫(xiě)鎖之間是互斥的浦辨,用來(lái)保證變更表結(jié)構(gòu)操作的安全性。因此忘嫉,如果有兩個(gè)線(xiàn)程要同時(shí)給一個(gè)表加字段荤牍,其中一個(gè)要等另一個(gè)執(zhí)行完才能開(kāi)始執(zhí)行案腺。
例:給一個(gè)小表加個(gè)字段庆冕,導(dǎo)致整個(gè)庫(kù)掛了。
1.session A 先啟動(dòng)劈榨,這時(shí)候會(huì)對(duì)表 t 加一個(gè) MDL 讀鎖访递。由于 session B 需要的也是 MDL 讀鎖,因此可以正常執(zhí)行同辣。
2.session C 會(huì)被 blocked拷姿,是因?yàn)?session A 的 MDL 讀鎖還沒(méi)有釋放惭载,而 session C 需要 MDL 寫(xiě)鎖,因此只能被阻塞响巢。
3.如果只有 session C 自己被阻塞還沒(méi)什么關(guān)系描滔,但是之后所有要在表 t 上新申請(qǐng) MDL 讀鎖的請(qǐng)求也會(huì)被 session C 阻塞。前面我們說(shuō)了踪古,所有對(duì)表的增刪改查操作都需要先申請(qǐng) MDL 讀鎖含长,就都被鎖住,等于這個(gè)表現(xiàn)在完全不可讀寫(xiě)了伏穆。
4.如果某個(gè)表上的查詢(xún)語(yǔ)句頻繁拘泞,而且客戶(hù)端有重試機(jī)制,也就是說(shuō)超時(shí)后會(huì)再起一個(gè)新 session 再請(qǐng)求的話(huà)枕扫,這個(gè)庫(kù)的線(xiàn)程很快就會(huì)爆滿(mǎn)
如何安全地給小表加字段:
1.如果你要做 DDL 變更的表剛好有長(zhǎng)事務(wù)在執(zhí)行陪腌,要考慮先暫停 DDL,或者 kill 掉這個(gè)長(zhǎng)事務(wù)烟瞧。
2.在 alter table 語(yǔ)句里面設(shè)定等待時(shí)間(MariaDB合并了 AliSQL 的這個(gè)功能诗鸭, 支持 DDL NOWAIT/WAIT n 這個(gè)語(yǔ)法。)燕刻。
行鎖
行鎖就是針對(duì)數(shù)據(jù)表中行記錄的鎖只泼,比如事務(wù) A 更新了一行,而這時(shí)候事務(wù) B 也要更新同一行卵洗,則必須等事務(wù) A 的操作完成后才能進(jìn)行更新请唱。
MySQL 的行鎖是在引擎層由各個(gè)引擎自己實(shí)現(xiàn)的。但并不是所有的引擎都支持行鎖过蹂,比如 MyISAM 引擎就不支持行鎖十绑。不支持行鎖意味著并發(fā)控制只能使用表鎖,對(duì)于這種引擎的表酷勺,同一張表上任何時(shí)刻只能有一個(gè)更新在執(zhí)行本橙,這就會(huì)影響到業(yè)務(wù)并發(fā)度。InnoDB 是支持行鎖的脆诉,這也是 MyISAM 被 InnoDB 替代的重要原因之一甚亭。
兩階段鎖:
在 InnoDB 事務(wù)中,行鎖是在需要的時(shí)候才加上的击胜,但并不是不需要了就立刻釋放亏狰,而是要等到事務(wù)結(jié)束時(shí)才釋放。
例:事務(wù) B 的 update 語(yǔ)句會(huì)被阻塞偶摔,直到事務(wù) A 執(zhí)行 commit 之后暇唾,事務(wù) B 才能繼續(xù)執(zhí)行。
mysql優(yōu)化思路:如果你的事務(wù)中需要鎖多個(gè)行,要把最可能造成鎖沖突策州、最可能影響并發(fā)度的鎖盡量往后放瘸味。
死鎖和死鎖檢測(cè)
當(dāng)并發(fā)系統(tǒng)中不同線(xiàn)程出現(xiàn)循環(huán)資源依賴(lài),涉及的線(xiàn)程都在等待別的線(xiàn)程釋放資源時(shí)够挂,就會(huì)導(dǎo)致這幾個(gè)線(xiàn)程都進(jìn)入無(wú)限等待的狀態(tài)旁仿,稱(chēng)為死鎖。
例:事務(wù) A 在等待事務(wù) B 釋放 id=2 的行鎖孽糖,而事務(wù) B 在等待事務(wù) A 釋放 id=1 的行鎖丁逝。 事務(wù) A 和事務(wù) B 在互相等待對(duì)方的資源釋放,就是進(jìn)入了死鎖狀態(tài)梭姓。
解決策略:
1.通過(guò)參數(shù) innodb_lock_wait_timeout 來(lái)設(shè)置等待超時(shí)時(shí)間霜幼。
2。死鎖檢測(cè)誉尖,將參數(shù) innodb_deadlock_detect 設(shè)置為 on罪既,發(fā)現(xiàn)死鎖后,主動(dòng)回滾死鎖鏈條中的某一個(gè)事務(wù)铡恕,讓其他事務(wù)得以繼續(xù)執(zhí)行琢感。
3.其他:a.控制并發(fā)度,需要足夠的團(tuán)隊(duì)開(kāi)發(fā)mysql引擎探熔。b.把一個(gè)業(yè)務(wù)拆分多個(gè)表驹针,隨機(jī)對(duì)其中一個(gè)表修改。