📄 row0mysql.c
字号:
/* MySQL will roll back the latest SQL statement */ } else if (err == DB_ROW_IS_REFERENCED || err == DB_NO_REFERENCED_ROW || err == DB_CANNOT_ADD_CONSTRAINT) { if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ trx_general_rollback_for_mysql(trx, TRUE, savept); } /* MySQL will roll back the latest SQL statement */ } else if (err == DB_LOCK_WAIT) { srv_suspend_mysql_thread(thr); if (trx->error_state != DB_SUCCESS) { que_thr_stop_for_mysql(thr); goto handle_new_error; } *new_err = err; return(TRUE); } else if (err == DB_DEADLOCK || err == DB_LOCK_TABLE_FULL) { /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ trx_general_rollback_for_mysql(trx, FALSE, NULL); } else if (err == DB_OUT_OF_FILE_SPACE || err == DB_LOCK_WAIT_TIMEOUT) { if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ trx_general_rollback_for_mysql(trx, TRUE, savept); } /* MySQL will roll back the latest SQL statement */ } else if (err == DB_MUST_GET_MORE_FILE_SPACE) { fputs( "InnoDB: The database cannot continue operation because of\n" "InnoDB: lack of space. You must add a new data file to\n" "InnoDB: my.cnf and restart the database.\n", stderr); exit(1); } else if (err == DB_CORRUPTION) { fputs( "InnoDB: We detected index corruption in an InnoDB type table.\n" "InnoDB: You have to dump + drop + reimport the table or, in\n" "InnoDB: a case of widespread corruption, dump all InnoDB\n" "InnoDB: tables and recreate the whole InnoDB tablespace.\n" "InnoDB: If the mysqld server crashes after the startup or when\n" "InnoDB: you dump the tables, look at\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html" " for help.\n", stderr); } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", (ulong) err); ut_error; } if (trx->error_state != DB_SUCCESS) { *new_err = trx->error_state; } else { *new_err = err; } trx->error_state = DB_SUCCESS; return(FALSE);#else /* UNIV_HOTBACKUP */ /* This function depends on MySQL code that is not included in InnoDB Hot Backup builds. Besides, this function should never be called in InnoDB Hot Backup. */ ut_error;#endif /* UNIV_HOTBACKUP */}/************************************************************************Create a prebuilt struct for a MySQL table handle. */row_prebuilt_t*row_create_prebuilt(/*================*/ /* out, own: a prebuilt struct */ dict_table_t* table) /* in: Innobase table handle */{ row_prebuilt_t* prebuilt; mem_heap_t* heap; dict_index_t* clust_index; dtuple_t* ref; ulint ref_len; ulint i; heap = mem_heap_create(128); prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t)); prebuilt->magic_n = ROW_PREBUILT_ALLOCATED; prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED; prebuilt->table = table; prebuilt->trx = NULL; prebuilt->sql_stat_start = TRUE; prebuilt->mysql_has_locked = FALSE; prebuilt->index = NULL; prebuilt->used_in_HANDLER = FALSE; prebuilt->n_template = 0; prebuilt->mysql_template = NULL; prebuilt->heap = heap; prebuilt->ins_node = NULL; prebuilt->ins_upd_rec_buff = NULL; prebuilt->upd_node = NULL; prebuilt->ins_graph = NULL; prebuilt->upd_graph = NULL; prebuilt->pcur = btr_pcur_create_for_mysql(); prebuilt->clust_pcur = btr_pcur_create_for_mysql(); prebuilt->select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = 99999999; prebuilt->sel_graph = NULL; prebuilt->search_tuple = dtuple_create(heap, 2 * dict_table_get_n_cols(table)); clust_index = dict_table_get_first_index(table); /* Make sure that search_tuple is long enough for clustered index */ ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields); ref_len = dict_index_get_n_unique(clust_index); ref = dtuple_create(heap, ref_len); dict_index_copy_types(ref, clust_index, ref_len); prebuilt->clust_ref = ref; for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) { prebuilt->fetch_cache[i] = NULL; } prebuilt->n_fetch_cached = 0; prebuilt->blob_heap = NULL; prebuilt->old_vers_heap = NULL; return(prebuilt);}/************************************************************************Free a prebuilt struct for a MySQL table handle. */voidrow_prebuilt_free(/*==============*/ row_prebuilt_t* prebuilt) /* in, own: prebuilt struct */{ ulint i; if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) { fprintf(stderr,"InnoDB: Error: trying to free a corrupt\n""InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", (ulong) prebuilt->magic_n, (ulong) prebuilt->magic_n2); ut_print_name(stderr, NULL, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); ut_error; } prebuilt->magic_n = ROW_PREBUILT_FREED; prebuilt->magic_n2 = ROW_PREBUILT_FREED; btr_pcur_free_for_mysql(prebuilt->pcur); btr_pcur_free_for_mysql(prebuilt->clust_pcur); if (prebuilt->mysql_template) { mem_free(prebuilt->mysql_template); } if (prebuilt->ins_graph) { que_graph_free_recursive(prebuilt->ins_graph); } if (prebuilt->sel_graph) { que_graph_free_recursive(prebuilt->sel_graph); } if (prebuilt->upd_graph) { que_graph_free_recursive(prebuilt->upd_graph); } if (prebuilt->blob_heap) { mem_heap_free(prebuilt->blob_heap); } if (prebuilt->old_vers_heap) { mem_heap_free(prebuilt->old_vers_heap); } for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) { if (prebuilt->fetch_cache[i] != NULL) { if ((ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4((prebuilt->fetch_cache[i]) - 4)) || (ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4((prebuilt->fetch_cache[i]) + prebuilt->mysql_row_len))) { fputs( "InnoDB: Error: trying to free a corrupt\n" "InnoDB: fetch buffer.\n", stderr); mem_analyze_corruption( prebuilt->fetch_cache[i]); ut_error; } mem_free((prebuilt->fetch_cache[i]) - 4); } } dict_table_decrement_handle_count(prebuilt->table); mem_heap_free(prebuilt->heap);}/*************************************************************************Updates the transaction pointers in query graphs stored in the prebuiltstruct. */voidrow_update_prebuilt_trx(/*====================*/ /* out: prebuilt dtuple */ row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL handle */ trx_t* trx) /* in: transaction handle */{ if (trx->magic_n != TRX_MAGIC_N) { fprintf(stderr, "InnoDB: Error: trying to use a corrupt\n" "InnoDB: trx handle. Magic n %lu\n", (ulong) trx->magic_n); mem_analyze_corruption((byte*)trx); ut_error; } if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to use a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); ut_print_name(stderr, NULL, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); ut_error; } prebuilt->trx = trx; if (prebuilt->ins_graph) { prebuilt->ins_graph->trx = trx; } if (prebuilt->upd_graph) { prebuilt->upd_graph->trx = trx; } if (prebuilt->sel_graph) { prebuilt->sel_graph->trx = trx; } }/*************************************************************************Gets pointer to a prebuilt dtuple used in insertions. If the insert graphhas not yet been built in the prebuilt struct, then this function firstbuilds it. */staticdtuple_t*row_get_prebuilt_insert_row(/*========================*/ /* out: prebuilt dtuple; the column type information is also set in it */ row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL handle */{ ins_node_t* node; dtuple_t* row; dict_table_t* table = prebuilt->table; ulint i; ut_ad(prebuilt && table && prebuilt->trx); if (prebuilt->ins_node == NULL) { /* Not called before for this handle: create an insert node and query graph to the prebuilt struct */ node = ins_node_create(INS_DIRECT, table, prebuilt->heap); prebuilt->ins_node = node; if (prebuilt->ins_upd_rec_buff == NULL) { prebuilt->ins_upd_rec_buff = mem_heap_alloc( prebuilt->heap, prebuilt->mysql_row_len); } row = dtuple_create(prebuilt->heap, dict_table_get_n_cols(table)); dict_table_copy_types(row, table); /* We init the value of every field to the SQL NULL to avoid a debug assertion from failing */ for (i = 0; i < dtuple_get_n_fields(row); i++) { dtuple_get_nth_field(row, i)->len = UNIV_SQL_NULL; } ins_node_set_new_row(node, row); prebuilt->ins_graph = que_node_get_parent( pars_complete_graph_for_exec(node, prebuilt->trx, prebuilt->heap)); prebuilt->ins_graph->state = QUE_FORK_ACTIVE; } return(prebuilt->ins_node->row); }/*************************************************************************Updates the table modification counter and calculates new estimatesfor table and index statistics if necessary. */UNIV_INLINEvoidrow_update_statistics_if_needed(/*============================*/ dict_table_t* table) /* in: table */{ ulint counter; counter = table->stat_modified_counter; table->stat_modified_counter = counter + 1; /* Calculate new statistics if 1 / 16 of table has been modified since the last time a statistics batch was run, or if stat_modified_counter > 2 000 000 000 (to avoid wrap-around). We calculate statistics at most every 16th round, since we may have a counter table which is very small and updated very often. */ if (counter > 2000000000 || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) { dict_update_statistics(table); } } /*************************************************************************Unlocks an AUTO_INC type lock possibly reserved by trx. */void row_unlock_table_autoinc_for_mysql(/*===============================*/ trx_t* trx) /* in: transaction */{ if (!trx->auto_inc_lock) { return; } lock_table_unlock_auto_inc(trx);}/*************************************************************************Sets an AUTO_INC type lock on the table mentioned in prebuilt. TheAUTO_INC lock gives exclusive access to the auto-inc counter of thetable. The lock is reserved only for the duration of an SQL statement.It is not compatible with another AUTO_INC or exclusive lock on thetable. */introw_lock_table_autoinc_for_mysql(/*=============================*/ /* out: error code or DB_SUCCESS */ row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL table handle */{ trx_t* trx = prebuilt->trx; ins_node_t* node = prebuilt->ins_node; que_thr_t* thr; ulint err; ibool was_lock_wait; ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (trx->auto_inc_lock) { return(DB_SUCCESS); } trx->op_info = "setting auto-inc lock"; if (node == NULL) { row_get_prebuilt_insert_row(prebuilt); node = prebuilt->ins_node; } /* We use the insert query graph as the dummy graph needed in the lock module call */ thr = que_fork_get_first_thr(prebuilt->ins_graph); que_thr_move_to_run_state_for_mysql(thr, trx);run_again: thr->run_node = node; thr->prev_node = node; /* It may be that the current session has not yet started its transaction, or it has been committed: */ trx_start_if_not_started(trx); err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); trx->error_state = err; if (err != DB_SUCCESS) { que_thr_stop_for_mysql(thr); was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); if (was_lock_wait) { goto run_again; } trx->op_info = ""; return((int) err); } que_thr_stop_for_mysql_no_error(thr, trx); trx->op_info = ""; return((int) err);}/*************************************************************************Sets a table lock on the table mentioned in prebuilt. */introw_lock_table_for_mysql(/*=====================*/ /* out: error code or DB_SUCCESS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -