MySQL加锁实现的方式
https://www.aneasystone.com/archives/2017/11/solving-dead-locks-two.html,先了解如何加锁,死锁原因也就水落石出了
本文部分转自https://www.cnblogs.com/olinux/p/5497176.html
首先,通过show engine innodb status查看服务器信息以及定位问题。
| InnoDB | |
=====================================
2018-07-02 14:23:07 3054 INNODBMONITOROUTPUT
=====================================
Persecondaveragescalculatedfromthelast 40 seconds //最近40秒每2秒的平均值。
-----------------
BACKGROUNDTHREAD
-----------------
srv_master_threadloops: 7 srv_active, 0 srv_shutdown, 17879 srv_idle
srv_master_threadlogflushandwrites: 17886
----------
SEMAPHORES //信号
----------
OSWAITARRAYINFO: reservationcount 11 //OSwait的信息,表示innodb产生了11次的oswait
OSWAITARRAYINFO: signalcount 11 //进行OSwait线程,接收到11次single(信号)被唤醒,该数值越大,可能是i/o等待或者是innodb争用问题(与OS调度有关,可以尝试减少innodb_thread_concurrency参数(7.2中被移除))。
Mutexspinwaits 9,rounds 33,OSwaits 0 // Mutexspin线程无法获取锁而进入 SPinwait。rounds是spinwait进行轮询检查mutextes(互斥量)的次数,sowait线程。
RW-sharedspins 11,rounds 330,OSwaits 11 //RW-SHARED共享锁
RW-exclspins 0,rounds 0,OSwaits 0 // RW-excl排它锁
Spinroundsperwait: 3.67 mutex, 30.00 RW-shared, 0.00 RW-excl
// 备注:要明白Innodb如何处理互斥量(Mutexes),以及什么是两步获得锁(two-stepapproach)。首先进程,
试图获得一个锁,如果此锁被它人占用。它就会执行所谓的spinwait,即所谓循环的查询”锁被释放了吗?”。
如果在循环过程中,一直未得到锁释放的信息,则其转入OSWAIT,即所谓线程进入挂起(suspended)状态。
直到锁被释放后,通过信号(singal)唤醒线程
Spinwait的消耗远小于OSwaits。Spinwait利用cpu的空闲时间,检查锁的状态,
OSWait会有所谓contentswitch,从CPU内核中换出当前执行线程以供其它线程使用。
你可以通过innodb_sync_spin_loops参数来平衡spinwait和oswait
------------------------
LATESTDETECTEDDEADLOCK
------------------------
2016-05-11 18:52:09 2b6677e07700 //死锁发生的时间
*** (1) TRANSACTION:
TRANSACTION 495116414,ACTIVE 0.092 secfetchingrows
mysqltablesinuse 1,locked 1
LOCKWAIT 14 lockstruct(s),heapsize 6544, 20 rowlock(s),undologentries 6
LOCKBLOCKINGMySQLthreadid: 870003 block 876753
MySQLthreadid 876753,OSthreadhandle 0x2b6685903700,queryid 31567741510.168.152.132 dscSearchingrowsforupdate
updateaaaa
setxxx=xxx+(-1)
whereid=412 andxxx+(-1)>=0 //显示第一个死锁的的第一个事务
*** (1) WAITINGFORTHISLOCKTOBEGRANTED:
RECORDLOCKSspaceid 558 pageno 5 nbits 144 index `idx_aaaa_unique` oftable `test`.`aaaa` trxid 495116414 lock_modeXlocksrecbutnotgapwaiting
Recordlock,heapno 17 PHYSICALRECORD: n_fields 23; compactformat; infobits 0
// 以上表示死锁发生时事务1等待的锁,事务想获得aaaa表的idx_aaaa_unique索引对应的X排他锁(Innodb的锁是与索引相关)
0: len 8; hex 8000000000000001; asc ;;
1: len 2; hex 5748; ascWH;;
2: len 8; hex 800000000000004b; asc K;;
3: len 8; hex 8000000000000002; asc ;;
4: len 8; hex 8000000000002725; asc '%;;
5: len 8; hex 8000000000000215; asc ;;
6: len 2; hex 5a50; ascZP;;
7: len 8; hex 4231363033313441; ascB160314A;;
8: len 6; hex 00001d82e06a; asc j;;
9: len 7; hex 1d00000235151a; asc 5 ;;
10: len 8; hex 800000000000019c; asc ;;
11: len 8; hex 8000000000000000; asc ;;
12: len 5; hex 9998da0000; asc ;;
13: len 5; hex 999f5a0000; asc Z ;;
14: len 10; hex 5a303230323032303031; ascZ020202001;;
15: len 12; hexe5b9bfe4b89ce5b9bfe5b79e; asc ;;
16: len 4; hex 80001b2f; asc /;;
17: len 7; hex 80000000000000; asc ;;
18: len 23; hex 50555243484153455f4f524445525f494e5f53544f434b; ascPURCHASE_ORDER_IN_STOCK;;
19: len 22; hex53493230313630343136303030303136333531313735; ascSI20160416000016351175;;
20: len 5; hex 99992b1384; asc + ;;
21: SQLNULL;
22: len 5; hex 99994d7c8d; asc M| ;;
*** (2) TRANSACTION: // 事务2的状态
TRANSACTION 495116394,ACTIVE 0.246 secfetchingrows
mysqltablesinuse 1,locked 1
lockstruct(s),heapsize 2936, 18 rowlock(s),undologentries 21
MySQLthreadid 870003,OSthreadhandle 0x2b6677e07700,queryid 31567742610.168.152.132 dscSearchingrowsforupdate
updateaaaa
setxxx=xxx+(-2)
whereid=430 andxxx+(-2)>=0
*** (2) HOLDSTHELOCK(S): // 表示事务2获得的锁
RECORDLOCKSspaceid 558 pageno 5 nbits 144 index `idx_aaaa_unique` oftable `test`.`aaaa` trxid 495116394 lock_modeXlocksrecbutnotgap
Recordlock,heapno 17 PHYSICALRECORD: n_fields 23; compactformat; infobits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 2; hex 5748; ascWH;;
2: len 8; hex 800000000000004b; asc K;;
3: len 8; hex 8000000000000002; asc ;;
4: len 8; hex 8000000000002725; asc '%;;
5: len 8; hex 8000000000000215; asc ;;
6: len 2; hex 5a50; ascZP;;
7: len 8; hex 4231363033313441; ascB160314A;;
8: len 6; hex 00001d82e06a; asc j;;
9: len 7; hex 1d00000235151a; asc 5 ;;
10: len 8; hex 800000000000019c; asc ;;
11: len 8; hex 8000000000000000; asc ;;
12: len 5; hex 9998da0000; asc ;;
13: len 5; hex 999f5a0000; asc Z ;;
14: len 10; hex 5a303230323032303031; ascZ020202001;;
15: len 12; hexe5b9bfe4b89ce5b9bfe5b79e; asc ;;
16: len 4; hex 80001b2f; asc /;;
17: len 7; hex 80000000000000; asc ;;
18: len 23; hex 50555243484153455f4f524445525f494e5f53544f434b; ascPURCHASE_ORDER_IN_STOCK;;
19: len 22; hex53493230313630343136303030303136333531313735; ascSI20160416000016351175;;
20: len 5; hex 99992b1384; asc + ;;
21: SQLNULL;
22: len 5; hex 99994d7c8d; asc M| ;;
Recordlock,heapno 59 PHYSICALRECORD: n_fields 23; compactformat; infobits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 2; hex 5748; ascWH;;
2: len 8; hex 800000000000004b; asc K;;
3: len 8; hex 8000000000000002; asc ;;
4: len 8; hex 800000000000276a; asc 'j;;
5: len 8; hex 80000000000002c2; asc ;;
6: len 2; hex 5a50; ascZP;;
7: len 9; hex 423136303231374341;ascB160217CA;;
8: len 6; hex 00001d82e06a; asc j;;
9: len 7; hex 1d00000235169f; asc 5 ;;
10: len 8; hex 80000000000001db; asc ;;
11: len 8; hex 8000000000000000; asc ;;
12: len 5; hex 9998a20000; asc ;;
13: len 5; hex 99a2600000; asc ` ;;
14: len 10; hex 5a303230323032303031; ascZ020202001;;
15: len 12; hexe5b9bfe4b89ce5b9bfe5b79e; asc ;;
16: len 4; hex 80000772; asc r;;
17: len 7; hex 80000000000000; asc ;;
18: len 23; hex 50555243484153455f4f524445525f494e5f53544f434b; ascPURCHASE_ORDER_IN_STOCK;;
19: len 22; hex53493230313630343136303030303137333630353531; ascSI20160416000017360551;;
20: len 5; hex 99992b1385; asc + ;;
21: SQLNULL;
22: len 5; hex 99994d7c8d; asc M| ;;
*** (2) WAITINGFORTHISLOCKTOBEGRANTED: // 表示事务2等待的锁
RECORDLOCKSspaceid 558 pageno 4 nbits 152 index `idx_aaaa_unique` oftable `test`.`aaaa` trxid 495116394 lock_modeXlocksrecbutnotgapwaiting
Recordlock,heapno 63 PHYSICALRECORD: n_fields 23; compactformat; infobits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 2; hex 5748; ascWH;;
2: len 8; hex 800000000000004b; asc K;;
3: len 8; hex 8000000000000002; asc ;;
4: len 8; hex 8000000000000065; asc e;;
5: len 8; hex 80000000000000a8; asc ;;
6: len 2; hex 5a50; ascZP;;
7: len 9; hex 423136303232314b41; ascB160221KA;;
8: len 6; hex 00001d82e07e; asc ~;;
9: len 7; hex 2b000001d920ad; asc + ;;
10: len 8; hex 80000000000001c8; asc ;;
11: len 8; hex 8000000000000000; asc ;;
12: len 5; hex 9998aa0000; asc ;;
13: len 5; hex 99a2680000; asc h ;;
14: len 10; hex 5a303230323032303031; ascZ020202001;;
15: len 12; hexe5b9bfe4b89ce5b9bfe5b79e; asc ;;
16: len 4; hex 80000b14; asc ;;
17: len 7; hex 80000000000000; asc ;;
18: len 23; hex 50555243484153455f4f524445525f494e5f53544f434b; ascPURCHASE_ORDER_IN_STOCK;;
19: len 22; hex53493230313630343136303030303137333630353531; ascSI20160416000017360551;;
20: len 5; hex 99992b1385; asc + ;;
21: SQLNULL;
22: len 5; hex 99994d7c8d; asc M| ;;
*** WEROLLBACKTRANSACTION (1) // 表示选择了哪个事务回滚,避免无限期死锁等待
// innodb有一个内在的死锁检测工具,当死锁超过一定时间后,会回滚其中一个事务,innodb_lock_wait_timeout
可配置死锁等待超时时间
------------
TRANSACTIONS // 包含了InnoDB事务(transaction)的统计信息
------------
Trxidcounter 495910498 // 当前的transactionid,这是个系统变量,随着每次新的transaction产生而增加
Purgedonefortrx'sn:o < 495910389 undon:o < 0 state: runningbutidle //正在进行清空的操作操作的transactionID
Historylistlength 2606 // 记录了undospaces内unpurged的事务个数
//Purge的原则就是记录没有被其它事务继续使用了
LISTOFTRANSACTIONSFOREACHSESSION:
---TRANSACTION 329193748744296,notstarted
MySQLthreadid 909825,OSthreadhandle 0x2b6142bc7700,queryid 32577309210.143.34.172 dscinit
showengineinnodbstatus
---TRANSACTION 329193658413160,notstarted
MySQLthreadid 909832,OSthreadhandle 0x2b667d881700,queryid 32577302410.168.108.146 dsccleaningup
.....此处省略...
---TRANSACTION 329194102134888,notstarted
MySQLthreadid 886232,OSthreadhandle 0x2b6686c40700,queryid 32576927510.252.160.92 dsccleaningup
--------
FILEI/O // 显示了I/O Helperthreadd的状态,包含一些统计信息
--------
I/Othread 0 state: waitingfori/orequest (insertbufferthread)
I/Othread 1 state: waitingfori/orequest (logthread)
I/Othread 2 state: waitingfori/orequest (readthread)
I/Othread 3 state: waitingfori/orequest (readthread)
I/Othread 4 state: waitingfori/orequest (readthread)
I/Othread 5 state: waitingfori/orequest (readthread)
I/Othread 6 state: waitingfori/orequest (writethread)
I/Othread 7 state: waitingfori/orequest (writethread)
I/Othread 8 state: waitingfori/orequest (writethread)
I/Othread 9 state: waitingfori/orequest (writethread) // 以上显示了I/OHelperthread的状态
Pendingnormalaioreads: 0 [0, 0, 0, 0] ,aiowrites: 0 [0, 0, 0, 0] ,
ibufaioreads: 0,logi/o's: 0,synci/o's: 0
Pendingflushes (fsync) log: 0; bufferpool: 0 // 显示各个I/OHelperthread的pendingoperations,pending的log和bufferpoolthread的fsync()调用
OSfilereads, 61115257 OSfilewrites, 51279005 OSfsyncs //显示了readswritesfsync() 调用次数
0.00 reads/s, 0 avgbytes/read, 46.64 writes/s, 39.30 fsyncs/s
-------------------------------------
INSERTBUFFERANDADAPTIVEHASHINDEX
-------------------------------------
Ibuf: size 1,freelistlen 3606,segsize 3608, 38466 merges
// segsize表示当前插入缓冲的大小为3608*16KB,大约为57728KB。freelistlen代表了空闲列表的长度,merges表示合并次数
mergedoperations:
insert 34642,deletemark 1008134,delete 0 //insert插入的记录数,deletemark打上的标记,delete删除的次数
discardedoperations:
insert 0,deletemark 0,delete 0
AHIPARTITION 1: Hashtablesize 4980539,nodeheaphas 161 buffer(s)
AHIPARTITION 2: Hashtablesize 4980539,nodeheaphas 90 buffer(s)
AHIPARTITION 3: Hashtablesize 4980539,nodeheaphas 225 buffer(s)
AHIPARTITION 4: Hashtablesize 4980539,nodeheaphas 352 buffer(s)
AHIPARTITION 5: Hashtablesize 4980539,nodeheaphas 3556 buffer(s)
AHIPARTITION 6: Hashtablesize 4980539,nodeheaphas 4393 buffer(s)
AHIPARTITION 7: Hashtablesize 4980539,nodeheaphas 3052 buffer(s)
AHIPARTITION 8: Hashtablesize 4980539,nodeheaphas 145 buffer(s)
26.62 hashsearches/s, 51.78 non-hashsearches/s
---
LOG // 记录了transactionlog子系统的信息
---
Logsequencenumber 264509449071 //显示当前logsequencenumber表示有多少字节写入到log文件内
Logflushedupto 264509449064 //显示已经被flushed(写入磁盘)的logs
Pagesflushedupto 264509446093
Lastcheckpointat 264509412298 //显示最后一个checkpoint的logs
pendinglogflushes, 0 pendingchkpwrites
logi/o'sdone, 16.22 logi/o's/second // 显示pendinglog的统计信息
----------------------
BUFFERPOOLANDMEMORY
----------------------
Totalmemoryallocated 20653670400; inadditionalpoolallocated 0 // 显示分配给innodb的内存大小,以及additionalpool使用的大小 (0表示没有使用)
Dictionarymemoryallocated 1905658
Bufferpoolsize 1228800 // bufferpoolsize > databasepages因为bufferpoolsize还会存放lockindexhashindex等一些其他系统信息
Freebuffers 8192
Databasepages 1208634
Olddatabasepages 445992
Modifieddbpages 8
Pendingreads 0 //显示了pending的reads和writes
Pendingwrites: LRU 0,flushlist 0,singlepage 0 // 显示InnoDB读写和创建的页面(pages)
Pagesmadeyoung 842882,notyoung 127112054
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 2637230,created 729565,written 30484675
0.00 reads/s, 0.34 creates/s, 24.06 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000 //显示bufferpool的命中率
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 1208634,unzip_LRUlen: 0
I/Osum[9624]:cur[0],unzipsum[0]:cur[0]
----------------------
INDIVIDUALBUFFERPOOLINFO
----------------------
---BUFFERPOOL 0
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151095
Olddatabasepages 55755
Modifieddbpages 2
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 32021,notyoung 15238551
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 326672,created 90881,written 6387155
0.00 reads/s, 0.00 creates/s, 4.80 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151095,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 1
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151061
Olddatabasepages 55742
Modifieddbpages 0
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 32063,notyoung 15503760
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 327353,created 91471,written 978265
0.00 reads/s, 0.00 creates/s, 0.24 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151061,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 2
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151107
Olddatabasepages 55759
Modifieddbpages 0
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 32746,notyoung 14789866
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 328273,created 91339,written 4147582
0.00 reads/s, 0.00 creates/s, 3.50 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151107,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 3
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151088
Olddatabasepages 55752
Modifieddbpages 0
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 31950,notyoung 15539726
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 329629,created 91566,written 2998238
0.00 reads/s, 0.00 creates/s, 1.68 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151088,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 4
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151063
Olddatabasepages 55743
Modifieddbpages 1
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 323393,notyoung 17803631
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 337003,created 90967,written 3974291
0.00 reads/s, 0.08 creates/s, 4.38 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151063,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 5
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151066
Olddatabasepages 55744
Modifieddbpages 3
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 323468,notyoung 18135650
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 335789,created 90992,written 3382034
0.00 reads/s, 0.26 creates/s, 3.04 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151066,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 6
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151073
Olddatabasepages 55747
Modifieddbpages 2
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 34315,notyoung 15008240
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 324769,created 91064,written 5580181
0.00 reads/s, 0.00 creates/s, 4.66 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151073,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
---BUFFERPOOL 7
Bufferpoolsize 153600
Freebuffers 1024
Databasepages 151081
Olddatabasepages 55750
Modifieddbpages 0
Pendingreads 0
Pendingwrites: LRU 0,flushlist 0,singlepage 0
Pagesmadeyoung 32926,notyoung 15092630
0.00 youngs/s, 0.00 non-youngs/s
Pagesread 327742,created 91285,written 3036929
0.00 reads/s, 0.00 creates/s, 1.76 writes/s
Bufferpoolhitrate 1000 / 1000,young-makingrate 0 / 1000 not 0 / 1000
Pagesreadahead 0.00/s,evictedwithoutaccess 0.00/s,Randomreadahead 0.00/s
LRUlen: 151081,unzip_LRUlen: 0
I/Osum[1203]:cur[0],unzipsum[0]:cur[0]
--------------
ROWOPERATIONS //显示了rowoperations及其他一些统计信息
--------------
queriesinsideInnoDB, 0 queriesinqueue //显示了有多少个线程在InnoDB内核
readviewsopeninsideInnoDB // 有多少个readview被打开,一个readview是一致性保证MVCC "snapshot"
Mainthreadprocessno. 46196,id 47719070582528,state: sleeping //显示内核mainthread的状态信息。
Numberofrowsinserted 35803330,updated 3181469,deleted 14015545,read 7740416065
12.48 inserts/s, 0.68 updates/s, 0.30 deletes/s, 3005.82 reads/s
----------------------------
ENDOFINNODBMONITOROUTPUT
============================
首先 mysql> show full processlist;
查看当前的进程。可以看到被卡住的操作,但是由于之前的事务处于sleep状态,无法得知它到底执行了什么。
mysql> select* from information_schema.innodb_trx\G 这时我们查询innodb_trx表可看到事务1也看不到sql信息
例如:select * from information_schema.innodb_trx \G;
***************************1. row ***************************
trx_id: 23840
trx_state: RUNNING
trx_started: 2018-07-0214:21:55
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 1
trx_mysql_thread_id: 3
trx_query: select * from information_schema.innodb_trx
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 1
trx_lock_memory_bytes: 1184
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
trx_is_read_only: 0
trx_autocommit_non_locking: 0
*************************** 2. row***************************
trx_id: 23839
trx_state: RUNNING
trx_started: 2018-07-0214:20:50
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 3
trx_mysql_thread_id: 2
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 2
trx_lock_memory_bytes: 360
trx_rows_locked: 1
trx_rows_modified: 1
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
trx_is_read_only: 0
trx_autocommit_non_locking: 0
思路
1)第一种方法是利用performance_schema中的相关信息查询
mysql> showvariables like 'performance_schema';
+--------------------+-------+
|Variable_name | Value |
+--------------------+-------+
|performance_schema | ON |
+--------------------+-------+
1 row in set(0.00 sec)
通过查看events_statements_current表可看到每一个session正在执行的sql,哪怕它依旧执行完成了,只是没有提交。这里可看到事务1最后执行的正是update chen.a set cc ='ce' where id =1;
select * from performance_schema.events_statements_current \G;
***************************1. row ***************************
THREAD_ID: 23
EVENT_ID: 42
END_EVENT_ID: 42
EVENT_NAME: statement/sql/update
SOURCE: mysqld.cc:966
TIMER_START: 17772209118346530
TIMER_END: 17772209706292278
TIMER_WAIT: 587945748
LOCK_TIME: 144000000
SQL_TEXT: update chen.a set cc ='ce' where id =1
DIGEST: 7715f807a61a778aa252065205f86e25
DIGEST_TEXT: UPDATE `chen` . `a` SET `cc` = ? WHERE `id` = ?
CURRENT_SCHEMA: chen
OBJECT_TYPE: NULL
OBJECT_SCHEMA: NULL
OBJECT_NAME: NULL
OBJECT_INSTANCE_BEGIN: NULL
MYSQL_ERRNO: 0
RETURNED_SQLSTATE: 00000
MESSAGE_TEXT: Rows matched: 1 Changed: 1 Warnings: 0
ERRORS: 0
WARNINGS: 0
ROWS_AFFECTED: 1
ROWS_SENT: 0
ROWS_EXAMINED: 1
CREATED_TMP_DISK_TABLES: 0
CREATED_TMP_TABLES: 0
SELECT_FULL_JOIN: 0
SELECT_FULL_RANGE_JOIN: 0
SELECT_RANGE: 0
SELECT_RANGE_CHECK: 0
SELECT_SCAN: 0
SORT_MERGE_PASSES: 0
SORT_RANGE: 0
SORT_ROWS: 0
SORT_SCAN: 0
NO_INDEX_USED: 0
NO_GOOD_INDEX_USED: 0
NESTING_EVENT_ID: NULL
NESTING_EVENT_TYPE: NULL
不过方案1有个缺陷,一个事务可能有一组sql组成,这个方法只能看到这个事务最后执行的是什么SQL,无法看到全部。PS:关于information_schema.processlist和events_statements_current如何一一对应起来,可以查看performance_schema.threads表来关联,这里不多描述,给出一个可行的sql:select a.SQL_TEXT,c.id,d.trx_started from events_statements_current a join threads b on a.THREAD_ID=b.THREAD_ID join information_schema.processlist c on b.PROCESSLIST_ID=c.id join information_schema.innodb_trx d on c.id=d.trx_mysql_thread_id order by d.trx_started \G
2) 可以用general_log的方式,(需要开启general_log),(一般情况下general_log不会打开),即使事务没有提交,一样会写到general_log。
mysql> setglobal general_log=1;
Query OK, 0 rowsaffected (0.00 sec)
mysql> select* from mysql.general_log where thread_id=4;
+---------------------+---------------------------------------------+-----------+-----------+--------------+----------------------------------------------+
|event_time | user_host | thread_id| server_id | command_type | argument |
+---------------------+---------------------------------------------+-----------+-----------+--------------+----------------------------------------------+
| 2016-07-2715:20:12 | ucloudbackup[ucloudbackup] @ [10.9.24.168]| 4 |168368296 | Query | begin |
| 2016-07-2715:20:28 | ucloudbackup[ucloudbackup] @ [10.9.24.168]| 4 |168368296 | Query | insert intotest_lock values(2,'jiangjian1') |
| 2016-07-2715:20:33 | ucloudbackup[ucloudbackup] @ [10.9.24.168]| 4 |168368296 | Query | insert intotest_lock values(3,'song') |
| 2016-07-2715:20:37 | ucloudbackup[ucloudbackup] @ [10.9.24.168]| 4 |168368296 | Query | insert intotest_lock values(4,'luocheng') |
| 2016-07-2715:20:39 | ucloudbackup[ucloudbackup] @ [10.9.24.168]| 4 |168368296 | Query | updatetest_lock set id=123 where id=1 |
+---------------------+---------------------------------------------+-----------+-----------+--------------+----------------------------------------------+
5 rows in set(0.00 sec)
这样只要后续能否复现的话,就能找到所有的SQL了
3)假如后面应用层最终commit了,那么会在binlog里记录,可以根据当时的session id去binlog查看。