mysql insert into select大量数据插入比较慢_史上最全MySQL锁机制
本文主要記錄學(xué)習(xí)MyISAM 和 InnoDB 這兩個存儲引擎。
為什么要學(xué)習(xí)鎖機(jī)制
鎖是計算機(jī)協(xié)調(diào)多個進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。
因為數(shù)據(jù)也是一種供許多用戶共享的資源,如何保證數(shù)據(jù)并發(fā)訪問的一致性、有效性是所有數(shù)據(jù)庫必須解決的一個問題,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個重要因素,所以進(jìn)一步學(xué)習(xí)MySQL,就需要去了解它的鎖機(jī)制。
MySQL鎖概述:
相對其他數(shù)據(jù)庫而言,MySQL 的鎖機(jī)制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機(jī)制。比如,MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);BDB存儲引擎采用的是頁面鎖(page-level locking),但也支持表級鎖;InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認(rèn)情況下是采用行級鎖。MySQL這3種鎖的特性可大致歸納如下。
開銷、加鎖速度、死鎖、粒度、并發(fā)性能
①:表級鎖:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。
②:行級鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。
③:頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。
從上述特點可見,很難籠統(tǒng)地說哪種鎖更好,只能就具體應(yīng)用的特點來說哪種鎖更合適!僅從鎖的角度來說:表級鎖更適合于以查詢?yōu)橹?#xff0c;只有少量按索引條件更新數(shù)據(jù)的應(yīng)用,如Web應(yīng)用;而行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時又有并發(fā)查詢的應(yīng)用,如一些在線事務(wù)處理(OLTP)系統(tǒng)。由于BDB已經(jīng)被InnoDB取代,即將成為歷史(所以現(xiàn)在基本都在使用InnoDB存儲引擎)。
MyISAN存儲引擎
MyISAM 存儲引擎只支持表鎖,這也是 MySQL 開始幾個版本中唯一支持的鎖類型。
MySQL表級鎖
查詢表鎖爭用情況
mysql> show status like 'table%';+----------------------------+-------+| Variable_name | Value |+----------------------------+-------+| Table_locks_immediate | 4 || Table_locks_waited | 0 || Table_open_cache_hits | 4 || Table_open_cache_misses | 8 || Table_open_cache_overflows | 0 |+----------------------------+-------+5 rows in set (0.00 sec)如果 Table_locks_waited 的值比較高,則說明存在著較嚴(yán)重的表級鎖爭用情況。
MySQL的表級鎖的兩種模式
表共享讀鎖(Table Read Lock)
表獨占寫鎖(Table Write Lock)
MySQL中的表鎖兼容性:
| 讀鎖 | 是 | 是 | 否 |
| 寫鎖 | 是 | 否 | 否 |
也就是說,在MyISAM讀模式下,不會阻塞其它用戶的同一表讀操作,但是會阻塞寫操作;而在寫模式下,會同時阻塞其它用戶同一表的讀寫操作。
測試MyISAM的寫鎖模式
新建一個user表,引擎是MyISAM:
mysql> desc user;+---------+-------------+------+-----+---------+----------------+| Field | Type | | Key | Default | Extra |+---------+-------------+------+-----+---------+----------------+| id | int(11) | NO | PRI | | auto_increment || name | varchar(20) | YES | | | || age | int(3) | YES | | | || address | varchar(60) | YES | | | |+---------+-------------+------+-----+---------+----------------+4 rows in set (0.01 sec)| 獲得user表的鎖鎖定 mysql> lock table user write; Query OK, 0 rows affected (0.00 sec) mysql>select * from user; Empty set (0.00 sec) mysql> insert into user(id, name, age, address) values(1, 'test', 18, 'test address'); Query OK,1 row affected (0.02 sec) | |
| mysql> select * from userG 被阻塞了,一直卡住在這,沒有返回結(jié)果 | |
| mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) | 等待 |
| mysql> select * from userG ********** name: test age: 18 address: test address 1 row in set (5 min 29.61 sec) |
可以看出,通過lock table user write將user表鎖住后,其它用戶進(jìn)行對該表操作時,都會被阻塞。
測試MyISAM讀鎖
在用LOCK TABLES給表顯式加表鎖時,必須同時取得所有涉及到表的鎖,并且MySQL不支持鎖升級。也就是說,在執(zhí)行LOCK TABLES后,只能訪問顯式加鎖的這些表,不能訪問未加鎖的表;同時,如果加的是讀鎖,那么只能執(zhí)行查詢操作,而不能執(zhí)行更新操作。其實,在自動加鎖的情況下也基本如此,MyISAM總是一次獲得SQL語句所需要的全部鎖。這也正是MyISAM表不會出現(xiàn)死鎖(Deadlock Free)的原因。
| 獲得user表的讀鎖定 mysql> lock table user read; Query OK, 0 rows affected (0.00 sec) | |
| mysql> select * from user where id = 1 G 中從查詢速度中可以看出,sessionB并沒有被阻塞 1 row in set (0.00 sec) | |
| 由于沒有獲取order表的讀鎖定,所以不能查詢order表 mysql> select * from order; ERROR 1100 (HY000): Table 'order' was not locked with LOCK TABLES | 但是session B可以訪問oder表,不阻塞 mysql> select * from order; Empty set (0.00 sec) |
| 獲得讀鎖定時,不能進(jìn)行寫操作 mysql> update user set name = 'wahaha' where id = 1; ERROR 1099 (HY000): Table 'user' was locked with a READ lock and can't be updated | 其它session進(jìn)行更新操作時,會被阻塞 mysql> update user set name = 'wahaha' where id = 1; 等待ing |
| 釋放鎖 mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) | 等待 |
| mysql> update user set name = 'wahaha' where id = 1; Query OK, 1 row affected (1 min 6.43 sec) |
MyISAM支持并發(fā)插入
MyISAM表的讀和寫是串行的,但這是就總體而言的。在一定條件下,MyISAM表也支持查詢和插入操作的并發(fā)進(jìn)行。MyISAM存儲引擎有一個系統(tǒng)變量concurrent_insert,專門用以控制其并發(fā)插入的行為,其值分別可以為0、1或2。
當(dāng)concurrent_insert設(shè)置為0時,不允許并發(fā)插入。
當(dāng)concurrent_insert設(shè)置為1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進(jìn)程讀表的同時,另一個進(jìn)程從表尾插入記錄。這也是MySQL的默認(rèn)設(shè)置。
當(dāng)concurrent_insert設(shè)置為2時,無論MyISAM表中有沒有空洞,都允許在表尾并發(fā)插入記錄。
MyISAM的鎖調(diào)度
MyISAM存儲引擎的讀鎖和寫鎖是互斥的,讀寫操作是串行的。但它認(rèn)為寫鎖的優(yōu)先級比讀鎖高,所以即使讀請求先到鎖等待隊列,寫請求后到,寫鎖也會插到讀鎖請求之前!這也正是MyISAM表不太適合于有大量更新操作和查詢操作應(yīng)用的原因,因為,大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠(yuǎn)阻塞。可以通過一些設(shè)置來調(diào)節(jié)MyISAM的調(diào)度行為。
通過指定啟動參數(shù)low-priority-updates,使MyISAM引擎默認(rèn)給予讀請求以優(yōu)先的權(quán)利。
通過執(zhí)行命令SET LOW_PRIORITY_UPDATES=1,使該連接發(fā)出的更新請求優(yōu)先級降低。
通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優(yōu)先級。
雖然上面3種方法都是要么更新優(yōu)先,要么查詢優(yōu)先的方法,但還是可以用其來解決查詢相對重要的應(yīng)用(如用戶登錄系統(tǒng))中,讀鎖等待嚴(yán)重的問題。另外,MySQL也提供了一種折中的辦法來調(diào)節(jié)讀寫沖突,即給系統(tǒng)參數(shù)max_write_lock_count設(shè)置一個合適的值,當(dāng)一個表的讀鎖達(dá)到這個值后,MySQL就暫時將寫請求的優(yōu)先級降低,給讀進(jìn)程一定獲得鎖的機(jī)會。上面已經(jīng)討論了寫優(yōu)先調(diào)度機(jī)制帶來的問題和解決辦法。
這里還要強(qiáng)調(diào)一點:一些需要長時間運行的查詢操作,也會使寫進(jìn)程“餓死”!因此,應(yīng)用中應(yīng)盡量避免出現(xiàn)長時間運行的查詢操作,不要總想用一條SELECT語句來解決問題,因為這種看似巧妙的SQL語句,往往比較復(fù)雜,執(zhí)行時間較長,在可能的情況下可以通過使用中間表等措施對SQL語句做一定的“分解”,使每一步查詢都能在較短時間完成,從而減少鎖沖突。如果復(fù)雜查詢不可避免,應(yīng)盡量安排在數(shù)據(jù)庫空閑時段執(zhí)行,比如一些定期統(tǒng)計可以安排在夜間執(zhí)行。
InnoDB
InnoDB與MyISAM的最大不同有兩點:一是支持事務(wù)(TRANSACTION);二是采用了行級鎖。行級鎖與表級鎖本來就有許多不同之處,另外,事務(wù)的引入也帶來了一些新問題。
事務(wù)概念
學(xué)習(xí)Spring的時候,一般通過注解@Transitional就能啟動spring的事務(wù)管理,在MySQL中也同樣支持事務(wù)的四個原則ACID:
**A(Atomicity)原子性:**事務(wù)是一個原子操作單元,其對數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。
**C(Consistent)一致性:**在事務(wù)開始和完成時,數(shù)據(jù)都必須保持一致狀態(tài)。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持?jǐn)?shù)據(jù)的完整性;事務(wù)結(jié)束時,所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如B樹索引或雙向鏈表)也都必須是正確的。
**I(Isolation)隔離性:**數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的“獨立”環(huán)境執(zhí)行。這意味著事務(wù)處理過程中的中間狀態(tài)對外部是不可見的,反之亦然。
**D(Durable)持久性:**事務(wù)完成之后,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。
并發(fā)事務(wù)處理帶來的問題
相對于串行處理來說,并發(fā)事務(wù)處理能大大增加數(shù)據(jù)庫資源的利用率,提高數(shù)據(jù)庫系統(tǒng)的事務(wù)吞吐量,從而可以支持更多的用戶。但并發(fā)事務(wù)處理也會帶來一些問題,主要包括以下幾種情況。
更新丟失(Last update):A和B同時對一行數(shù)據(jù)進(jìn)行處理,A修改后進(jìn)行保存,然后B修改后進(jìn)行保存,這樣A的更新被覆蓋了,相當(dāng)于發(fā)生丟失更新的問題。所以可以在A事務(wù)未結(jié)束前,B不能訪問該記錄,這樣就能避免更新丟失的問題。
臟讀(Dirty Reads):A事務(wù)在對一條記錄做修改,但還未提交,這條記錄處于不一致的狀態(tài);這時,B事務(wù)也來讀同一條記錄,這時如果沒有加控制,B讀了未修改前的數(shù)據(jù),并根據(jù)該數(shù)據(jù)進(jìn)行進(jìn)一步處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象叫做“臟讀”
不可重復(fù)讀(Non-Repeatable Reads):B事務(wù)在讀取某些數(shù)據(jù)后的某個時間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變(被更新或者刪除了,例如A事務(wù)修改了)。這種現(xiàn)象叫做“不可重復(fù)讀”。
幻讀(Phantom Reads):A事務(wù)按照相同查詢條件,重新讀取之前檢索過得內(nèi)容,卻發(fā)現(xiàn)其它事務(wù)插入或修改其查詢條件的新數(shù)據(jù),這種現(xiàn)象就叫”幻讀“。
事務(wù)的隔離級別
數(shù)據(jù)庫的事務(wù)隔離越嚴(yán)格,并發(fā)副作用越小,但付出的代價也就越大,因為事務(wù)隔離實質(zhì)上就是使事務(wù)在一定程度上 “串行化”進(jìn)行,這顯然與“并發(fā)”是矛盾的。同時,不同的應(yīng)用對讀一致性和事務(wù)隔離程度的要求也是不同的,比如許多應(yīng)用對“不可重復(fù)讀”和“幻讀”并不敏感,可能更關(guān)心數(shù)據(jù)并發(fā)訪問的能力。
4種隔離級別比較
| 未提交讀(Read uncommitted) | 最低級別,只能保證不讀取 物理上損害的數(shù)據(jù) | 是 | 是 | 是 |
| 已提交讀(Read committed) | 語句級 | 否 | 是 | 是 |
| 可重復(fù)讀(Repeatable read) | 事務(wù)級 | 否 | 否 | 是 |
| 可序列化(Serializable) | 最高級別,事務(wù)級 | 否 | 否 | 否 |
獲取InnoDB行鎖爭用情況
檢查InnoDB_row_lock狀態(tài)變量來分析:
mysql> show status like 'InnoDB_row_lock%';+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 0 |
| Innodb_row_lock_time_avg | 0 |
| Innodb_row_lock_time_max | 0 |
| Innodb_row_lock_waits | 0 |
+-------------------------------+-------+
5 rows in set (0.00 sec)
復(fù)制代碼
如果InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比較高,表示鎖爭用情況比較嚴(yán)重。
InnoDB的行鎖模式以及加鎖方法
InnoDB實現(xiàn)了一下兩種類型的行鎖:
共享鎖(S):允許一個事務(wù)去多一行,阻止其它事務(wù)獲得相同數(shù)據(jù)集的排他鎖。
排他鎖(X): 允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其它事務(wù)獲得相同數(shù)據(jù)集的共享鎖和排他寫鎖。
另外,為了允許行鎖和表鎖共存,實現(xiàn)多粒度鎖機(jī)制,InnoDB還有兩種內(nèi)部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖。(感覺與MyISAM的表鎖機(jī)制類似)
意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖,事務(wù)在給一個數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖。
意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖。
InnoDB行鎖模式兼容性列表:
| X | 沖突 | 沖突 | 沖突 | 沖突 |
| IX | 沖突 | 兼容 | 沖突 | 兼容 |
| S | 沖突 | 沖突 | 兼容 | 兼容 |
| IS | 沖突 | 兼容 | 兼容 | 兼容 |
如果一個事務(wù)請求的鎖模式與當(dāng)前的鎖兼容,InnoDB就將請求的鎖授予該事務(wù);反之,如果兩者不兼容,該事務(wù)就要等待鎖釋放。意向鎖是InnoDB自動加的;對于UPDATE、DELETE和INSERT語句,InnoDB會自動給設(shè)計數(shù)據(jù)集加排他鎖(X);對于普通的SELECT語句,InnoDB不會加鎖。可以通過以下語句顯示給記錄集加共享鎖或排他鎖:
共享鎖(S):SELECT * FROM TABLE_NAME WHERE ... LOCK IN SHARE MODE.
排他鎖(X):SELECT * FROM TABLE_NAME WHERE ... FOR UPDATE.
用SELECT ... IN SHARE MODE獲得共享鎖,主要用在需要數(shù)據(jù)依存關(guān)系時來確認(rèn)某行記錄是否存在,并確保沒有人對這個記錄進(jìn)行UPDATE或者DELETE操作。但是如果當(dāng)前事務(wù)也需要對該記錄進(jìn)行更新操作,則很有可能造成死鎖,對于鎖定行記錄后需要進(jìn)行更新操作的應(yīng)用,應(yīng)該使用SELECT... FOR UPDATE方式獲得排他鎖。
所以在使用共享鎖模式下,查詢完數(shù)據(jù)后不要進(jìn)行更新操作,不然又可能會造成死鎖;要更新數(shù)據(jù),應(yīng)該使用排他鎖模式。
InnoDB行鎖實現(xiàn)方式
InnoDB行鎖是通過給索引上的索引項加鎖來實現(xiàn)的,這一點MySQL與Oracle不同,后者是通過在數(shù)據(jù)塊中對相應(yīng)數(shù)據(jù)行加鎖來實現(xiàn)的。InnoDB這種行鎖實現(xiàn)特點意味著:只有通過索引條件檢索數(shù)據(jù),InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!(這個問題遇到過,由于沒加索引,行鎖變表鎖)
在不通過索引條件查詢的時候,InnoDB確實使用的是表鎖,而不是行鎖。
由于MySQL的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現(xiàn)鎖沖突的。
當(dāng)表有多個索引的時候,不同的事務(wù)可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB都會使用行鎖來對數(shù)據(jù)加鎖。
即便在條件中使用了索引字段,但是否使用索引來檢索數(shù)據(jù)是由MySQL通過判斷不同執(zhí)行計劃的代價來決定的,如果MySQL認(rèn)為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB將使用表鎖,而不是行鎖。
可以通過explain執(zhí)行計劃查看是否真正使用了索引。
間隙鎖(Next-key鎖)
當(dāng)我們用范圍條件而不是相等條件檢索數(shù)據(jù),并請求共享或排他鎖時,InnoDB會給符合條件的已有數(shù)據(jù)記錄的索引項加鎖;對于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做“間隙(GAP)”,InnoDB也會對這個“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖(Next-Key鎖)。
舉個例子:假如emp表中只有101條記錄,其id的值從1~101,下面的sql:select * from emp where id > 100 for update;是范圍條件查詢,InnoDB不僅會對符合條件的id值為101的記錄加鎖,也會對id大于101(并不存在的值)的“間隙”加鎖。
結(jié)論:
很顯然,在使用范圍條件檢索并鎖定記錄時,InnoDB這種加鎖機(jī)制會阻塞符合條件范圍內(nèi)鍵值的并發(fā)插入,這往往會造成嚴(yán)重的鎖等待。因此,在實際應(yīng)用開發(fā)中,尤其是并發(fā)插入比較多的應(yīng)用,我們要盡量優(yōu)化業(yè)務(wù)邏輯,盡量使用相等條件來訪問更新數(shù)據(jù),避免使用范圍條件。
關(guān)于死鎖(DeadLock)
上面知識點說過,MyISAM表鎖是deadlock free的,這是因為MyISAM總是一次獲得所需的全部鎖,要么全部滿足,要么等待,因此不會出現(xiàn)死鎖。但在InnoDB中,除單個SQL組成的事務(wù)外,鎖是逐步或得的,所以InnoDB發(fā)生死鎖是可能的。
舉個例子:
| mysql> set autocommit = 0; Query OK, 0 rows affected (0.00 sec) mysql> select * from table_1 where where id=1 for update; ... 做一些其他處理... | mysql> set autocommit = 0; Query OK, 0 rows affected (0.00 sec) mysql> select * from table_2 where id=1 for update; ... |
| select * from table_2 where id =1 for update; 因session_2已取得排他鎖,等待 | 做一些其他處理... |
| mysql> select * from table_1 where where id=1 for update; 死鎖 |
也就是我們死鎖產(chǎn)生的條件,互相持有資源不釋放,還有環(huán)形等待。
發(fā)生死鎖后,InnoDB一般都能自動檢測到,并使一個事務(wù)釋放鎖并回退,另一個事務(wù)獲得鎖,繼續(xù)完成事務(wù)。但在涉及外部鎖,或涉及表鎖的情況下,InnoDB并不能完全自動檢測到死鎖,這需要通過設(shè)置鎖等待超時參數(shù) innodb_lock_wait_timeout來解決。需要說明的是,這個參數(shù)并不是只用來解決死鎖問題,在并發(fā)訪問比較高的情況下,如果大量事務(wù)因無法立即獲得所需的鎖而掛起,會占用大量計算機(jī)資源,造成嚴(yán)重性能問題,甚至拖跨數(shù)據(jù)庫。我們通過設(shè)置合適的鎖等待超時閾值,可以避免這種情況發(fā)生。
避免死鎖的方法
在應(yīng)用中,如果不同的程序會并發(fā)存取多個表,應(yīng)盡量約定以相同的順序來訪問表,這樣可以大大降低產(chǎn)生死鎖的機(jī)會。在下面的例子中,由于兩個session訪問兩個表的順序不同,發(fā)生死鎖的機(jī)會就非常高!但如果以相同的順序來訪問,死鎖就可以避免。
在程序以批量方式處理數(shù)據(jù)的時候,如果事先對數(shù)據(jù)排序,保證每個線程按固定的順序來處理記錄,也可以大大降低出現(xiàn)死鎖的可能。
在事務(wù)中,如果要更新記錄,應(yīng)該直接申請足夠級別的鎖,即排他鎖,而不應(yīng)先申請共享鎖,更新時再申請排他鎖,因為當(dāng)用戶申請排他鎖時,其他事務(wù)可能又已經(jīng)獲得了相同記錄的共享鎖,從而造成鎖沖突,甚至死鎖。
在REPEATABLE-READ隔離級別下,如果兩個線程同時對相同條件記錄用SELECT...FOR UPDATE加排他鎖,在沒有符合該條件記錄情況下,兩個線程都會加鎖成功。程序發(fā)現(xiàn)記錄尚不存在,就試圖插入一條新記錄,如果兩個線程都這么做,就會出現(xiàn)死鎖。這種情況下,將隔離級別改成READ COMMITTED,就可避免問題。
當(dāng)隔離級別為READ COMMITTED時,如果兩個線程都先執(zhí)行SELECT...FOR UPDATE,判斷是否存在符合條件的記錄,如果沒有,就插入記錄。此時,只有一個線程能插入成功,另一個線程會出現(xiàn)鎖等待,當(dāng)?shù)?個線程提交后,第2個線程會因主鍵重出錯,但雖然這個線程出錯了,卻會獲得一個排他鎖!這時如果有第3個線程又來申請排他鎖,也會出現(xiàn)死鎖。
對于這種情況,可以直接做插入操作,然后再捕獲主鍵重異常,或者在遇到主鍵重錯誤時,總是執(zhí)行ROLLBACK釋放獲得的排他鎖
小結(jié)
這是一篇學(xué)習(xí)文章,關(guān)于MySQL的鎖機(jī)制又多了幾分了解,以后在寫SQL和排查問題時候,盡量避免死鎖和更快定位問題所在。
出處:https://juejin.im/post/5ce8eee45188253114078f2a
編輯:尹文敏
如何成為 DevOps 大牛?
DevOps 國際峰會 2019 · 北京站,
一線互聯(lián)網(wǎng)、金融、通信企業(yè) DevOps 落地實踐案例
Jenkins、Kubernetes、持續(xù)交付技術(shù)大咖為您分享落地案例
點擊閱讀原文,查看更多精彩
總結(jié)
以上是生活随笔為你收集整理的mysql insert into select大量数据插入比较慢_史上最全MySQL锁机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 投资小利润高的养殖业 农村创业者一定得知
- 下一篇: 加油卡积分怎么使用