日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

MySQL死鎖產生的原因和解決方法

瀏覽:36日期:2023-07-28 19:59:55
目錄前言鎖類型死鎖產生原因和示例1、產生原因:2、產生示例:案例一案例二死鎖檢查處理查看當前鏈接查看當前正在被鎖的事務查看當前等待鎖的事務查看當前未提交的事務查看正在被訪問的表死鎖異常查看最近一個死鎖情況相關參數配置死鎖日志鎖等待超時事務回滾Command='Sleep'總結前言

最近經常碰到mysql又死鎖了導致業務報錯。今天我們就來聊聊死鎖以及怎么解決

鎖類型

mysql鎖級別:頁級、表級、行級

表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高。頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般死鎖產生原因和示例1、產生原因:

死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.此時稱系統處于死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。表級鎖不會產生死鎖.所以解決死鎖主要還是針對于最常用的InnoDB。

死鎖的關鍵在于:兩個(或以上)的Session加鎖的順序不一致。

那么對應的解決死鎖問題的關鍵就是:讓不同的session加鎖有次序

2、產生示例:案例一

需求:將投資的錢拆成幾份隨機分配給借款人。

起初業務程序思路是這樣的:

投資人投資后,將金額隨機分為幾份,然后隨機從借款人表里面選幾個,然后通過一條條select for update 去更新借款人表里面的余額等。

例如兩個用戶同時投資,A用戶金額隨機分為2份,分給借款人1,2

B用戶金額隨機分為2份,分給借款人2,1

由于加鎖的順序不一樣,死鎖當然很快就出現了。

對于這個問題的改進很簡單,直接把所有分配到的借款人直接一次鎖住就行了。

Select * from xxx where id in (xx,xx,xx) for update

在in里面的列表值mysql是會自動從小到大排序,加鎖也是一條條從小到大加的鎖

第一個會話:

注意:關閉掉自動提交set autocommit=0;

mysql> select * from goods where goods_id in (2,3) for update;+----+--------+------+---------------------+| good_id | goods_name | price |+----+--------+------+---------------------+| 2 | bbbb | 1.00 || 3 | vvv | 3.00 |+----+--------+------+---------------------+

第二個會話:

select * from goods where goods_id in (3,4,5) for update;

鎖等待中……

案例二

在開發中,經常會做這類的判斷需求:根據字段值查詢(有索引),如果不存在,則插入;否則更新。

以id為主鍵為例,目前還沒有id=22的行

注意:關閉掉自動提交set autocommit=0;

第一個會話:

select * from goods where goods_id=22 for update;

第二個會話:

select * from goods where goods_id=23 for update;

再在第一個會話:

insert into goods values(22,'ac',11.5);

鎖等待中……

再到第二個會話:

insert into goods values(23,'bc',23.0);

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

當對存在的行進行鎖的時候(主鍵),mysql就只有行鎖。

當對未存在的行進行鎖的時候(即使條件為主鍵),mysql是會鎖住一段范圍

鎖住的范圍為:

(無窮小或小于表中鎖住id的最大值,無窮大或大于表中鎖住id的最小值)

如一:如果表中目前有已有的id為(11 , 12)

那么就鎖?。?2,無窮大)

如二:如果表中目前已有的id為(11 , 30)

那么就鎖住(11,30)

對于這種死鎖的解決辦法是:

insert into goods(xx,xx) on duplicate key update `xx`='XX';

用mysql特有的語法來解決此問題。因為insert語句對于主鍵來說,插入的行不管有沒有存在,都會只有行鎖

死鎖檢查處理

正常情況下,死鎖發生時,權重最小的連接將被kill并回滾。但是為了找出語句來優化,啟用可啟用死鎖將死鎖信息記錄下來。

#step 1:窗口一mysql> start transaction;mysql> update aa set name='aaa' where id = 1;#step 2:窗口二mysql> start transaction;mysql> update bb set name='bbb' where id = 1;#step 3:窗口一mysql> update bb set name='bbb';

查看方式

#step 4:窗口三#是否自動提交mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | ON |+---------------+-------+查看當前鏈接#查看當前連接mysql> show processlist;mysql> show full processlist;mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;+----+------+-----------+------+---------+------+-------+------------------+| Id | User | Host | db | Command | Time | State | Info |+----+------+-----------+------+---------+------+-------+------------------+| 4 | root | localhost | test | Sleep | 244 | | NULL || 5 | root | localhost | test | Sleep | 111 | | NULL || 6 | root | localhost | NULL | Query | 0 | init | show processlist |+----+------+-----------+------+---------+------+-------+------------------+id列:一個標識,你要kill 一個語句的時候很有用。user列: 顯示當前用戶,如果不是root,這個命令就只顯示你權限范圍內的sql語句。host列:顯示這個語句是從哪個ip 的哪個端口上發出的??捎脕碜粉櫝鰡栴}語句的用戶。db列:顯示這個進程目前連接的是哪個數據庫。command列:顯示當前連接的執行的命令,一般就是休眠(sleep),查詢(query),連接(connect)time列:此這個狀態持續的時間,單位是秒。

這個命令中最關鍵的就是state列,mysql列出的狀態主要有以下幾種:

Checking table

正在檢查數據表(這是自動的)。

Closing tables

正在將表中修改的數據刷新到磁盤中,同時正在關閉已經用完的表。這是一個很快的操作,如果不是這樣的話,就應該確認磁盤空間是否已經滿了或者磁盤是否正處于重負中。

Connect Out

復制從服務器正在連接主服務器。

Copying to tmp table on disk

由于臨時結果集大于tmp_table_size,正在將臨時表從內存存儲轉為磁盤存儲以此節省內存。

Creating tmp table

正在創建臨時表以存放部分查詢結果。

deleting from main table

服務器正在執行多表刪除中的第一部分,剛刪除第一個表。

deleting from reference tables

服務器正在執行多表刪除中的第二部分,正在刪除其他表的記錄。

Flushing tables

正在執行FLUSH TABLES,等待其他線程關閉數據表。

Killed

發送了一個kill請求給某線程,那么這個線程將會檢查kill標志位,同時會放棄下一個kill請求。MySQL會在每次的主循環中檢查kill標志位,不過有些情況下該線程可能會過一小段才能死掉。如果該線程程被其他線程鎖住了,那么kill請求會在鎖釋放時馬上生效。

Locked

被其他查詢鎖住了。

Sending data

正在處理SELECT查詢的記錄,同時正在把結果發送給客戶端。

Sorting for group

正在為GROUP BY做排序。

Sorting for order

正在為ORDER BY做排序。

Opening tables

這個過程應該會很快,除非受到其他因素的干擾。例如,在執ALTER TABLE或LOCK TABLE語句行完以前,數據表無法被其他線程打開。正嘗試打開一個表。

Removing duplicates

正在執行一個SELECT DISTINCT方式的查詢,但是MySQL無法在前一個階段優化掉那些重復的記錄。因此,MySQL需要再次去掉重復的記錄,然后再把結果發送給客戶端。

Reopen table

獲得了對一個表的鎖,但是必須在表結構修改之后才能獲得這個鎖。已經釋放鎖,關閉數據表,正嘗試重新打開數據表。

Repair by sorting

修復指令正在排序以創建索引。

Repair with keycache

修復指令正在利用索引緩存一個一個地創建新索引。它會比Repair by sorting慢些。

Searching rows for update

正在講符合條件的記錄找出來以備更新。它必須在UPDATE要修改相關的記錄之前就完成了。

Sleeping

正在等待客戶端發送新請求.

System lock

正在等待取得一個外部的系統鎖。如果當前沒有運行多個mysqld服務器同時請求同一個表,那么可以通過增加--skip-external-locking參數來禁止外部系統鎖。

Upgrading lock

INSERT DELAYED正在嘗試取得一個鎖表以插入新記錄。

Updating

正在搜索匹配的記錄,并且修改它們。

User Lock

正在等待GET_LOCK()。

Waiting for tables

該線程得到通知,數據表結構已經被修改了,需要重新打開數據表以取得新的結構。然后,為了能的重新打開數據表,必須等到所有其他線程關閉這個表。以下幾種情況下會產生這個通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。

Waiting for handler insert

INSERT DELAYED已經處理完了所有待處理的插入操作,正在等待新的請求。

查看當前正在被鎖的事務 #查看當前正在被鎖的事務(鎖請求超時后則查不到)mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+| 130718495:65:3:4 | 130718495 | X | RECORD | `test`.`bb` | GEN_CLUST_INDEX | 65 | 3 |4 | 0x000000000300 || 130718496:65:3:4 | 130718496 | X | RECORD | `test`.`bb` | GEN_CLUST_INDEX | 65 | 3 |4 | 0x000000000300 |+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+查看當前等待鎖的事務#查看當前等待鎖的事務(鎖請求超時后則查不到)mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; +-------------------+-------------------+-----------------+------------------+| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |+-------------------+-------------------+-----------------+------------------+| 130718499 | 130718499:65:3:4 | 130718500 | 130718500:65:3:4 |+-------------------+-------------------+-----------------+------------------+查看當前未提交的事務 #查看當前未提交的事務(如果死鎖等待超時,事務可能還沒有關閉)mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

主要看箭頭指向的這幾個字段,如果有阻塞數據(不為0的就是阻塞的),找到后在根據下圖這個字段:try_mysql_thread_id 作為這條數據的主鍵id執行這個sql進行刪除: kill id ;(殺死對應id的進程).假設這里try_mysql_thread_id=14的這條數據是鎖了。我們執行 kill 14刪除就不再鎖表了。

查看正在被訪問的表#查看正在被訪問的表mysql> show OPEN TABLES where In_use > 0;+----------+-------+--------+-------------+| Database | Table | In_use | Name_locked |+----------+-------+--------+-------------+| test | bb | 1 | 0 |+----------+-------+--------+-------------+死鎖異常#step 3:窗口一 (若第三步中鎖請求太久,則出現鎖超時而終止執行)mysql> update bb set name='bbb';ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction#'窗口一' 鎖請求超時前,執行第五步,使死鎖產生,則該連接 '窗口二' 執行終止,'窗口一' 順利執行#step 5:窗口二mysql> update aa set name='aa';ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction查看最近一個死鎖情況mysql> SHOW ENGINE INNODB STATUS;相關參數配置死鎖日志#死鎖記錄只記錄最近一個死鎖信息,若要將每個死鎖信息都保存到錯誤日志,啟用以下參數:mysql> show variables like 'innodb_print_all_deadlocks';+----------------------------+-------+| Variable_name | Value |+----------------------------+-------+| innodb_print_all_deadlocks | OFF |+----------------------------+-------+鎖等待超時 #上面 【step 3:窗口一】若一直請求不到資源,默認50秒則出現鎖等待超時。mysql> show variables like 'innodb_lock_wait_timeout'; +--------------------------+-------+| Variable_name | Value |+--------------------------+-------+| innodb_lock_wait_timeout | 50 |+--------------------------+-------+ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction#設置全局變量 鎖等待超時為60秒(新的連接生效)#mysql> set session innodb_lock_wait_timeout=50; mysql> set global innodb_lock_wait_timeout=60; 事務回滾 #上面測試中,當事務中的某個語句超時只回滾該語句,事務的完整性屬于被破壞了。為了回滾這個事務,啟用以下參數:mysql> show variables like 'innodb_rollback_on_timeout';+----------------------------+-------+| Variable_name | Value |+----------------------------+-------+| innodb_rollback_on_timeout | OFF |+----------------------------+-------+

最終參數設置如下:(重啟服務重新連接測試)

[mysqld]log-error =/var/log/mysqld3306.loginnodb_lock_wait_timeout=60 #鎖請求超時時間(秒)innodb_rollback_on_timeout = 1 #事務中某個語句鎖請求超時將回滾真個事務innodb_print_all_deadlocks = 1 #死鎖都保存到錯誤日志Command='Sleep'

表示連接休眠,如果太多,可以手動刪除

#若手動刪除堵塞會話,刪除 Command='Sleep' 、無State、無Info、trx_weight 權重最小的。show processlist;SELECT trx_mysql_thread_id,trx_state,trx_started,trx_weight FROM INFORMATION_SCHEMA.INNODB_TRX;總結

上面是小編總結的mysql死鎖相關的內容,尤其是死鎖檢查處理,是比較實用的,小伙伴們可以參考。

到此這篇關于MySQL死鎖產生的原因和解決方法的文章就介紹到這了,更多相關MySQL死鎖內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: MySQL 數據庫
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
99视频精品视频高清免费| 婷婷精品在线| 精品欠久久久中文字幕加勒比| 国产精品亚洲二区| 国产午夜精品一区在线观看| 久久a爱视频| 日韩专区精品| 午夜一级久久| 国产亚洲久久| 国产传媒av在线| 免费av一区二区三区四区| 黄色成人91| 日韩视频一二区| 欧美91在线| 91精品久久久久久久久久不卡| 99国产精品| 欧美欧美黄在线二区| 久久久久久夜| 最新亚洲一区| 日本伊人久久| 国内精品美女在线观看| 蜜桃tv一区二区三区| 91p九色成人| 999久久久国产精品| 日本aⅴ亚洲精品中文乱码| 成人一区不卡| 亚洲精选久久| 97精品国产福利一区二区三区| 九九综合在线| 国产剧情一区二区在线观看| 亚洲综合在线电影| 中文字幕av亚洲精品一部二部| 精品国产一区二区三区性色av| 婷婷激情图片久久| 清纯唯美亚洲综合一区| 成人精品天堂一区二区三区| 亚洲精品日本| 精品国产美女a久久9999| 99亚洲视频| 精品国产成人| 日韩在线观看一区二区| 精品99久久| 蜜臀av一区二区三区| 精品免费av| 色综合视频一区二区三区日韩 | 国产一区二区三区不卡av | 青青草国产成人99久久| 久久久噜噜噜| 国产精品美女在线观看直播| 91成人精品视频| 国内揄拍国内精品久久| 亚洲无线观看| 激情综合亚洲| 国产一区二区视频在线看| 中文字幕日韩亚洲| 久久中文字幕二区| 卡一卡二国产精品| 亚洲欧美网站在线观看| 久久精品影视| 国产一区二区三区网| 国产日韩中文在线中文字幕| 国产精品免费看| 日韩精品欧美| 成人一区不卡| 精品久久影院| 欧美成a人片免费观看久久五月天| 午夜久久影院| 日韩精品欧美| 日韩高清欧美| 福利视频一区| 国产精品网址| 欧美日韩亚洲一区三区| 亚洲人成亚洲精品| 亚洲在线网站| 国产一区日韩一区| 亚洲精品.com| 欧美成人精品三级网站| 精品国产一区二区三区av片| 国产探花一区| 日韩激情一区二区| 亚洲天堂免费| 国产精品日韩欧美一区| 1000部精品久久久久久久久| 久久国产免费| 欧美丝袜一区| 欧美日韩国产免费观看视频| 成人久久一区| 国产一区亚洲| 国产国产精品| 最新亚洲激情| 亚洲一区av| 日韩区一区二| 国产日韩一区| 国产极品久久久久久久久波多结野 | 久久高清免费观看| 黄色成人91| 亚洲精品字幕| 日本精品国产| 欧美国产三级| 精品国产一区二区三区噜噜噜| 国产精品99久久久久久董美香| 国产精品亚洲片在线播放| 国产午夜精品一区在线观看| 久久99精品久久久野外观看| 免费观看亚洲天堂| 国产传媒在线观看| 欧美~级网站不卡| 久久xxxx精品视频| 日韩精品一区二区三区免费视频 | 久久精品高清| 午夜在线精品偷拍| 蜜桃视频免费观看一区| 日本视频一区二区| 精品九九久久| 蜜桃一区二区三区| 亚洲免费毛片| 免费日韩一区二区三区| 综合日韩av| 欧美1区2区3区| 亚洲精品高潮| 国产专区精品| 免费精品国产的网站免费观看| 夜夜精品视频| 91国内精品| 深夜视频一区二区| 亚洲精品乱码久久久久久蜜桃麻豆| 欧美片第1页综合| 亚洲激情社区| 国产精品啊啊啊| 色爱综合av| 综合一区av| 一区二区三区四区日本视频| 国产亚洲综合精品| 国产日韩在线观看视频| 国产日韩电影| 亚洲欧美视频| 国产亚洲欧美日韩精品一区二区三区| 精品日本视频| 日韩中文字幕亚洲一区二区va在线| 青青草91久久久久久久久| 日本激情一区| 涩涩涩久久久成人精品| 国产传媒在线| 三级久久三级久久久| 中文字幕高清在线播放| 亚洲人成网77777色在线播放 | 中文字幕在线看片| 亚洲精品综合| 欧美aa一级| 日韩精品亚洲专区在线观看| 久久精品伊人| 日韩视频1区| 亚洲国产一区二区三区在线播放| 久久不卡日韩美女| 免费观看日韩电影| 久久精品青草| 精品中文字幕一区二区三区| 中文字幕一区二区精品区| 国产成年精品| 91久久精品无嫩草影院| 国产在线日韩| 国产成人免费| 日本va欧美va瓶| 美女亚洲一区| 福利一区二区三区视频在线观看| 丝袜诱惑制服诱惑色一区在线观看 | av资源亚洲| 国产精品永久| 中文字幕av一区二区三区四区| 欧洲精品一区二区三区| 国产精品亚洲片在线播放| av不卡免费看| 日韩和的一区二在线| 精品国产一区二区三区2021| 欧美亚洲三级| 亚洲精品护士| 亚洲一区日本| 日韩一区欧美| 精品久久99| 欧美成a人片免费观看久久五月天| 亚洲尤物av| 天堂va蜜桃一区二区三区| 久久精品国产大片免费观看| 狠狠久久伊人| 欧美黄色一区二区| 日本视频一区二区| 亚洲色图综合| 久久国产66| 亚洲一区二区三区高清| 亚洲欧美伊人| 欧美综合另类| 久久久久中文| 亚洲天堂一区二区| 水蜜桃久久夜色精品一区| 欧美xxxx性| 国产福利资源一区| 欧美激情麻豆| 精品日本视频| www.九色在线| 蜜桃成人精品|