Commit bdb12d14 authored by Aleksey Midenkov's avatar Aleksey Midenkov

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.
parent 002a1bd0
...@@ -365,7 +365,7 @@ ENDIF() ...@@ -365,7 +365,7 @@ ENDIF()
IF(WITH_INNOBASE_STORAGE_ENGINE) IF(WITH_INNOBASE_STORAGE_ENGINE)
SET(PLUGIN_INNOBASE STATIC CACHE STRING "" FORCE) SET(PLUGIN_INNOBASE STATIC CACHE STRING "" FORCE)
SET(PLUGIN_XTRADB DYNAMIC CACHE STRING "" FORCE) SET(PLUGIN_XTRADB NO CACHE STRING "" FORCE)
ELSE() ELSE()
SET(PLUGIN_INNOBASE DYNAMIC CACHE STRING "" FORCE) SET(PLUGIN_INNOBASE DYNAMIC CACHE STRING "" FORCE)
SET(PLUGIN_XTRADB STATIC CACHE STRING "" FORCE) SET(PLUGIN_XTRADB STATIC CACHE STRING "" FORCE)
......
...@@ -475,6 +475,19 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from) ...@@ -475,6 +475,19 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from)
to->second= (int) from->tm_sec; 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) void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds)
{ {
long t_seconds; long t_seconds;
......
...@@ -171,6 +171,16 @@ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, ...@@ -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 lsign, MYSQL_TIME *l_time3, ulonglong fuzzydate);
int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b); int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); 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); void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year); uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year);
......
...@@ -452,6 +452,66 @@ btr_pcur_move_to_next_page( ...@@ -452,6 +452,66 @@ btr_pcur_move_to_next_page(
ut_d(page_check_dir(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. 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 Commits mtr. Note that to prevent a possible deadlock, the operation
...@@ -461,7 +521,7 @@ alphabetical position of the cursor is guaranteed to be sensible on ...@@ -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 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 record of any page, because the structure of the tree may have changed
during the time when the cursor had no latches. */ during the time when the cursor had no latches. */
static UNIV_INTERN
void void
btr_pcur_move_backward_from_page( btr_pcur_move_backward_from_page(
/*=============================*/ /*=============================*/
......
...@@ -319,7 +319,10 @@ dict_getnext_system_low( ...@@ -319,7 +319,10 @@ dict_getnext_system_low(
rec_t* rec = NULL; rec_t* rec = NULL;
while (!rec || rec_get_deleted_flag(rec, 0)) { 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); rec = btr_pcur_get_rec(pcur);
...@@ -346,7 +349,8 @@ dict_startscan_system( ...@@ -346,7 +349,8 @@ dict_startscan_system(
btr_pcur_t* pcur, /*!< out: persistent cursor to btr_pcur_t* pcur, /*!< out: persistent cursor to
the record */ the record */
mtr_t* mtr, /*!< in: the mini-transaction */ 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_table_t* system_table;
dict_index_t* clust_index; dict_index_t* clust_index;
...@@ -358,7 +362,7 @@ dict_startscan_system( ...@@ -358,7 +362,7 @@ dict_startscan_system(
clust_index = UT_LIST_GET_FIRST(system_table->indexes); 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); true, 0, mtr);
rec = dict_getnext_system_low(pcur, mtr); rec = dict_getnext_system_low(pcur, mtr);
...@@ -822,6 +826,15 @@ dict_process_sys_datafiles( ...@@ -822,6 +826,15 @@ dict_process_sys_datafiles(
return(NULL); 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 This function parses a SYS_VTQ record, extracts necessary
information from the record and returns it to the caller. information from the record and returns it to the caller.
...@@ -832,13 +845,15 @@ dict_process_sys_vtq( ...@@ -832,13 +845,15 @@ dict_process_sys_vtq(
/*=======================*/ /*=======================*/
mem_heap_t* heap, /*!< in/out: heap memory */ mem_heap_t* heap, /*!< in/out: heap memory */
const rec_t* rec, /*!< in: current rec */ 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_begin_ts,
ullong* col_commit_ts, ullong* col_commit_ts,
ullong* col_concurr_trx) char** col_concurr_trx)
{ {
ulint len; ulint len, col, concurr_n;
const byte* field; const byte *field, *ptr;
char *out;
trx_id_t trx_id;
if (rec_get_deleted_flag(rec, 0)) { if (rec_get_deleted_flag(rec, 0)) {
return("delete-marked record in SYS_VTQ"); return("delete-marked record in SYS_VTQ");
...@@ -847,35 +862,57 @@ ullong* col_concurr_trx) ...@@ -847,35 +862,57 @@ ullong* col_concurr_trx)
if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_VTQ) { if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_VTQ) {
return("wrong number of columns in SYS_VTQ record"); return("wrong number of columns in SYS_VTQ record");
} }
/* TRX_ID */
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__TRX_ID, &len); rec, (col = DICT_FLD__SYS_VTQ__TRX_ID), &len);
if (len != sizeof(col_trx_id)) {
err_len: if (len != sizeof(trx_id_t))
return("incorrect column length in SYS_VTQ"); return dict_print_error(heap, col, len, sizeof(trx_id_t));
}
*col_trx_id = mach_read_from_8(field);
*col_trx_id = mach_read_from_8(field);
/* BEGIN_TS */
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__BEGIN_TS, &len); rec, (col = DICT_FLD__SYS_VTQ__BEGIN_TS), &len);
if (len != sizeof(col_begin_ts)) {
goto err_len; if (len != sizeof(ullong))
} return dict_print_error(heap, col, len, sizeof(ullong));
*col_begin_ts = mach_read_from_8(field); *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( field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_VTQ__COMMIT_TS, &len); rec, (col = DICT_FLD__SYS_VTQ__CONCURR_TRX), &len);
if (len != sizeof(col_commit_ts)) { concurr_n = len / sizeof(trx_id_t);
goto err_len; 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( if (concurr_n == 0) {
rec, DICT_FLD__SYS_VTQ__CONCURR_TRX, &len); *col_concurr_trx = NULL;
if (len != sizeof(col_concurr_trx)) { return(NULL);
goto err_len; }
*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); return(NULL);
} }
......
...@@ -4816,6 +4816,11 @@ innobase_commit( ...@@ -4816,6 +4816,11 @@ innobase_commit(
if (commit_trx if (commit_trx
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { || (!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_EXECUTE_IF("crash_innodb_before_commit",
DBUG_SUICIDE();); DBUG_SUICIDE(););
......
...@@ -9690,10 +9690,11 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] = ...@@ -9690,10 +9690,11 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] =
#define SYS_VTQ_CONCURR_TRX 3 #define SYS_VTQ_CONCURR_TRX 3
{ STRUCT_FLD(field_name, "concurr_trx"), { STRUCT_FLD(field_name, "concurr_trx"),
STRUCT_FLD(field_length, 120), // 3 for "..." if list is truncated
STRUCT_FLD(field_type, MYSQL_TYPE_MEDIUM_BLOB), 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(value, 0),
STRUCT_FLD(field_flags, 0), STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""), STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
...@@ -9712,7 +9713,7 @@ i_s_dict_fill_vtq( ...@@ -9712,7 +9713,7 @@ i_s_dict_fill_vtq(
ullong col_trx_id, /*!< in: table fields */ ullong col_trx_id, /*!< in: table fields */
ullong col_begin_ts, ullong col_begin_ts,
ullong col_commit_ts, ullong col_commit_ts,
ullong col_concurr_trx, char* col_concurr_trx,
TABLE* table_to_fill) /*!< in/out: fill this table */ TABLE* table_to_fill) /*!< in/out: fill this table */
{ {
Field** fields; Field** fields;
...@@ -9723,7 +9724,7 @@ i_s_dict_fill_vtq( ...@@ -9723,7 +9724,7 @@ i_s_dict_fill_vtq(
OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], col_trx_id)); 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_BEGIN_TS], col_begin_ts));
OK(field_store_packed_ts(fields[SYS_VTQ_COMMIT_TS], col_commit_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)); OK(schema_table_store_record(thd, table_to_fill));
...@@ -9736,7 +9737,7 @@ Loop through each record in SYS_VTQ, and extract the column ...@@ -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. information and fill the INFORMATION_SCHEMA.INNODB_SYS_VTQ table.
@return 0 on success */ @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 static
int int
...@@ -9764,16 +9765,16 @@ i_s_sys_vtq_fill_table( ...@@ -9764,16 +9765,16 @@ i_s_sys_vtq_fill_table(
mutex_enter(&dict_sys->mutex); mutex_enter(&dict_sys->mutex);
mtr_start(&mtr); 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) { for (int i = 0; rec && i < I_S_SYS_VTQ_LIMIT; ++i) {
const char* err_msg; const char* err_msg;
ullong col_trx_id; trx_id_t col_trx_id;
ullong col_begin_ts; ullong col_begin_ts;
ullong col_commit_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( err_msg = dict_process_sys_vtq(
heap, heap,
rec, rec,
......
...@@ -337,6 +337,17 @@ btr_pcur_move_to_next_user_rec( ...@@ -337,6 +337,17 @@ btr_pcur_move_to_next_user_rec(
function may release the page latch */ function may release the page latch */
mtr_t* mtr); /*!< in: mtr */ 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. Moves the persistent cursor to the first record on the next page.
Releases the latch on the current page, and bufferunfixes it. Releases the latch on the current page, and bufferunfixes it.
Note that there must not be modifications on the current page, Note that there must not be modifications on the current page,
...@@ -347,6 +358,33 @@ btr_pcur_move_to_next_page( ...@@ -347,6 +358,33 @@ btr_pcur_move_to_next_page(
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
last record of the current page */ last record of the current page */
mtr_t* mtr); /*!< in: mtr */ 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 #ifdef UNIV_DEBUG
/*********************************************************//** /*********************************************************//**
Returns the btr cursor component of a persistent cursor. Returns the btr cursor component of a persistent cursor.
......
...@@ -334,6 +334,42 @@ loop: ...@@ -334,6 +334,42 @@ loop:
goto loop; goto loop;
} }
/*********************************************************//**
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 */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false;
loop:
if (btr_pcur_is_before_first_on_page(cursor)) {
if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
return(FALSE);
}
btr_pcur_move_to_prev(cursor, mtr);
} else {
btr_pcur_move_to_prev_on_page(cursor);
}
if (btr_pcur_is_on_user_rec(cursor)) {
return(TRUE);
}
goto loop;
}
/*********************************************************//** /*********************************************************//**
Moves the persistent cursor to the next record in the tree. If no records are Moves the persistent cursor to the next record in the tree. If no records are
left, the cursor stays 'after last in tree'. left, the cursor stays 'after last in tree'.
......
...@@ -182,7 +182,8 @@ dict_startscan_system( ...@@ -182,7 +182,8 @@ dict_startscan_system(
btr_pcur_t* pcur, /*!< out: persistent cursor to btr_pcur_t* pcur, /*!< out: persistent cursor to
the record */ the record */
mtr_t* mtr, /*!< in: the mini-transaction */ 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 = true);
/********************************************************************//** /********************************************************************//**
This function get the next system table record as we scan the table. This function get the next system table record as we scan the table.
@return the record if found, NULL if end of scan. */ @return the record if found, NULL if end of scan. */
...@@ -319,6 +320,7 @@ dict_process_sys_datafiles( ...@@ -319,6 +320,7 @@ dict_process_sys_datafiles(
This function parses a SYS_VTQ record, extracts necessary This function parses a SYS_VTQ record, extracts necessary
information from the record and returns it to the caller. information from the record and returns it to the caller.
@return error message, or NULL on success */ @return error message, or NULL on success */
#define I_S_MAX_CONCURR_TRX 100
UNIV_INTERN UNIV_INTERN
const char* const char*
dict_process_sys_vtq( dict_process_sys_vtq(
...@@ -328,7 +330,7 @@ const rec_t* rec, /*!< in: current rec */ ...@@ -328,7 +330,7 @@ const rec_t* rec, /*!< in: current rec */
ullong* col_trx_id, /*!< out: field values */ ullong* col_trx_id, /*!< out: field values */
ullong* col_begin_ts, ullong* col_begin_ts,
ullong* col_commit_ts, ullong* col_commit_ts,
ullong* col_concurr_trx); char** col_concurr_trx);
/** Update the record for space_id in SYS_TABLESPACES to this filepath. /** Update the record for space_id in SYS_TABLESPACES to this filepath.
@param[in] space_id Tablespace ID @param[in] space_id Tablespace ID
......
...@@ -95,9 +95,10 @@ row_ins_clust_index_entry_low( ...@@ -95,9 +95,10 @@ row_ins_clust_index_entry_low(
dtuple_t* entry, /*!< in/out: index entry to insert */ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */ ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr, /*!< in: query thread or NULL */ que_thr_t* thr, /*!< in: query thread or NULL */
bool dup_chk_only) bool dup_chk_only,
/*!< in: if true, just do duplicate check /*!< in: if true, just do duplicate check
and return. don't execute actual insert. */ and return. don't execute actual insert. */
trx_t* trx = 0)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/***************************************************************//** /***************************************************************//**
...@@ -123,9 +124,10 @@ row_ins_sec_index_entry_low( ...@@ -123,9 +124,10 @@ row_ins_sec_index_entry_low(
trx_id_t trx_id, /*!< in: PAGE_MAX_TRX_ID during trx_id_t trx_id, /*!< in: PAGE_MAX_TRX_ID during
row_log_table_apply(), or 0 */ row_log_table_apply(), or 0 */
que_thr_t* thr, /*!< in: query thread */ que_thr_t* thr, /*!< in: query thread */
bool dup_chk_only) bool dup_chk_only,
/*!< in: if true, just do duplicate check /*!< in: if true, just do duplicate check
and return. don't execute actual insert. */ and return. don't execute actual insert. */
trx_t* trx = 0)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/** Sets the values of the dtuple fields in entry from the values of appropriate /** Sets the values of the dtuple fields in entry from the values of appropriate
columns in row. columns in row.
...@@ -183,7 +185,7 @@ row_ins_step( ...@@ -183,7 +185,7 @@ row_ins_step(
/***********************************************************//** /***********************************************************//**
Inserts a row to SYS_VTQ table. Inserts a row to SYS_VTQ table.
@return error state */ @return error state */
dberr_t vers_notify_vtq(que_thr_t * thr, mem_heap_t * heap); void vers_notify_vtq(trx_t* trx);
/* Insert node structure */ /* Insert node structure */
......
...@@ -1267,7 +1267,7 @@ struct trx_t { ...@@ -1267,7 +1267,7 @@ struct trx_t {
os_event_t wsrep_event; /* event waited for in srv_conc_slot */ os_event_t wsrep_event; /* event waited for in srv_conc_slot */
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
bool vtq_notified; bool vtq_notify_on_commit; /*!< Notify VTQ for System Versioned update */
ulint magic_n; ulint magic_n;
/** @return whether any persistent undo log has been generated */ /** @return whether any persistent undo log has been generated */
......
...@@ -146,6 +146,7 @@ typedef ib_id_t undo_no_t; ...@@ -146,6 +146,7 @@ typedef ib_id_t undo_no_t;
/** Transaction savepoint */ /** Transaction savepoint */
struct trx_savept_t{ struct trx_savept_t{
undo_no_t least_undo_no; /*!< least undo number to undo */ undo_no_t least_undo_no; /*!< least undo number to undo */
bool vtq_notify_on_commit; /*!< Notify VTQ for System Versioned update */
}; };
/** File objects */ /** File objects */
......
This diff is collapsed.
...@@ -1537,12 +1537,8 @@ row_insert_for_mysql( ...@@ -1537,12 +1537,8 @@ row_insert_for_mysql(
node->duplicate = NULL; node->duplicate = NULL;
if (!trx->vtq_notified && DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED)) { if (!trx->vtq_notify_on_commit && DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED)) {
trx->vtq_notified = true; trx->vtq_notify_on_commit = true;
err = vers_notify_vtq(thr, node->table->heap);
if (err != DB_SUCCESS) {
goto error_exit;
}
} }
if (dict_table_has_fts_index(table)) { if (dict_table_has_fts_index(table)) {
...@@ -1989,7 +1985,6 @@ row_update_for_mysql_using_upd_graph( ...@@ -1989,7 +1985,6 @@ row_update_for_mysql_using_upd_graph(
err = trx->error_state; err = trx->error_state;
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
error_exit:
que_thr_stop_for_mysql(thr); que_thr_stop_for_mysql(thr);
if (err == DB_RECORD_NOT_FOUND) { if (err == DB_RECORD_NOT_FOUND) {
...@@ -2137,12 +2132,8 @@ row_update_for_mysql_using_upd_graph( ...@@ -2137,12 +2132,8 @@ row_update_for_mysql_using_upd_graph(
} }
} }
if (!trx->vtq_notified && DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED)) { if (!trx->vtq_notify_on_commit && DICT_TF2_FLAG_IS_SET(node->table, DICT_TF2_VERSIONED)) {
trx->vtq_notified = true; trx->vtq_notify_on_commit = true;
err = vers_notify_vtq(thr, node->table->heap);
if (err != DB_SUCCESS) {
goto error;
}
} }
trx->op_info = ""; trx->op_info = "";
......
...@@ -128,6 +128,7 @@ trx_rollback_to_savepoint_low( ...@@ -128,6 +128,7 @@ trx_rollback_to_savepoint_low(
} else { } else {
trx->lock.que_state = TRX_QUE_RUNNING; trx->lock.que_state = TRX_QUE_RUNNING;
MONITOR_INC(MONITOR_TRX_ROLLBACK_SAVEPOINT); MONITOR_INC(MONITOR_TRX_ROLLBACK_SAVEPOINT);
trx->vtq_notify_on_commit = savept->vtq_notify_on_commit;
} }
ut_a(trx->error_state == DB_SUCCESS); ut_a(trx->error_state == DB_SUCCESS);
...@@ -614,6 +615,7 @@ trx_savept_take( ...@@ -614,6 +615,7 @@ trx_savept_take(
trx_savept_t savept; trx_savept_t savept;
savept.least_undo_no = trx->undo_no; savept.least_undo_no = trx->undo_no;
savept.vtq_notify_on_commit = trx->vtq_notify_on_commit;
return(savept); return(savept);
} }
......
...@@ -470,6 +470,8 @@ trx_create_low() ...@@ -470,6 +470,8 @@ trx_create_low()
trx_free(). */ trx_free(). */
ut_a(trx->mod_tables.size() == 0); ut_a(trx->mod_tables.size() == 0);
trx->vtq_notify_on_commit = false;
#ifdef WITH_WSREP #ifdef WITH_WSREP
trx->wsrep_event = NULL; trx->wsrep_event = NULL;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
...@@ -1363,8 +1365,7 @@ trx_start_low( ...@@ -1363,8 +1365,7 @@ trx_start_low(
} }
} }
trx->vtq_notified = false; trx->vtq_notify_on_commit = false;
ut_a(trx->error_state == DB_SUCCESS); ut_a(trx->error_state == DB_SUCCESS);
MONITOR_INC(MONITOR_TRX_ACTIVE); MONITOR_INC(MONITOR_TRX_ACTIVE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment