假設你想給別人說明,Mysql裏面是有鎖的,你會怎麼作?面試
大多數人,都會開兩個窗口,分別起兩個事務,而後update同一條記錄,在發起第二次update請求時,block,這樣就說明這行記錄被鎖住了(若是是RR,那麼鎖住的不僅是這行記錄):sql
問題來了,貌似只有顯式的開啓一個事務,纔會有鎖,若是直接執行一條update語句,會不會加鎖呢?數據庫
好比直接執行:安全
update t set c = c + 1 where id = 1;
這條語句,前面不加begin,不顯式開啓事務,那麼Mysql會不會加鎖呢?多線程
直覺告訴你,會。架構
可是爲何要加鎖?併發
給你五秒鐘,說出答案。性能
...學習
學過多線程和併發的同窗,都知道下面這段代碼,若是不加鎖,就會有靈異事件:ui
I++;
開啓十個線程,執行1000次這段代碼,最後i有極大可能性,會小於1000。
這時候,用Java的套路,加鎖:
synchornize { I++; }
問題解決。
同理,對於數據庫,你能夠理解爲i,就是數據庫裏的一行記錄,i++這段代碼,就是一條update語句,而多線程,對應的就是數據庫裏的多個事務。
既然對內存中i的操做須要加鎖,保證併發安全,那麼對數據庫的記錄進行修改,也必須加鎖。
這道理很簡單,可是不少人,不曾想過。
爲何你們都喜歡用第一部分裏的例子來演示Mysql鎖?
由於開兩個事務,會block,夠直觀。
那麼問題又來了,爲何會block,或者說,爲何Mysql必定要等到commit了,纔去釋放鎖?
執行完一條update語句,就把鎖釋放了,不行嗎?
舉個例子就知道Mysql爲何要這麼幹了:
一開始數據是:{id:1,c:1}
接着事務A經過select .. for update,進行當前讀,查到了c=1
接着它繼續去更新,把c更新成3,假設這時候,事務A執行完update語句後,就把鎖釋放了
那麼就有了第4行,事務B過來更新,把c更新成4
結果到了第5行,事務A又來執行一次當前讀,讀到的c,居然是4,明明我上一步才把c改爲了3 ...
事務A不禁的發出怒吼:我爲何會看到了我不應看,我也不想看的東西?!
事務B的修改,竟然讓事務A看到了,這明目張膽的違反了事務ACID中的I,Isolation,隔離性(事務提交以前,對其餘事務不可見)。
因此,結論:Mysql爲了知足事務的隔離性,必須在commit才釋放鎖。
有人說,若是我是讀未提交(Read Uncommited)的隔離級別,能夠讀到對方未提交的東西,是否是就不須要知足隔離性,是否是就能夠不用等到commit才釋放鎖了?
非也。
仍是舉例子:
事務A是Read Committed,事務B是Read Uncommitted;
事務B執行了一條update語句,把c更新成了3
假設事務B以爲本身是讀未提交,就把鎖釋放了
那這時候事務A過來執行當前讀,讀到了c就是3
事務A讀到了別的事務沒有提交的東西,而事務A,還說本身是讀已提交,真是諷刺
根因在於,事務B很是自私,他以爲本身是讀未提交,就把鎖釋放了,結果讓別人也被「讀未提交」
顯然,Mysql不容許這麼自私的行爲存在。
結論:就算你是讀未提交,你也要等到commit了再釋放鎖。
都知道Mysql的行鎖,分爲X鎖和S鎖,爲何Mysql要這麼作呢?
這個簡單吧,一樣能夠類比Java的讀寫鎖:
It allows multiple threads to read a certain resource, but only one to write it, at a time.
容許多個線程同時讀,但只容許一個線程寫,既支持併發提升性能,又保證了併發安全。
最後來個難點的。
假設事務A鎖住了表T裏的一行記錄,這時候,你執行了一個DDL語句,想給這張表加個字段,這時候須要鎖表吧?可是因爲表裏有一行記錄被鎖住了,因此這時候鎖表時會block。
那Mysql在鎖表時,怎麼判斷表裏有沒有記錄被鎖住呢?
最簡單暴力的,遍歷整張表,遍歷每行記錄,遇到一個鎖,就說明表裏加鎖了。
這樣作能夠,可是很傻,性能不好,高性能的Mysql,不容許這樣的作法存在。
Mysql會怎麼作呢?
行鎖是行級別的,粒度比較小,好,那我要你在拿行鎖以前,必須先拿一個假的表鎖,表示你想去鎖住表裏的某一行或者多行記錄。
這樣,Mysql在判斷表裏有沒有記錄被鎖定,就不須要遍歷整張表了,它只須要看看,有沒有人拿了這個假的表鎖。
這個假的表鎖,就是咱們常說的,意向鎖。
Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table
不少人知道意向鎖是什麼,可是殊不知道爲何須要一個粒度比較大的鎖,不知道它爲什麼而來,不知道Mysql爲什麼要設計個意向鎖出來。
知其然,知其因此然。
以爲不錯請點贊支持,歡迎留言或進個人我的羣855801563領取【架構資料專題目合集90期】、【BATJTMD大廠JAVA面試真題1000+】,本羣專用於學習交流技術、分享面試機會,拒絕廣告,我也會在羣內不按期答題、探討