Innodb中為什么lockinsharemode在showengine看不到行鎖信息

這篇文章主要介紹“Innodb中為什么lock in share mode在show engine看不到行鎖信息”,在日常操作中,相信很多人在Innodb中為什么lock in share mode在show engine看不到行鎖信息問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Innodb中為什么lock in share mode在show engine看不到行鎖信息”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設(shè)、翁源網(wǎng)站維護(hù)、網(wǎng)站推廣。

一、問題提出

不知道有沒有朋友和我一樣用lock in share mode做加鎖實(shí)驗(yàn),但是卻在show engine innodb status中看不到加鎖信息,今天剛好有朋友在問@在樹枝上吹風(fēng),今天就做了一下簡(jiǎn)單的debug,因?yàn)槲乙餐{悶的。(我喜歡多問一個(gè)為什么也挺累的)
問題如下:
首先我開啟了我的打印行鎖參數(shù),讓加鎖輸出到日志中

MySQL> show variables like '%gaopeng%';
+--------------------------------+-------+| Variable_name                  | Value |
+--------------------------------+-------+
| gaopeng_mdl_detail             | OFF   || innodb_gaopeng_row_lock_detail | ON    |
+--------------------------------+-------+

然后跑如下語句

mysql> show create table t \G
*************************** 1. row ***************************       Table: t
Create Table: CREATE TABLE `t` (  `id` int(11) NOT NULL,  `c` int(11) DEFAULT NULL,  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec)
mysql> select * from t;
+----+------+------+| id | c    | d    |+----+------+------+|  0 |    0 |    0 ||  5 |    5 |    5 || 10 |   10 |   10 || 15 |   15 |   15 || 20 |   20 |   20 || 25 |   25 |   25 |+----+------+------+6 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from t where id=0 lock in share mode;
+----+------+------+| id | c    | d    |+----+------+------+|  0 |    0 |    0 |+----+------+------+1 row in set (4.21 sec)

按理說這個(gè)時(shí)候應(yīng)該在主鍵ID=0這一行上了LOCK_S,但是show engine innodb卻看不到加鎖信息如下:

------------
TRANSACTIONS
------------
Trx id counter 241482
Purge done for trx's n:o < 241482 undo n:o < 0 state: running but idle
History list length 182
Total number of lock structs in row lock hash table 1
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 422211785606640, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 422211785605248, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
--------
FILE I/O
--------

根本看不到加鎖信息。但是我的日志中卻有輸出如下:

2019-03-20T14:37:41.980845+08:00 10 [Note] InnoDB: TRX ID:(0) table:test/t index:PRIMARY space_id: 95 page_id:3 heap_no:2 row lock mode:LOCK_S|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000000; asc     ;;
 1: len 6; hex 00000003676a; asc     gj;;
 2: len 7; hex d8000000330110; asc     3  ;;
 3: len 4; hex 80000000; asc     ;;
 4: len 4; hex 80000000; asc     ;;

因此我基本斷定加鎖肯定是做了的,但是為什么沒有輸出呢?

二、分析

我開始懷疑是否是提前釋放了或者是打印的時(shí)候過濾掉了?后來發(fā)現(xiàn)都不是??戳说搅艘粋€(gè)TRX_ID為422211785605248,這是只讀事物的TRX_ID的形式,會(huì)不是因?yàn)閼?yīng)打印的時(shí)候只會(huì)打印讀寫的事物的鎖結(jié)構(gòu)信息,因?yàn)镮nnodb中讀寫事物有一個(gè)獨(dú)立的鏈表,如果只打印這個(gè)鏈表上的信息就會(huì)出現(xiàn)這個(gè)問題。接著我做了一個(gè)事物先做了一個(gè)delete操作然后做lock in share mode語句可以看到LOCK_S結(jié)構(gòu)就可以看到了,如下:

mysql> begin;
Query OK, 0 rows affected (2.43 sec)
mysql> delete from t2 limit 1; ##這個(gè)語句我就顯示的開始了一個(gè)讀寫事物Query OK, 1 row affected (3.53 sec)
mysql> select * from t where id=0 lock in share mode; 
+----+------+------+| id | c    | d    |+----+------+------+|  0 |    0 |    0 |+----+------+------+1 row in set (2.98 sec)
mysql>

再來看看

---TRANSACTION 422211785606640, not started0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 422211785605248, not started0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 241482, ACTIVE 85 sec4 lock struct(s), heap size 1160, 2 row lock(s), undo log entries 1MySQL thread id 10, OS thread handle 140737153423104, query id 391 localhost root
TABLE LOCK table `test`.`t2` trx id 241482 lock mode IX
RECORD LOCKS space id 33 page no 19 n bits 624 index GEN_CLUST_INDEX of table `test`.`t2` trx id 241482 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 447 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
 0: len 6; hex 00000000451d; asc     E ;; 1: len 6; hex 00000003af4a; asc      J;; 2: len 7; hex 3c000000453040; asc <   E0@;; 3: len 4; hex 80000001; asc     ;;
TABLE LOCK table `test`.`t` trx id 241482 lock mode IS
RECORD LOCKS space id 95 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 241482 lock mode S(LOCK_S) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000000; asc     ;; 1: len 6; hex 00000003676a; asc     gj;; 2: len 7; hex d8000000330110; asc     3  ;; 3: len 4; hex 80000000; asc     ;; 4: len 4; hex 80000000; asc     ;;

我們看到了 lock mode S(LOCK_S) locks rec but not gap(LOCK_REC_NOT_GAP)的信息看來沒有問題,猜測(cè)是實(shí)驗(yàn)是一樣的,但是還是要源碼驗(yàn)證一下。

三、源碼驗(yàn)證

  • 1、打印函數(shù)lock_print_info_all_transactions
/*********************************************************************//**
Prints info of locks for each transaction. This function assumes that the
caller holds the lock mutex and more importantly it will release the lock
mutex on behalf of the caller. (This should be fixed in the future). */voidlock_print_info_all_transactions(/*=============================*/
    FILE*       file)   /*!< in/out: file where to print */{
    ut_ad(lock_mutex_own());    fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
    mutex_enter(&trx_sys->mutex);    /* First print info on non-active transactions */
    /* NOTE: information of auto-commit non-locking read-only
    transactions will be omitted here. The information will be
    available from INFORMATION_SCHEMA.INNODB_TRX. */
    PrintNotStarted print_not_started(file);//建立一個(gè)結(jié)構(gòu)體,目的是做not start 事物的打印
    ut_list_map(trx_sys->mysql_trx_list, print_not_started); //這個(gè)地方打印出那些事物狀態(tài)是no start的事物,但是這里存在一個(gè)問題,等會(huì)看代碼在看。mysql_trx_list是全事物。
    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ì)有只讀事物的信息。
        check_trx_state(trx);        if (trx != prev_trx) {
            lock_trx_print_wait_and_mvcc_state(file, trx);
            prev_trx = trx;            /* The transaction that read in the page is no
            longer the one that read the page in. We need to
            force a page read. */
            load_block = true;
        }        /* 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(
                    file, trx, lock_iter, load_block)) {                /* Resync trx_iter, the trx_sys->mutex and
                the lock mutex were released. A page was
                successfully read in.  We need to print its
                contents on the next call to
                lock_trx_print_locks(). On the next call to
                lock_trx_print_locks() we should simply print
                the contents of the page just read in.*/
                load_block = false;                continue;
            }
        }
        load_block = true;        /* All record lock details were printed without fetching
        a page from disk, or we didn't need to print the detail. */
        trx_iter.next();
    }
    lock_mutex_exit();
    mutex_exit(&trx_sys->mutex);
    ut_ad(lock_validate());
}

這個(gè)函數(shù)是調(diào)用的邏輯。

  • 結(jié)構(gòu)體PrintNotStarted括號(hào)重載
void    operator()(const trx_t* trx)
    {
        ut_ad(trx->in_mysql_trx_list);
        ut_ad(mutex_own(&trx_sys->mutex));        /* See state transitions and locking rules in trx0trx.h */
        if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {//這里我們發(fā)現(xiàn)只有狀態(tài)為TRX_STATE_NOT_STARTED才會(huì)進(jìn)行輸出
            fputs("---", m_file);
            trx_print_latched(m_file, trx, 600);
        }
    }

我們這里可以看到只有狀態(tài)為TRX_STATE_NOT_STARTED才會(huì)輸出為not start狀態(tài)。

TrxListIterator迭代器初始化代碼
    TrxListIterator() : m_index()
    {        /* We iterate over the RW trx list first. */
        m_trx_list = &trx_sys->rw_trx_list;
    }

我們這里可以看到只有讀寫事物才會(huì)進(jìn)行鎖結(jié)構(gòu)的輸出。

到此,關(guān)于“Innodb中為什么lock in share mode在show engine看不到行鎖信息”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

網(wǎng)頁名稱:Innodb中為什么lockinsharemode在showengine看不到行鎖信息
文章源于:http://muchs.cn/article2/iidoic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、定制開發(fā)、網(wǎng)頁設(shè)計(jì)公司營銷型網(wǎng)站建設(shè)服務(wù)器托管、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司