/** Structure for an SQL data tuple of fields (logical record) */ structdtuple_t { /* ... */
/** Number of fields in dtuple */ ulint n_fields; /* 当前 dtuple 记录的字段数量. */
/** number of fields which should be used in comparison services of rem0cmp.*; the index search is performed by comparing only these fields, others are ignored; the default value in dtuple creation is the same value as n_fields */ ulint n_fields_cmp; /* 当前 dtuple 中可以用来比较的字段数量, 可以通过 * dtuple_set_n_fields_cmp() 设置. */
/** Fields. */ dfield_t *fields; /* 当前 dtuple 的字段内容. */ /** Structure for an SQL data field */ structdfield_t { void *data; /*!< pointer to data */ unsigned ext : 1; /*!< TRUE=externally stored, FALSE=local */ unsigned spatial_status : 2; /*!< spatial status of externally stored field in undo log for purge */ unsigned len; /*!< data length; UNIV_SQL_NULL if SQL null 数据长度 */ dtype_t type; /*!< type of data 数据类型*/ /* ... */ } */
/** ... */
/** Compare a data tuple to a physical record. * dtuple_t 与 rec_t 的比较函数. */ intcompare(constrec_t *rec, constdict_index_t *index, const ulint *offsets, ulint *matched_fields)const;
/** ... */ };
MySQL SQL 层的 record 可以通过row_sel_convert_mysql_key_to_innobase()转换为 InnoDB 可识别的dtuple_t结构.
/* This is the same record as stored, may need to be adjusted for BTR_PCUR_BEFORE/AFTER, depending on search mode and direction. */ if (is_on_user_rec()) { m_pos_state = BTR_PCUR_IS_POSITIONED_OPTIMISTIC; } return (false); } }
/* If optimistic restoration did not succeed, open the cursor anew */
if (m_rel_pos == BTR_PCUR_ON && is_on_user_rec() && !cmp_dtuple_rec( tuple, get_rec(), index, rec_get_offsets(get_rec(), index, nullptr, ULINT_UNDEFINED, &heap))) { /* We have to store the NEW value for the modify clock, since the cursor can now be on a different page! But we can retain the value of old_rec */ auto block = get_block(); m_block_when_stored.store(block); m_modify_clock = buf_block_get_modify_clock(block);
m_old_stored = true;
mem_heap_free(heap);
return (true); }
mem_heap_free(heap);
/* We have to store new position information, modify_clock etc., to the cursor because it can now be on a different page, the record under it may have been removed, etc. */
/* If not own buf_pool_mutex, page_hash can be changed. */ latch = buf_page_hash_lock_s_confirm(latch, pool, m_page_id); if (buf_is_block_in_instance(pool, m_block) && m_page_id == m_block->page.id && buf_block_get_state(m_block) == BUF_BLOCK_FILE_PAGE) { buf_block_buf_fix_inc(m_block, __FILE__, __LINE__); } else { clear(); }
rw_lock_s_unlock(latch); } }
游标 cursor 的搜索模式
PAGE_CUR_G: > 查询,查询第一个大于 dtuple 的 rec_t.
PAGE_CUR_GE: >=,> 查询,查询第一个大于等于 dtuple 的 rec_t.
如果搜索一个存在的 user record, 使用 PAGE_CUR_GE 可能定位在这个 user record 的 previous page 的 supremum record.
PAGE_CUR_L: < 查询,查询最后一个小于 dtuple 的 rec_t.
PAGE_CUR_LE: <= 查询,查询最后一个小于等于 dtuple 的 rec_t.
如果搜索一个不存在的 user record, 使用 PAGE_CUR_LE 返回最后一个小于 dtuple 的 record.