Comment 2 for bug 1408971

Revision history for this message
Valerii Kravchuk (valerii-kravchuk) wrote :

I've spent some time checking the code to find out what this variable really shows:

[openxs@centos ~]$ cd git/percona-server/
[openxs@centos percona-server]$ grep -rni Innodb_current_row_locks *
doc/source/ps-variables.rst:788: * - :variable:`Innodb_current_row_locks`
doc/source/diagnostics/innodb_show_status.rst:432:.. variable:: Innodb_current_row_locks
storage/innobase/include/srv0srv.h:1047: ulint innodb_current_row_locks;
storage/innobase/srv/srv0srv.cc:1763: export_vars.innodb_current_row_locks
storage/innobase/handler/ha_innodb.cc:809: (char*) &export_vars.innodb_current_row_locks, SHOW_LONG},

So, the only place where it's referred in the code (5.6.27 from GitHub) is in srv0srv.cc:

/******************************************************************//**
Function to pass InnoDB status variables to MySQL */
UNIV_INTERN
void
srv_export_innodb_status(void)
/*==========================*/
{
...
        export_vars.innodb_current_row_locks
                = lock_sys->rec_num;
...

First, let's check when srv_export_innodb_status() is called:

[openxs@centos percona-server]$ grep -rn srv_export_innodb_status *
storage/innobase/include/srv0srv.h:812:srv_export_innodb_status(void);
storage/innobase/srv/srv0mon.cc:1435:srv_export_innodb_status() for related global counters used by
storage/innobase/srv/srv0srv.cc:1577:srv_export_innodb_status(void)
storage/innobase/handler/ha_innodb.cc:13330: srv_export_innodb_status();
[openxs@centos percona-server]$

So, this is where it's called:

/************************************************************************//**
Here we export InnoDB status variables to MySQL. */
static
void
innodb_export_status()
/*==================*/
{
        if (innodb_inited) {
                srv_export_innodb_status();
        }
}

Let's check when innodb_export_status() is called:

[openxs@centos percona-server]$ vi +13330 storage/innobase/handler/ha_innodb.cc
[openxs@centos percona-server]$ grep -rn innodb_export_status *
storage/innobase/handler/ha_innodb.cc:13326:innodb_export_status()
storage/innobase/handler/ha_innodb.cc:16429: innodb_export_status();
[openxs@centos percona-server]$

So, here it is:

/****************************************************************//**
Callback function for accessing the InnoDB variables from MySQL:
SHOW VARIABLES. */
static
int
show_innodb_vars(
/*=============*/
        THD* thd,
        SHOW_VAR* var,
        char* buff)
{
        innodb_export_status();
        var->type = SHOW_ARRAY;
        var->value = (char*) &innodb_status_variables;

        return(0);
}

So, we can assume it's called every time when SHOW VARIABLES is called. Now, let's check where lock_sys->rec_num comes from:

[openxs@centos percona-server]$ grep -rn 'lock_sys->rec_num' *
...
storage/innobase/lock/lock0lock.cc:619: lock_sys->rec_num = 0;
storage/innobase/lock/lock0lock.cc:1869: lock_sys->rec_num++;
storage/innobase/lock/lock0lock.cc:2511: lock_sys->rec_num--;
storage/innobase/lock/lock0lock.cc:2562: lock_sys->rec_num--;
storage/innobase/srv/srv0srv.cc:1764: = lock_sys->rec_num;

Creates a new record lock and inserts it to the lock queue. Does NOT check
for deadlocks or lock compatibility!
@return created lock */
static
lock_t*
lock_rec_create(
...
        HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
                    lock_rec_fold(space, page_no), lock);

        lock_sys->rec_num++;
...

This is the only place in the code when it is incremented. This is where it's decremented:

/*************************************************************//**
Removes a record lock request, waiting or granted, from the queue and
grants locks to other transactions in the queue if they now are entitled
to a lock. NOTE: all record locks contained in in_lock are removed. */
static
void
lock_rec_dequeue_from_page(
/*=======================*/
        lock_t* in_lock) /*!< in: record lock object: all
                                        record locks which are contained in
                                        this lock object are removed;
                                        transactions waiting behind will
                                        get their lock requests granted,
                                        if they are now qualified to it */
...
        HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
                    lock_rec_fold(space, page_no), in_lock);
        lock_sys->rec_num--;
...

and then later:

/*************************************************************//**
Removes a record lock request, waiting or granted, from the queue. */
static
void
lock_rec_discard(
/*=============*/
        lock_t* in_lock) /*!< in: record lock object: all
                                        record locks which are contained
                                        in this lock object are removed */
...
        HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
                    lock_rec_fold(space, page_no), in_lock);
        lock_sys->rec_num--;
...

From what I see I'd say it's a number of lock structures for record locks, with every record lock being able to track several individual row locks of the same "kind". Hence the value 3 in my original example.