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

一、只读事物
也许有人要问一个select算不算一个事物。其实在innodb中一个innodb的select是一个事物,他有trx_t结构体,并且放到了MySQL_trx_list链表中,关于
innodb事物系统一级的事都做了,但是这种事物叫做只读事物
bool read_only; /*!< true if transaction is flagged
as a READ-ONLY transaction.
if auto_commit && will_lock == 0
then it will be handled as a
AC-NL-RO-SELECT (Auto Commit Non-Locking
Read Only Select). A read only
transaction will not be assigned an
UNDO log. */
在实际的使用中他没有自己的锁结构也没有自己的undo segment,这一点很好理解因为这个操作
始终是非锁定的,至少在innodb一级是这样(lock0lock.cc lock_table 都没调用),但是在MYSQL中,我们会发现实际上select语句也会
获得MDL LOCK。(再次声明这里只是说innodb select没有表级别锁存在,但是MYSQL上层会有MDL LOCK)
对于只读事物源码注释给出的流程如下:
Auto-commit non-locking read-only:
* NOT_STARTED -> ACTIVE -> NOT_STARTED
而我们一般的2pc TRX流程如下:
XA (2PC):
* NOT_STARTED -> ACTIVE -> PREPARED -> COMMITTED -> NOT_STARTED
可以看到他实际上就是没有commit的步骤,没有undo reodo这些当然是不需要的。但是不可否认它是一个事物
另外当需要一个事物的时候在现在innodb版本中调用如下:
trx_allocate_for_mysql --> trx_allocate_for_background --> trx_create_low
这里涉及到一个innodb 事物池的概念,trx_create_low 从事物池中取出一个事物TRX_T结构体指针给调用者
这个步骤完成后事物处于NOT_STARTED阶段,这个时候TRX_T结构各种属性都处于初始化阶段,为什么要说一下
事物池的概念因为后面说事物号分配的时候会用到这个概念。
然后根据调用者的需求适时激活事物。实际上会调用,而调用会通过
trx_start_if_not_started_low->trx_start_low完成,在trx_start_low做好事物结构的准备工作,我们来看一
下关于源码中重点的部分

trx->read_only =

(trx->api_trx && !trx->read_write)
        || (!trx->ddl && !trx->internal
        && thd_trx_is_read_only(trx->mysql_thd))
        || srv_read_only_mode; //此处获取事物当前是否是只读属性,可以看到他和我们的read_only参数设置事物是ddl事物是否是内部事物有关

if (!trx->auto_commit) { //是否自动提交否则需要设置will_Lock属性如果时候只读事物未TURE,如果是DML事物为flase
    //这里的auto_commit属性和我们平时设置的参数感觉不是一回事
        ++trx->will_lock;
    } else if (trx->will_lock == 0) {
        trx->read_only = true; //如果不需要will_lock属性它肯定是只读事物
    }
//以上也就说明了只读事物不需要锁结构因为 trx->will_lock = 0(false)
    /* We tend to over assert and that complicates the code somewhat.
    e.g., the transaction state can be set earlier but we are forced to
    set it under the protection of the trx_sys_t::mutex because some
    trx list assertions are triggered unnecessarily. */

/* By default all transactions are in the read-only list unless they
    are non-locking auto-commit read only transactions or background
    (internal) transactions. Note: Transactions marked explicitly as
    read only can write to temporary tables, we put those on the RO
    list too. */
    //当然如果是非只读事物 我们需要开始分配undo rollback segment了 以及undo segment了
    //并且trx->mysql_thd == 0 表示是否是MYSQL线程建立的innodb事物
    //是否是读写事物这个是由调用者传入只读事物为false,DML事物为true,这里的读写和前面
    //trx->read_only有区别如果是只读事物建立临时表也是读写事物
    //是否是DDL事物 DDL也需要分配undo rollback segment了 以及undo segment
    if (!trx->read_only
    && (trx->mysql_thd == 0 || read_write || trx->ddl)) {

trx->rsegs.m_redo.rseg = trx_assign_rseg_low(
            srv_undo_logs, srv_undo_tablespaces,
            TRX_RSEG_TYPE_REDO);

/* Temporary rseg is assigned only if the transaction
        updates a temporary table */

trx_sys_mutex_enter();

trx_assign_id_for_rw(trx);//分配事物号
        /*
    (gdb) p trx_sys->max_trx_id
        $21 = 328707
    */

trx_sys_rw_trx_add(trx); //将入集合

ut_ad(trx->rsegs.m_redo.rseg != 0
        || srv_read_only_mode
        || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);

UT_LIST_ADD_FIRST(trx_sys->rw_trx_list, trx); //将事物放入rw_trx_list

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

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