Mysql資料庫併發插入死鎖問題及處理方式
Mysql有很多坑,對Mysql多執行緒支援這塊不是很熟的話就會莫名其妙地發生一些詭異的問題。多執行緒執行緒併發操作時最容易產生死鎖問題。所以很多大資料的操作一般都採用NoSQL資料庫方案來處理,或者讀寫分離,只需要做好冪等設計即可。
如何避免資料庫併發
1.通過資料庫連線池做分發處理:設定何時的資料庫連線池引數。
如配置:執行緒池大小,空閒時間,超時時間等。
2.永遠不要手動開啟執行緒插入資料:不要手動開啟執行緒去執行批量插入。
new Thread(new Runnable(){ public void run(){// 批量插入資料}}).start(); //執行緒內部批量執行插入
3.執行執行緒的時候儘量使用執行緒池而不是直接使用Threadpackage com.boonya.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class TaskRunnable implements Runnable { @Override public void run() { for (int x = 0; x < 100; x++) { Thread.sleep(1000);//休眠1000ms System.out.println("Do something:"+x); } } } public class ExecutorServiceDemo { public static void main(String[] args) { // 建立一個執行緒池物件,控制要建立幾個執行緒物件。 // public static ExecutorService newFixedThreadPool(int nThreads) ExecutorService pool = Executors.newFixedThreadPool(2); // 可以執行Runnable物件或者Callable物件代表的執行緒 pool.submit(new TaskRunnable ()); pool.submit(new TaskRunnable ()); //結束執行緒池 pool.shutdown(); } }
注:上面的執行緒池示例主要是為了節省系統資源佔用,順帶提一下。
如何處理死鎖問題
Mysql對插入問題的描述:
INSERT sets an exclusive lock on the inserted row. This lock is an index-record lock, not a next-key lock (that is, there is no gap lock) and does not prevent other sessions from inserting into the gap before the inserted row.Prior to inserting the row, a type of gap lock called an insertion intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.If a duplicate-key error occurs, a shared lock on the duplicate index record is set. This use of a shared lock can result in deadlock should there be multiple sessions trying to insert the same row if another session already has an exclusive lock.
大體的意思是:insert會對插入成功的行加上排它鎖,這個排它鎖是個記錄鎖,而非next-key鎖(當然更不是gap鎖了),不會阻止其他併發的事務往這條記錄之前插入記錄。在插入之前,會先在插入記錄所在的間隙加上一個插入意向gap鎖(簡稱I鎖吧),併發的事務可以對同一個gap加I鎖。如果insert 的事務出現了duplicate-key error ,事務會對duplicate index record加共享鎖。這個共享鎖在併發的情況下是會產生死鎖的,比如有兩個併發的insert都對要對同一條記錄加共享鎖,而此時這條記錄又被其他事務加上了排它鎖,排它鎖的事務提交或者回滾後,兩個併發的insert操作是會發生死鎖的。
1. 併發插入時,不在一個事務內進行再次事務提交。
2. 通過其他手段,如快取方案,解決這個要併發插入的問題。
3. 改併發為序列執行。
將併發處理都放入事務進行管理
事務管理的資料量不能太大,太大會造成資料庫插入併發死鎖。
處理死鎖表可以將資料庫表備份:然後重新建立匯入資料。
解鎖
第一種:
show processlist;
找到鎖程序,kill id ;
第二種:
mysql>UNLOCK TABLES;
鎖表
鎖定資料表,避免在備份過程中,表被更新
mysql>LOCK TABLES tbl_name READ;
為表增加一個寫鎖定:
mysql>LOCK TABLES tbl_name WRITE;