binlog文件作為一次寫入,會(huì)在sync階段消耗大量的IO,會(huì)導(dǎo)致全庫hang主,狀態(tài)大多為query end。 大事務(wù)會(huì)造成導(dǎo)致主從延遲。 大事務(wù)可能導(dǎo)致某些需要備份掛起,原因在于flush table with read lock,拿不到MDL GLOBAL 級(jí)別的鎖,等待狀態(tài)為 Waiting for global read lock。 大事務(wù)可能導(dǎo)致更大Innodb row鎖加鎖范圍,導(dǎo)致row鎖等待問題。 回滾困難。 基于如上一些不完全的列舉,我們應(yīng)該在線上盡可能的避免大事務(wù)。好了我們下面來進(jìn)行問題討論。
PrintNotStarted print_not_started(file);//建立一個(gè)結(jié)構(gòu)體,目的是做not start 事務(wù)的打印 ut_list_map(trx_sys->mysql_trx_list, print_not_started); //這個(gè)地方打印出那些事務(wù)狀態(tài)是no start的事務(wù)。mysql_trx_list是全事務(wù)。 const trx_t* trx; TrxListIterator trx_iter; //這個(gè)迭代器是trx_sys->rw_trx_list 這個(gè)鏈表的迭代器 const trx_t* prev_trx = 0; /* Control whether a block should be fetched from the buffer pool. */ bool load_block = true; bool monitor = srv_print_innodb_lock_monitor && (srv_show_locks_held != 0); while ((trx = trx_iter.current()) != 0) { //通過迭代器進(jìn)行迭代 ,顯然這里不會(huì)有只讀事務(wù)的信息,全部是讀寫事務(wù)。 ... /* If we need to print the locked record contents then we need to fetch the containing block from the buffer pool. */ if (monitor) { /* Print the locks owned by the current transaction. */ TrxLockIterator& lock_iter = trx_iter.lock_iter(); if (!lock_trx_print_locks( //打印出鎖的詳細(xì)信息 file, trx, lock_iter, load_block)) 簡(jiǎn)單的說就是先打印哪些處于not start的事務(wù),然后打印那些讀寫事務(wù)的信息,當(dāng)然我們的回滾事務(wù)肯定也包含在其中了,需要注意的是只讀事務(wù)show engine不會(huì)打印。 對(duì)于處于回滾狀態(tài)的事務(wù)我們可以在show engine中觀察到如下信息:
MySQL 5.6版本 有大事務(wù)的存在,大概100G左右的數(shù)據(jù)加行鎖了 使用了show engine innodb status 這樣當(dāng)在統(tǒng)計(jì)這個(gè)大事務(wù)行鎖個(gè)數(shù)的時(shí)候,就會(huì)進(jìn)行大量的循環(huán)操作。從現(xiàn)象上看就是線程消耗了大量的CPU資源,并且處于perf top的第一位。