日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 一个死锁的分析

發布時間:2024/8/26 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 一个死锁的分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

死鎖信息如下:

*** (1) TRANSACTION:

TRANSACTION 4363766192, ACTIVE 0 sec

mysql tables in use 2, locked 2

LOCK WAIT 9 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 6

MySQL thread id 8822753, OS thread handle 0x7fca3025b700, query id 2302320886 *.*.*.* cashcoupon_oper Sending data

update keap_cash_coup_type a,(select sum(freezed_amount) freezedAmount,cash_coupon_type_id from keap_cash_transcation where transcation_id = 10000001415322882 group by cash_coupon_type_id)b set a.amount = a.amount-b.freezedAmount,a.locked_amount=a.locked_amount+b.freezedAmount where a.cash_coupon_type_id=b.cash_coupon_type_id

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 2280?page no 3 n bits 176?index `PRIMARY` of table `keap_ticket_cash`.`keap_cash_transcation` trx id 4363766192 lock mode?S locks?rec but not gap waiting


*** (2) TRANSACTION:

TRANSACTION 4363766191, ACTIVE 0 sec fetching rows, thread declared inside InnoDB 4999

mysql tables in use 2, locked 2

9 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 6

MySQL thread id 8822751, OS thread handle 0x7fc8718a1700, query id 2302320895 *.*.*.* cashcoupon_oper Sending data

update keap_cash_coup_type a,(select sum(freezed_amount) freezedAmount,cash_coupon_type_id from keap_cash_transcation where transcation_id = 10000001415322879 group by cash_coupon_type_id)b set a.amount = a.amount-b.freezedAmount,a.locked_amount=a.locked_amount+b.freezedAmount where a.cash_coupon_type_id=b.cash_coupon_type_id

*** (2) HOLDS THE LOCK(S):

RECORD LOCKS space?id 2280 page no 3 n bits 176?index `PRIMARY` of table `keap_ticket_cash`.`keap_cash_transcation` trx id 4363766191 lock_mode?X locks?rec but not gap


*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space?id 2280 page no 3 n bits 176?index `PRIMARY` of table `keap_ticket_cash`.`keap_cash_transcation` trx id 4363766191 lock mode?S locks?rec but not gap waiting

Record lock, heap no 103 PHYSICAL RECORD: n_fields 12; compact format; info bits 0


信息顯示兩個多表鏈接update的事務,事務一在等待表keap_cash_transcation表主鍵索引的S鎖,位置在第3頁的176字節處,事務二拿到了對應位置的鎖,而又在等待該位置S鎖,這種鎖等待看起來有點奇怪,明明已經拿到該位置的X鎖為什么還要去獲取S鎖,都知道mysql在對唯一索引做update和insert時是會先獲取S鎖再獲取X鎖,這感覺有點像,一步一步排查分析吧


首先查詢隔離級別好判斷加鎖粒度:

mysql> show global variables like "%iso%";

+---------------+----------------+

| Variable_name | Value ? ? ? ? ?|

+---------------+----------------+

| tx_isolation ?| READ-COMMITTED |

+---------------+----------------+

1 row in set (0.00 sec)


是RC提交讀隔離級別,知道了無gap鎖,只有針對行加鎖的情況,再仔細看看兩個事務的sql發現等待鎖的表keap_cash_transcation只是作為關聯條件并未更新字段,查看表結構都只有主鍵,transcation_id無索引,建兩個只有主鍵的零時表進行測試:

結構:

CREATE TABLE `t1`/`t2` (

??`id` int(11) DEFAULT NULL,

??`name` varchar(10) DEFAULT NULL,

??`id_1` int(11) NOT NULL AUTO_INCREMENT,

??PRIMARY KEY (`id_1`)

) ENGINE=InnoDB AUTO_INCREMENT=7


測試:


session 1: session 2:
select * from t1 for update;

update t2 join t1 on t1.id=t2.id set t2.age=10;

發生等待


mysql> select a.lock_trx_id,b.trx_mysql_thread_id,b.trx_query,a.lock_mode,a.lock_type from INNODB_LOCKs a join INNODB_trx b on a.lock_trx_id=b.trx_id\G;

*************************** 1. row ***************************

lock_trx_id: 18944085

trx_mysql_thread_id: 33762

??trx_query: update t2 join t1 on t1.id=t2.id set t2.age=10

??lock_mode: S

??lock_type: RECORD

??lock_page: 3

?lock_table: `test`.`t1`

*************************** 2. row ***************************

lock_trx_id: 18944084

trx_mysql_thread_id: 33761

??trx_query: NULL

??lock_mode: X

??lock_type: RECORD

??lock_page: 3

?lock_table: `test`.`t1`

2 rows in set (0.00 sec)


看出事務二的update在獲取t1表的S鎖,但是這條語句只對t1表做查詢匹配操作,兩個事務執行的語句調個順序看看結果

session 1 session 2
update t2 join t1 on t1.id=t2.id set t2.age=10;

select * from t1 for update;

發生等待


*************************** 1. row ***************************

lock_trx_id: 18944086

trx_mysql_thread_id: 33761

??trx_query: select * from t1 for update

??lock_mode: X

??lock_type: RECORD

??lock_page: 3

?lock_table: `test`.`t1`

*************************** 2. row ***************************

lock_trx_id: 18944085

trx_mysql_thread_id: 33762

??trx_query: NULL

??lock_mode: S

??lock_type: RECORD

??lock_page: 3

?lock_table: `test`.`t1`

2 rows in set (0.01 sec)


事務二這時是在獲取X鎖,注意死鎖顯示都在獲取同一個位置的鎖,并且update拿到有X鎖,事務一的語句顯然是首先從t1表獲取S鎖,再獲取X鎖,最終獲取S鎖

加上索引再進行測試:


session 1 session 2

update t2 join t1 ?on (t1.id=t2.id and t1.id=4) set t2.age=10;



select * from t1 where id=4 for update;

正常無阻塞!

總結:

通過上面的測試基本已經清楚mysql在關聯update時,只是作為關聯查詢的表如果沒有對應索引會對滿足條件的行數據會進行加鎖操作,在t1表進行數據查詢時滿足id=4條件的所有數據都會加S鎖,和t2表關聯對數據進行判斷并做更新時對應的行會請求X鎖,當對數據更新完成后會釋放X鎖并請求S鎖,整個流程為 S-> X->S,如果未給t1表指明條件又以它作為驅動表的話就會造成t1表的記錄都會加鎖,在對條件字段id加了索引過后t1表不會產生阻塞,在生產環境中有這種關聯更新的語句需要注意索引的問題。


總結

以上是生活随笔為你收集整理的mysql 一个死锁的分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。