成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

完蛋,公司被一條Update語句干趴了!

運維 數據庫運維
昨晚在群劃水的時候,看到有位讀者說了這么一件事。

[[423960]]

圖片來自 包圖網

大概就是,在線上執行一條 update 語句修改數據庫數據的時候,where 條件沒有帶上索引,導致業務直接崩了,被老板教訓了一波。

這次我們就來看看:

  • 為什么會發生這種的事故?
  • 又該如何避免這種事故的發生?

說個前提,接下來說的案例都是基于 InnoDB 存儲引擎,且事務的隔離級別是可重復讀。

為什么會發生這種的事故?

InnoDB 存儲引擎的默認事務隔離級別是「可重復讀」,但是在這個隔離級別下,在多個事務并發的時候,會出現幻讀的問題。

所謂的幻讀是指在同一事務下,連續執行兩次同樣的查詢語句,第二次的查詢語句可能會返回之前不存在的行。

因此 InnoDB 存儲引擎自己實現了行鎖,通過 next-key 鎖(記錄鎖和間隙鎖的組合)來鎖住記錄本身和記錄之間的“間隙”,防止其他事務在這個記錄之間插入新的記錄,從而避免了幻讀現象。

當我們執行 update 語句時,實際上是會對記錄加獨占鎖(X 鎖)的,如果其他事務對持有獨占鎖的記錄進行修改時是會被阻塞的。

另外,這個鎖并不是執行完 update 語句就會釋放的,而是會等事務結束時才會釋放。

在 InnoDB 事務中,對記錄加鎖帶基本單位是 next-key 鎖,但是會因為一些條件會退化成間隙鎖,或者記錄鎖。加鎖的位置準確的說,鎖是加在索引上的而非行上。

比如,在 update 語句的 where 條件使用了唯一索引,那么 next-key 鎖會退化成記錄鎖,也就是只會給一行記錄加鎖。

這里舉個例子,這里有一張數據庫表,其中 id 為主鍵索引。

假設有兩個事務的執行順序如下:

可以看到,事務 A 的 update 語句中 where 是等值查詢,并且 id 是唯一索引,所以只會對 id = 1 這條記錄加鎖,因此,事務 B 的更新操作并不會阻塞。

但是,在 update 語句的 where 條件沒有使用索引,就會全表掃描,于是就會對所有記錄加上 next-key 鎖(記錄鎖 + 間隙鎖),相當于把整個表鎖住了。

假設有兩個事務的執行順序如下:

可以看到,這次事務 B 的 update 語句被阻塞了。

這是因為事務 A的 update 語句中 where 條件沒有索引列,所有記錄都會被加鎖,也就是這條 update 語句產生了 4 個記錄鎖和 5 個間隙鎖,相當于鎖住了全表。

因此,當在數據量非常大的數據庫表執行 update 語句時,如果沒有使用索引,就會給全表的加上 next-key 鎖, 那么鎖就會持續很長一段時間,直到事務結束。

而這期間除了 select ... from 語句,其他語句都會被鎖住不能執行,業務會因此停滯,接下來等著你的,就是老板的挨罵。

那 update 語句的 where 帶上索引就能避免全表記錄加鎖了嗎?并不是。

關鍵還得看這條語句在執行過程中,優化器最終選擇的是索引掃描,還是全表掃描,如果走了全表掃描,就會對全表的記錄加鎖了。

又該如何避免這種事故的發生?

我們可以將 MySQL 里的 sql_safe_updates 參數設置為 1,開啟安全更新模式。

官方的解釋:

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.

大致的意思是,當 sql_safe_updates 設置為 1 時,update 語句必須滿足如下條件之一才能執行成功:

  • 使用 where,并且 where 條件中必須有索引列。
  • 使用 limit。
  • 同時使用 where 和 limit,此時 where 條件中可以沒有索引列。

delete 語句必須滿足如下條件之一才能執行成功:

  • 使用 where,并且 where 條件中必須有索引列。
  • 同時使用 where 和 limit,此時 where 條件中可以沒有索引列。

如果 where 條件帶上了索引列,但是優化器最終掃描選擇的是全表,而不是索引的話,我們可以使用 force index([index_name]) 可以告訴優化器使用哪個索引,以此避免有幾率鎖全表帶來的隱患。

總結

不要小看一條 update 語句,在生產機上使用不當可能會導致業務停滯,甚至崩潰。

當我們要執行 update 語句的時候,確保 where 條件中帶上了索引列,并且在測試機確認該語句是否走的是索引掃描,防止因為掃描全表,而對表中的所有記錄加上鎖。

我們可以打開 MySQL 里的 sql_safe_updates 參數,這樣可以預防 update 操作時 where 條件沒有帶上索引列。

如果發現即使在 where 條件中帶上了列索引列,優化器走的還是全標掃描,這時我們就要使用 force index([index_name]) 可以告訴優化器使用哪個索引。

這次就說到這啦,下次要小心點,別再被老板挨罵啦。

作者:小林

編輯:陶家龍

出處:轉載自公眾號小林coding(ID:CodingLin)

 

責任編輯:武曉燕 來源: 小林coding
相關推薦

2021-06-25 09:11:38

updateSQL數據庫

2023-11-01 16:50:58

2020-10-26 08:02:28

SQL慢查詢索引

2021-12-02 15:30:55

命令內存Linux

2025-06-04 08:20:30

2022-05-10 08:36:28

鏈路狀態協議IS-ISOSPF

2021-04-16 07:04:53

SQLOracle故障

2020-07-01 09:07:52

SQL索引語句

2025-05-12 08:27:25

2021-08-30 05:47:12

MySQL SQL 語句數據庫

2022-02-11 14:43:53

SQL語句C/S架構

2022-05-31 13:58:09

MySQL查詢語句

2023-10-06 15:29:07

MySQL數據庫更新

2017-10-23 15:17:42

技術業務職位

2024-12-17 06:20:00

MySQLSQL語句數據庫

2015-06-01 15:11:37

數據庫update

2021-02-09 09:50:21

SQLOracle應用

2024-01-03 17:42:32

SQL數據庫

2021-06-07 08:37:03

SQL 查詢語句

2021-04-30 15:07:53

防火墻電腦Windows
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美成人精品一区二区男人看 | 欧美国产视频 | 国产精品不卡 | 五月激情婷婷在线 | 午夜精品一区二区三区在线观看 | 欧美一级全黄 | 欧美第一区 | 日本黄色片免费在线观看 | 激情五月综合网 | 无码一区二区三区视频 | japan25hdxxxx日本 做a的各种视频 | 一区二区三区四区在线视频 | 亚洲综合视频 | 日韩欧美国产精品 | av久久 | 国产视频久 | 伊人焦久影院 | 亚洲精品一区在线观看 | 国产亚洲精品一区二区三区 | 日日夜夜天天 | 亚洲精品天堂 | 久久精品国产亚洲一区二区三区 | caoporn视频| 亚洲一区 中文字幕 | 九色 在线| 国产日韩欧美激情 | 人人性人人性碰国产 | 日韩精品在线一区 | 国产精品入口久久 | 久热精品在线 | 国产精品久久久久一区二区 | 日韩有码一区 | 久久久精品综合 | 欧美激情国产日韩精品一区18 | 精品久久久久久亚洲综合网 | 国产精品久久久久久久7电影 | 密室大逃脱第六季大神版在线观看 | 中文二区 | 91影院在线观看 | ww亚洲ww亚在线观看 | 国产成人在线播放 |