1.delete刪除不存在的資料導致死鎖
mysql的鎖分為三種(按照鎖定的行數劃分):
1.record lock:記錄鎖,也就是僅僅鎖著單獨的一行
2.gap lock:區間鎖,僅僅鎖住乙個區間(注意這裡的區間都是開區間,也就 是不包括邊界值,至於為什麼這麼定義?innodb官方定義的)
3.next-key lock:record lock+gap lock,所以next-key lock也就半開半閉區間,且是下界開,上界閉。(為什麼這麼定義?innodb官方定義的)
由於此處是在明確指定了no=xx的情況下丟擲了死鎖異常, 並且no建立的是普通索引, 所以此處mysql使用的應該是next-key lock(檢視何種情況下使用何種鎖
下面來舉個手冊上的例子看看next-key lock是如何上鎖的。假如乙個索引的行有10,11,13,20
那麼可能的next-key lock的包括:
(無窮小, 10]
(10,11]
(11,13]
(13,20]
(20, 無窮大)
因此對於delete刪除不存在的資料造成了區間鎖。
解決方法:
①先檢查記錄是否存在,否則不刪除
②對於同一條記錄,建議使用update
③如果鎖是gap鎖,這種死鎖需要將事務的隔離級別設定為read commit。
④對於等待鎖的的會話使用innodb_lock_wait_timeout,防止過載。
①沒有索引欄位的情況下不存在行鎖,如果加鎖,那麼排他鎖和共享鎖都會公升級為表鎖
②修改表結構時的鎖為表鎖
③修改大量資料的時候可以鎖表
④mysql的innodb儲存引擎實務鎖雖然是鎖行,但它內部是鎖索引的,根據where條件和select的值是否只有主鍵或非主鍵索引來判斷怎麼鎖,比如只有主鍵,則鎖主鍵索引,如果只有非主鍵,則鎖非主鍵索引,如果主鍵非主鍵都有,則內部會按照順序鎖
由於innodb預設是row-level lock,所以只有「明確」的指定主鍵,mysql才會執行row lock (只鎖住被選取的資料例) ,否則mysql將會執行table lock (將整個資料表單給鎖住)。
舉個例子:
假設有個表單products ,裡面有id跟name二個字段,id是主鍵。
例1: (明確指定主鍵,並且有此筆資料,row lock)
select * from products where id='3' for update;
select * from products where id='3' and type=1 for update;
例2: (明確指定主鍵,若查無此筆資料,無lock)
select * from products where id='-1' for update;
例2: (無主鍵,table lock)
select * from products where name='mouse' for update;
例3: (主鍵不明確,table lock)
select * from products where id<>'3' for update;
例4: (主鍵不明確,table lock)
select * from products where id like '3' for update;
例5:(主鍵不存在,gap鎖)
select * from products where id='50' for update; //假設50不存在
注1: for update僅適用於innodb,且必須在交易區塊(begin/commit)中才能生效。
注2: 要測試鎖定的狀況,可以利用mysql的command mode ,開二個視窗來做測試。
原文:mysql事物鎖等待超時
innodb_lock_wait_timeout
問題出現環境:
1、在同一事務內先後對同一條資料進行插入和更新操作;
2、多台伺服器操作同一資料庫;
3、瞬時出現高併發現象;
1、通過下面語句查詢到為提交事務的資料,kill掉此執行緒即可。
select * from information_schema.innodb_trx
2、增加鎖等待時間,即增大下面配置項引數值,單位為秒(s)
innodb_lock_wait_timeout=500
3、優化儲存過程,事務避免過長時間的等待。
①此引擎不支援事務、也不支援行鎖。
①表鎖有兩種模式:表共享讀鎖(table read lock)和表獨佔寫鎖(table write lock)
《 mysql併發時經典常見的死鎖原因及解決方法》
原因:uk衝突導致出現gap死鎖
解決方式:
方式一:不使用自增主鍵和索引,可以使用guid(uuid中獎重複的概率是中獎概率的32次方)。
方式二:降低事務的隔離級別
方式三:使用業務鎖,使得併發序列執行。
方式四:在方式一的基礎上,將生成的guid放入到redis佇列中,提前儲備一定數量,不足時再自動生成補充(推薦)。
方式五:snowflake演算法(twtter發明的)
對於有些記錄要求存在就更新、不存在就插入,可以使用如下方式
c on duplicate key update count=count+1;
也可以使用replace
insert into player_count(player_id,count) value(1,1)
解除正在死鎖的狀態有兩種方法:
第一種:
1.查詢是否鎖表
show open tables where in_use > 0;
2.查詢程序(如果您有super許可權,您可以看到所有執行緒。否則,您只能看到您自己的執行緒)
show processlist
3.殺死程序id(就是上面命令的id列)
kill id
第二種:
1.檢視下在鎖的事務
select * from information_schema.innodb_trx;
2.殺死程序id(就是上面命令的trx_mysql_thread_id列)
kill 執行緒id
其它關於檢視死鎖的命令:
1:檢視當前的事務
select * from information_schema.innodb_trx;
2:檢視當前鎖定的事務
select * from information_schema.innodb_locks;
3:檢視當前等鎖的事務
select * from information_schema.innodb_lock_waits;
mysql編碼不得不知的問題
1 檢視mysql相關編碼 檢視mysql資料庫所支援的編碼 showcharacterset 檢視當前變數中的一些編碼情況 show variableslike character 檢視某個資料庫的編碼 showcreatedatabasedb name 檢視某個表的字符集 showcreatet...
this指向 不得不看的this指向問題
分析this的指向共有四種型別 1 函式被呼叫時 即執行時 才會確定該函式內this的指向。因為在函式中this與arguments是兩個特殊的變數,在函式被呼叫時才會取得它們,而且搜尋這兩個變數時只會在活動物件範圍裡面去搜。2 要確定函式中this的指向,必須先找到該函式被呼叫的位置。認準第一種 ...
不得不說的「跳槽」
現實中不難發現 越是高階人才,適合的機會就越少 的現象。身處金字塔中上層的人員,無論是職位還是薪水,起點都很高,這客觀上造成適合的職位機會少,職業路徑轉換成本過高等問題。我個人認為,it技術高層人士,如果要跳槽,務必要注意三宜和三忌。忌 病急亂投醫 宜 方法得當 公升遷至較高職位的人,大多都多年不找...