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));