完蛋,公司被一條?update?語(yǔ)句干趴了!
- 為什么會(huì)發(fā)生這種的事故?
- 又該如何避免這種事故的發(fā)生?
但是,在 update 語(yǔ)句的 where 條件沒(méi)有使用索引,就會(huì)全表掃描,于是就會(huì)對(duì)所有記錄加上 next-key 鎖(記錄鎖 間隙鎖),相當(dāng)于把整個(gè)表鎖住了。假設(shè)有兩個(gè)事務(wù)的執(zhí)行順序如下:
select ... from
語(yǔ)句,其他語(yǔ)句都會(huì)被鎖住不能執(zhí)行,業(yè)務(wù)會(huì)因此停滯,接下來(lái)等著你的,就是老板的挨罵。那 update 語(yǔ)句的 where 帶上索引就能避免全表記錄加鎖了嗎?并不是。關(guān)鍵還得看這條語(yǔ)句在執(zhí)行過(guò)程中,優(yōu)化器最終選擇的是索引掃描,還是全表掃描,如果走了全表掃描,就會(huì)對(duì)全表的記錄加鎖了。2?又該如何避免這種事故的發(fā)生?我們可以將 MySQL 里的?sql_safe_updates
?參數(shù)設(shè)置為 1,開(kāi)啟安全更新模式。官方的解釋:大致的意思是,當(dāng) sql_safe_updates 設(shè)置為 1 時(shí)。update 語(yǔ)句必須滿足如下條件之一才能執(zhí)行成功:
If set to 1, MySQL aborts UPDATE or DELETE statements that do not use a key in the WHERE clause or a LIMIT clause. (Specifically, UPDATE statements must have a WHERE clause that uses a key or a LIMIT clause, or both. DELETE statements must have both.) This makes it possible to catch UPDATE or DELETE statements where keys are not used properly and that would probably change or delete a large number of rows. The default value is 0.
- 使用 where,并且 where 條件中必須有索引列;
- 使用 limit;
- 同時(shí)使用 where 和 limit,此時(shí) where 條件中可以沒(méi)有索引列;
- 使用 where,并且 where 條件中必須有索引列;
- 同時(shí)使用 where 和 limit,此時(shí) where 條件中可以沒(méi)有索引列;
force index([index_name])
?可以告訴優(yōu)化器使用哪個(gè)索引,以此避免有幾率鎖全表帶來(lái)的隱患。3?總結(jié)不要小看一條 update 語(yǔ)句,在生產(chǎn)機(jī)上使用不當(dāng)可能會(huì)導(dǎo)致業(yè)務(wù)停滯,甚至崩潰。當(dāng)我們要執(zhí)行 update 語(yǔ)句的時(shí)候,確保 where 條件中帶上了索引列,并且在測(cè)試機(jī)確認(rèn)該語(yǔ)句是否走的是索引掃描,防止因?yàn)閽呙枞恚鴮?duì)表中的所有記錄加上鎖。我們可以打開(kāi) MySQL 里的 sql_safe_updates 參數(shù),這樣可以預(yù)防 update 操作時(shí) where 條件沒(méi)有帶上索引列。如果發(fā)現(xiàn)即使在 where 條件中帶上了列索引列,優(yōu)化器走的還是全標(biāo)掃描,這時(shí)我們就要使用?force index([index_name])
?可以告訴優(yōu)化器使用哪個(gè)索引。這次就說(shuō)到這啦,下次要小心點(diǎn),別再被老板挨罵啦。