summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2021-07-22 22:24:02 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2021-07-22 22:29:44 +0300
commitec6406125bd6ab1083bfdcd0d491bae616580b55 (patch)
tree7cd0c3851f6a4bc4ea6218003cfc322303e7b5b8
parent5f8651ac238d8d6cd3e4a7e3090b4b529f990331 (diff)
downloadmariadb-git-ec6406125bd6ab1083bfdcd0d491bae616580b55.tar.gz
fix index corruption during insertbb-10.2-nikita-MDEV-26205
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/include/row0ins.h1
-rw-r--r--storage/innobase/include/row0mysql.h3
-rw-r--r--storage/innobase/que/que0que.cc4
-rw-r--r--storage/innobase/row/row0ins.cc26
-rw-r--r--storage/innobase/row/row0log.cc10
6 files changed, 40 insertions, 6 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 81f1dae85b6..ffae5706176 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -21900,7 +21900,7 @@ innobase_get_field_from_update_vector(
for purge thread.
*/
-bool innobase_allocate_row_for_vcol(THD *thd, dict_index_t *index,
+bool innobase_allocate_row_for_vcol(THD *thd, const dict_index_t *index,
mem_heap_t **heap, TABLE **table,
VCOL_STORAGE *storage)
{
diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h
index 27fe442f6ff..e5205aa0596 100644
--- a/storage/innobase/include/row0ins.h
+++ b/storage/innobase/include/row0ins.h
@@ -190,6 +190,7 @@ struct ins_node_t{
if this is NULL, entry list should be created
and buffers for sys fields in row allocated */
ulint magic_n;
+ mem_heap_t *heap;
};
#define INS_NODE_MAGIC_N 15849075
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 8738f991368..6fb7be76799 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -829,6 +829,7 @@ struct VCOL_STORAGE
bool innobase_allocate_row_for_vcol(
THD * thd,
+ const
dict_index_t* index,
mem_heap_t** heap,
TABLE** table,
@@ -845,7 +846,7 @@ public:
ib_vcol_row(mem_heap_t *heap) : heap(heap) {}
- byte *record(THD *thd, dict_index_t *index, TABLE **table)
+ byte *record(THD *thd, const dict_index_t *index, TABLE **table)
{
if (!storage.innobase_record)
{
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index 0b630bb1c8c..9085a59b071 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -465,6 +465,10 @@ que_graph_free_recursive(
mem_heap_free(ins->entry_sys_heap);
ins->entry_sys_heap = NULL;
}
+ if (ins->heap != NULL) {
+ mem_heap_free(ins->heap);
+ ins->heap = NULL;
+ }
break;
case QUE_NODE_PURGE:
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 4dc9c66a536..3b3545e06c0 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -92,6 +92,8 @@ ins_node_create(
node->magic_n = INS_NODE_MAGIC_N;
+ node->heap = mem_heap_create(128);
+
return(node);
}
@@ -3304,7 +3306,10 @@ dberr_t
row_ins_index_entry_set_vals(
const dict_index_t* index,
dtuple_t* entry,
- const dtuple_t* row)
+ dtuple_t* row,
+ mem_heap_t *heap,
+ THD* thd,
+ TABLE* mysql_table)
{
ulint n_fields;
ulint i;
@@ -3336,6 +3341,18 @@ row_ins_index_entry_set_vals(
ut_ad(dtuple_get_n_fields(row)
== dict_table_get_n_cols(index->table));
row_field = dtuple_get_nth_v_field(row, v_col->v_pos);
+ ib_vcol_row vc(NULL);
+ if (v_col->m_col.ord_part
+ && dfield_is_null(row_field)) {
+ uchar *record = vc.record(thd, index,
+ &mysql_table);
+ innobase_get_computed_value(row, v_col, index,
+ &vc.heap, heap,
+ NULL,
+ thd, mysql_table,
+ record,
+ NULL, NULL, NULL);
+ }
} else {
row_field = dtuple_get_nth_field(
row, ind_field->col->ind);
@@ -3394,13 +3411,18 @@ row_ins_index_entry_step(
que_thr_t* thr) /*!< in: query thread */
{
dberr_t err;
+ trx_t* trx = thr_get_trx(thr);
DBUG_ENTER("row_ins_index_entry_step");
ut_ad(dtuple_check_typed(node->row));
err = row_ins_index_entry_set_vals(node->index, *node->entry,
- node->row);
+ node->row, node->heap,
+ trx->mysql_thd,
+ thr->prebuilt
+ ? thr->prebuilt->m_mysql_table
+ : NULL);
if (err != DB_SUCCESS) {
DBUG_RETURN(err);
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 1a7652350a9..3a428c823cc 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -286,6 +286,7 @@ row_log_online_op(
ulint mrec_size;
ulint avail_size;
row_log_t* log;
+ row_op op;
ut_ad(dtuple_validate(tuple));
ut_ad(dtuple_get_n_fields(tuple) == dict_index_get_n_fields(index));
@@ -337,11 +338,11 @@ row_log_online_op(
}
if (trx_id != 0) {
- *b++ = ROW_OP_INSERT;
+ *b++ = op = ROW_OP_INSERT;
trx_write_trx_id(b, trx_id);
b += DATA_TRX_ID_LEN;
} else {
- *b++ = ROW_OP_DELETE;
+ *b++ = op = ROW_OP_DELETE;
}
if (extra_size < 0x80) {
@@ -352,6 +353,11 @@ row_log_online_op(
*b++ = (byte) extra_size;
}
+ DBUG_EXECUTE_IF("ib_log_online",
+ ib::info() << "LOG " << index->name()
+ << (op == ROW_OP_INSERT ? " INS " : " DEL ")
+ << *tuple;);
+
rec_convert_dtuple_to_temp(
b + extra_size, index, tuple->fields, tuple->n_fields);
b += size;