MySQL innodb中的只读事物以及事物id的分配方式(2)

ut_d(trx->in_rw_trx_list = true);
#ifdef UNIV_DEBUG
        if (trx->id > trx_sys->rw_max_trx_id) {
            trx_sys->rw_max_trx_id = trx->id;
        }
#endif /* UNIV_DEBUG */

trx->state = TRX_STATE_ACTIVE; //更改事物的状态为ACTIVE

ut_ad(trx_sys_validate_trx_list());

trx_sys_mutex_exit();

} else {
        trx->id = 0; //任然没有分配事物ID给只读事物

if (!trx_is_autocommit_non_locking(trx)) { //#define trx_is_autocommit_non_locking(t)    ((t)->auto_commit && (t)->will_lock == 0)

/* If this is a read-only transaction that is writing
            to a temporary table then it needs a transaction id
            to write to the temporary table. */
            //如果是只读事物并且写入了临时表需要额外操作

if (read_write) {

trx_sys_mutex_enter();

ut_ad(!srv_read_only_mode);

trx_assign_id_for_rw(trx);

trx_sys->rw_trx_set.insert(
                    TrxTrack(trx->id, trx));

trx_sys_mutex_exit();
            }

trx->state = TRX_STATE_ACTIVE;

} else {
            ut_ad(!read_write);
            trx->state = TRX_STATE_ACTIVE;
        }
    }

if (trx->mysql_thd != NULL) {
        trx->start_time = thd_start_time_in_secs(trx->mysql_thd); //开始计时这是系统时间LINUX系统调用time()
    } else {
        trx->start_time = ut_time();
    }

根据上面的注释,我们可以看到只读事物没有分配undo segment也不会分配LOCK锁结构
二、事物ID的分配
也许很多朋友不止我一个人在show engine innodb status的时候会看到如下两种截然不同,相差很大的事物ID
(MYSQL)---TRANSACTION 329759, ACTIVE 10 sec
1 lock struct(s), heap size 1160, 0 row lock(s), undo log entries 1
MySQL thread id 3, OS thread handle 140737154152192, query id 28 localhost root cleaning up
(MYSQL)---TRANSACTION 422212177398528, not started
0 lock struct(s), heap size 1160, 0 row lock(s)

这里事物id 329759和422212177398528相差很大,innodb是怎么分配的呢?
其实这里实际上的事物id只有329759,及trx_t.id,是一个正常的DML事物,而对于 not started状态的事物
以及只读事物,是没有事物id的其实就是0,但是show engine innodb status的时候会调用时候会简单的分配
一个而已。
其实TRX ID的分配也是在trx_start_low中调用(trx_assign_id_for_rw(trx);//分配事物号 )
而对于只读事物并不会分配(trx->id = 0; //任然没有分配事物ID给只读事物)都在上面的代码解释中,
而show engine innodb status的时候对于事物ID为0的事物做如下输出

UNIV_INLINE

trx_id_t
trx_get_id_for_print(
    const trx_t*    trx)
{
    /* Readonly and transactions whose intentions are unknown (whether
    they will eventually do a WRITE) don't have trx_t::id assigned (it is
    0 for those transactions). Transaction IDs in
    innodb_trx.trx_id,
    innodb_locks.lock_id,
    innodb_locks.lock_trx_id,
    innodb_lock_waits.requesting_trx_id,
    innodb_lock_waits.blocking_trx_id should match because those tables
    could be used in an SQL JOIN on those columns. Also trx_t::id is
    printed by SHOW ENGINE INNODB STATUS, and in logs, so we must have the
    same value printed everywhere consistently. */
 
    /* DATA_TRX_ID_LEN is the storage size in bytes. */
    static const trx_id_t    max_trx_id
        = (1ULL << (DATA_TRX_ID_LEN * CHAR_BIT)) - 1;

ut_ad(trx->id <= max_trx_id);

return(trx->id != 0
    ? trx->id
    : reinterpret_cast<trx_id_t>(trx) | (max_trx_id + 1));
}

我们从注释也能看出
Readonly and transactions whose intentions are unknown don't have trx_t::id assigned (it is 0 for those transactions)
实际上422212177398528这种id就是这里打印的时候分配的,没有什么实际的意义
这里的max_trx_id是一个常量281474976710655如果trx->id==0会调用
reinterpret_cast(trx) | (max_trx_id + 1)
将指针转换为一个64字节非负整数然后位或上(max_trx_id + 1),如下:
(gdb) p max_trx_id
$19 = 281474976710655
(gdb) p reinterpret_cast(trx)
$20 = 140737200690640
(gdb) p  reinterpret_cast(trx) | (max_trx_id + 1)
$21 = 422212177401296

而对于这里DML的事物号的分配如下:

void

trx_assign_id_for_rw(trx_t* trx)
{
    ut_ad(mutex_own(&trx_sys->mutex));

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/983f4776a5c77fc4bd441070e311f44d.html