Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
IB: 0.2 part II
* moved vers_notify_vtq() to commit phase;
* low_level insert (load test passed);
* rest of SYS_VTQ columns filled: COMMIT_TS, CONCURR_TRX;
* savepoints support;
* I_S.INNODB_SYS_VTQ adjustments:
  - limit to I_S_SYS_VTQ_LIMIT(10000) of most recent records;
  - CONCURR_TRX limit to I_S_MAX_CONCURR_TRX(100) with '...' truncation marker;
  - TIMESTAMP fields show fractions of seconds.
  • Loading branch information
midenok committed May 5, 2017
1 parent 002a1bd commit bdb12d1
Show file tree
Hide file tree
Showing 17 changed files with 407 additions and 120 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -365,7 +365,7 @@ ENDIF()

IF(WITH_INNOBASE_STORAGE_ENGINE)
SET(PLUGIN_INNOBASE STATIC CACHE STRING "" FORCE)
SET(PLUGIN_XTRADB DYNAMIC CACHE STRING "" FORCE)
SET(PLUGIN_XTRADB NO CACHE STRING "" FORCE)
ELSE()
SET(PLUGIN_INNOBASE DYNAMIC CACHE STRING "" FORCE)
SET(PLUGIN_XTRADB STATIC CACHE STRING "" FORCE)
Expand Down
13 changes: 13 additions & 0 deletions sql/sql_time.cc
Expand Up @@ -475,6 +475,19 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from)
to->second= (int) from->tm_sec;
}


/*
Convert seconds since Epoch to TIME
*/

void unix_time_to_TIME(MYSQL_TIME *to, time_t secs, suseconds_t usecs)
{
struct tm tm_time;
localtime_r(&secs, &tm_time);
localtime_to_TIME(to, &tm_time);
to->second_part = usecs;
}

void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds)
{
long t_seconds;
Expand Down
10 changes: 10 additions & 0 deletions sql/sql_time.h
Expand Up @@ -171,6 +171,16 @@ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2,
int lsign, MYSQL_TIME *l_time3, ulonglong fuzzydate);
int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
void unix_time_to_TIME(MYSQL_TIME *to, time_t secs, suseconds_t usecs);

inline
longlong unix_time_to_packed(time_t secs, suseconds_t usecs)
{
MYSQL_TIME mysql_time;
unix_time_to_TIME(&mysql_time, secs, usecs);
return pack_time(&mysql_time);
}

void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year);

Expand Down
62 changes: 61 additions & 1 deletion storage/innobase/btr/btr0pcur.cc
Expand Up @@ -452,6 +452,66 @@ btr_pcur_move_to_next_page(
ut_d(page_check_dir(next_page));
}

/*********************************************************//**
Moves the persistent cursor to the last record on the previous page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
modifications on the current page, as then the x-latch can be released only in
mtr_commit. */
UNIV_INTERN
void
btr_pcur_move_to_prev_page(
/*=======================*/
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
last record of the current page */
mtr_t* mtr) /*!< in: mtr */
{
ulint prev_page_no;
page_t* page;
buf_block_t* prev_block;
page_t* prev_page;
ulint mode;

ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
ut_ad(btr_pcur_is_before_first_on_page(cursor));

cursor->old_stored = false;

page = btr_pcur_get_page(cursor);
prev_page_no = btr_page_get_prev(page, mtr);

ut_ad(prev_page_no != FIL_NULL);

mode = cursor->latch_mode;
switch (mode) {
case BTR_SEARCH_TREE:
mode = BTR_SEARCH_LEAF;
break;
case BTR_MODIFY_TREE:
mode = BTR_MODIFY_LEAF;
}

buf_block_t* block = btr_pcur_get_block(cursor);

prev_block = btr_block_get(
page_id_t(block->page.id.space(), prev_page_no),
block->page.size, mode,
btr_pcur_get_btr_cur(cursor)->index, mtr);

prev_page = buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_page) == page_is_comp(page));
ut_a(btr_page_get_next(prev_page, mtr)
== btr_pcur_get_block(cursor)->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */

btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr);

page_cur_set_after_last(prev_block, btr_pcur_get_page_cur(cursor));

page_check_dir(prev_page);
}

/*********************************************************//**
Moves the persistent cursor backward if it is on the first record of the page.
Commits mtr. Note that to prevent a possible deadlock, the operation
Expand All @@ -461,7 +521,7 @@ alphabetical position of the cursor is guaranteed to be sensible on
return, but it may happen that the cursor is not positioned on the last
record of any page, because the structure of the tree may have changed
during the time when the cursor had no latches. */
static
UNIV_INTERN
void
btr_pcur_move_backward_from_page(
/*=============================*/
Expand Down
91 changes: 64 additions & 27 deletions storage/innobase/dict/dict0load.cc
Expand Up @@ -319,7 +319,10 @@ dict_getnext_system_low(
rec_t* rec = NULL;

while (!rec || rec_get_deleted_flag(rec, 0)) {
btr_pcur_move_to_next_user_rec(pcur, mtr);
if (pcur->search_mode == PAGE_CUR_L)
btr_pcur_move_to_prev_user_rec(pcur, mtr);
else
btr_pcur_move_to_next_user_rec(pcur, mtr);

rec = btr_pcur_get_rec(pcur);

Expand All @@ -346,7 +349,8 @@ dict_startscan_system(
btr_pcur_t* pcur, /*!< out: persistent cursor to
the record */
mtr_t* mtr, /*!< in: the mini-transaction */
dict_system_id_t system_id) /*!< in: which system table to open */
dict_system_id_t system_id, /*!< in: which system table to open */
bool from_left)
{
dict_table_t* system_table;
dict_index_t* clust_index;
Expand All @@ -358,7 +362,7 @@ dict_startscan_system(

clust_index = UT_LIST_GET_FIRST(system_table->indexes);

btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, pcur,
btr_pcur_open_at_index_side(from_left, clust_index, BTR_SEARCH_LEAF, pcur,
true, 0, mtr);

rec = dict_getnext_system_low(pcur, mtr);
Expand Down Expand Up @@ -822,6 +826,15 @@ dict_process_sys_datafiles(
return(NULL);
}


inline
const char* dict_print_error(mem_heap_t* heap, ulint col, ulint len, ulint expected)
{
return mem_heap_printf(heap,
"incorrect column %lu length in SYS_VTQ; got: %lu, expected: %lu",
col, len, expected);
}

/********************************************************************//**
This function parses a SYS_VTQ record, extracts necessary
information from the record and returns it to the caller.
Expand All @@ -832,13 +845,15 @@ dict_process_sys_vtq(
/*=======================*/
mem_heap_t* heap, /*!< in/out: heap memory */
const rec_t* rec, /*!< in: current rec */
ullong* col_trx_id, /*!< out: field values */
trx_id_t* col_trx_id, /*!< out: field values */
ullong* col_begin_ts,
ullong* col_commit_ts,
ullong* col_concurr_trx)
char** col_concurr_trx)
{
ulint len;
const byte* field;
ulint len, col, concurr_n;
const byte *field, *ptr;
char *out;
trx_id_t trx_id;

if (rec_get_deleted_flag(rec, 0)) {
return("delete-marked record in SYS_VTQ");
Expand All @@ -847,35 +862,57 @@ ullong* col_concurr_trx)
if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_VTQ) {
return("wrong number of columns in SYS_VTQ record");
}

/* TRX_ID */
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__TRX_ID, &len);
if (len != sizeof(col_trx_id)) {
err_len:
return("incorrect column length in SYS_VTQ");
}
*col_trx_id = mach_read_from_8(field);
rec, (col = DICT_FLD__SYS_VTQ__TRX_ID), &len);

if (len != sizeof(trx_id_t))
return dict_print_error(heap, col, len, sizeof(trx_id_t));

*col_trx_id = mach_read_from_8(field);
/* BEGIN_TS */
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__BEGIN_TS, &len);
if (len != sizeof(col_begin_ts)) {
goto err_len;
}
rec, (col = DICT_FLD__SYS_VTQ__BEGIN_TS), &len);

if (len != sizeof(ullong))
return dict_print_error(heap, col, len, sizeof(ullong));

*col_begin_ts = mach_read_from_8(field);
/* COMMIT_TS */
field = rec_get_nth_field_old(
rec, (col = DICT_FLD__SYS_VTQ__COMMIT_TS), &len);

if (len != sizeof(ullong))
return dict_print_error(heap, col, len, sizeof(ullong));

*col_commit_ts = mach_read_from_8(field);
/* CONCURR_TRX */
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__COMMIT_TS, &len);
if (len != sizeof(col_commit_ts)) {
goto err_len;
rec, (col = DICT_FLD__SYS_VTQ__CONCURR_TRX), &len);
concurr_n = len / sizeof(trx_id_t);
if (len != concurr_n * sizeof(trx_id_t))
return dict_print_error(heap, col, len, concurr_n * sizeof(trx_id_t));

bool truncated = false;
if (concurr_n > I_S_MAX_CONCURR_TRX) {
concurr_n = I_S_MAX_CONCURR_TRX;
truncated = true;
}
*col_commit_ts = mach_read_from_8(field);

field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__CONCURR_TRX, &len);
if (len != sizeof(col_concurr_trx)) {
goto err_len;
if (concurr_n == 0) {
*col_concurr_trx = NULL;
return(NULL);
}
*col_concurr_trx = static_cast<char*>(mem_heap_alloc(heap, concurr_n * (TRX_ID_MAX_LEN + 1) + 3 + 1));
ptr = field, out = *col_concurr_trx;
for (ulint i = 0; i < concurr_n;
++i, ptr += sizeof(trx_id_t))
{
trx_id = mach_read_from_8(ptr);
out += ut_snprintf(out, TRX_ID_MAX_LEN + 1, TRX_ID_FMT " ", trx_id);
}
*col_concurr_trx = mach_read_from_8(field);
if (truncated)
strcpy(out, "...");

return(NULL);
}
Expand Down
5 changes: 5 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Expand Up @@ -4816,6 +4816,11 @@ innobase_commit(

if (commit_trx
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
/* Notify VTQ on System Versioned tables update */
if (trx->vtq_notify_on_commit) {
vers_notify_vtq(trx);
trx->vtq_notify_on_commit = false;
}

DBUG_EXECUTE_IF("crash_innodb_before_commit",
DBUG_SUICIDE(););
Expand Down
21 changes: 11 additions & 10 deletions storage/innobase/handler/i_s.cc
Expand Up @@ -9690,10 +9690,11 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] =

#define SYS_VTQ_CONCURR_TRX 3
{ STRUCT_FLD(field_name, "concurr_trx"),
STRUCT_FLD(field_length, 120),
STRUCT_FLD(field_type, MYSQL_TYPE_MEDIUM_BLOB),
// 3 for "..." if list is truncated
STRUCT_FLD(field_length, I_S_MAX_CONCURR_TRX * (TRX_ID_MAX_LEN + 1) + 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },

Expand All @@ -9712,7 +9713,7 @@ i_s_dict_fill_vtq(
ullong col_trx_id, /*!< in: table fields */
ullong col_begin_ts,
ullong col_commit_ts,
ullong col_concurr_trx,
char* col_concurr_trx,
TABLE* table_to_fill) /*!< in/out: fill this table */
{
Field** fields;
Expand All @@ -9723,7 +9724,7 @@ i_s_dict_fill_vtq(
OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], col_trx_id));
OK(field_store_packed_ts(fields[SYS_VTQ_BEGIN_TS], col_begin_ts));
OK(field_store_packed_ts(fields[SYS_VTQ_COMMIT_TS], col_commit_ts));
OK(field_store_ullong(fields[SYS_VTQ_CONCURR_TRX], col_concurr_trx));
OK(field_store_string(fields[SYS_VTQ_CONCURR_TRX], col_concurr_trx));

OK(schema_table_store_record(thd, table_to_fill));

Expand All @@ -9736,7 +9737,7 @@ Loop through each record in SYS_VTQ, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_SYS_VTQ table.
@return 0 on success */

static const int I_S_SYS_VTQ_LIMIT = 1000; // maximum number of records in I_S.INNODB_SYS_VTQ
static const int I_S_SYS_VTQ_LIMIT = 10000; // maximum number of records in I_S.INNODB_SYS_VTQ

static
int
Expand Down Expand Up @@ -9764,16 +9765,16 @@ i_s_sys_vtq_fill_table(
mutex_enter(&dict_sys->mutex);
mtr_start(&mtr);

rec = dict_startscan_system(&pcur, &mtr, SYS_VTQ);
rec = dict_startscan_system(&pcur, &mtr, SYS_VTQ, false);

for (int i = 0; rec && i < I_S_SYS_VTQ_LIMIT; ++i) {
const char* err_msg;
ullong col_trx_id;
trx_id_t col_trx_id;
ullong col_begin_ts;
ullong col_commit_ts;
ullong col_concurr_trx;
char* col_concurr_trx;

/* Extract necessary information from a SYS_VTQ row */
/* Extract necessary information from SYS_VTQ row */
err_msg = dict_process_sys_vtq(
heap,
rec,
Expand Down
38 changes: 38 additions & 0 deletions storage/innobase/include/btr0pcur.h
Expand Up @@ -337,6 +337,17 @@ btr_pcur_move_to_next_user_rec(
function may release the page latch */
mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Moves the persistent cursor to the previous user record in the tree. If no user
records are left, the cursor ends up 'before first in tree'.
@return TRUE if the cursor moved forward, ending on a user record */
UNIV_INLINE
ibool
btr_pcur_move_to_prev_user_rec(
/*===========================*/
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
function may release the page latch */
mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Moves the persistent cursor to the first record on the next page.
Releases the latch on the current page, and bufferunfixes it.
Note that there must not be modifications on the current page,
Expand All @@ -347,6 +358,33 @@ btr_pcur_move_to_next_page(
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
last record of the current page */
mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Moves the persistent cursor to the last record on the previous page.
Releases the latch on the current page, and bufferunfixes it.
Note that there must not be modifications on the current page,
as then the x-latch can be released only in mtr_commit. */
void
btr_pcur_move_to_prev_page(
/*=======================*/
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
last record of the current page */
mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Moves the persistent cursor backward if it is on the first record
of the page. Releases the latch on the current page, and bufferunfixes
it. Note that to prevent a possible deadlock, the operation first
stores the position of the cursor, releases the leaf latch, acquires
necessary latches and restores the cursor position again before returning.
The alphabetical position of the cursor is guaranteed to be sensible
on return, but it may happen that the cursor is not positioned on the
last record of any page, because the structure of the tree may have
changed while the cursor had no latches. */
void
btr_pcur_move_backward_from_page(
/*=============================*/
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the
first record of the current page */
mtr_t* mtr); /*!< in: mtr */
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the btr cursor component of a persistent cursor.
Expand Down

0 comments on commit bdb12d1

Please sign in to comment.