📄 que0que.c
字号:
} else if (fork_type == QUE_FORK_RECOVERY) { /* Do nothing */ } else if (fork_type == QUE_FORK_MYSQL_INTERFACE) { /* Do nothing */ } else { ut_error; /* not used in MySQL */ } } if (UT_LIST_GET_LEN(trx->signals) > 0 && trx->n_active_thrs == 0) { /* If the trx is signaled and its query thread count drops to zero, then we start processing a signal; from it we may get a new query thread to run */ trx_sig_start_handle(trx, next_thr); } if (trx->handling_signals && UT_LIST_GET_LEN(trx->signals) == 0) { trx_end_signal_handling(trx); } mutex_exit(&kernel_mutex);}/**************************************************************************Stops a query thread if graph or trx is in a state requiring it. Theconditions are tested in the order (1) graph, (2) trx. The kernel mutex hasto be reserved. */iboolque_thr_stop(/*=========*/ /* out: TRUE if stopped */ que_thr_t* thr) /* in: query thread */{ trx_t* trx; que_t* graph; ibool ret = TRUE;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */ graph = thr->graph; trx = graph->trx; if (graph->state == QUE_FORK_COMMAND_WAIT) { thr->state = QUE_THR_SUSPENDED; } else if (trx->que_state == TRX_QUE_LOCK_WAIT) { UT_LIST_ADD_FIRST(trx_thrs, trx->wait_thrs, thr); thr->state = QUE_THR_LOCK_WAIT; } else if (trx->error_state != DB_SUCCESS && trx->error_state != DB_LOCK_WAIT) { /* Error handling built for the MySQL interface */ thr->state = QUE_THR_COMPLETED; } else if (UT_LIST_GET_LEN(trx->signals) > 0 && graph->fork_type != QUE_FORK_ROLLBACK) { thr->state = QUE_THR_SUSPENDED; } else { ut_ad(graph->state == QUE_FORK_ACTIVE); ret = FALSE; } return(ret);}/**************************************************************************A patch for MySQL used to 'stop' a dummy query thread used in MySQL. Thequery thread is stopped and made inactive, except in the case whereit was put to the lock wait state in lock0lock.c, but the lock has alreadybeen granted or the transaction chosen as a victim in deadlock resolution. */voidque_thr_stop_for_mysql(/*===================*/ que_thr_t* thr) /* in: query thread */{ trx_t* trx; trx = thr_get_trx(thr); mutex_enter(&kernel_mutex); if (thr->state == QUE_THR_RUNNING) { if (trx->error_state != DB_SUCCESS && trx->error_state != DB_LOCK_WAIT) { /* Error handling built for the MySQL interface */ thr->state = QUE_THR_COMPLETED; } else { /* It must have been a lock wait but the lock was already released, or this transaction was chosen as a victim in selective deadlock resolution */ mutex_exit(&kernel_mutex); return; } } ut_ad(thr->is_active == TRUE); ut_ad(trx->n_active_thrs == 1); ut_ad(thr->graph->n_active_thrs == 1); thr->is_active = FALSE; (thr->graph)->n_active_thrs--; trx->n_active_thrs--; mutex_exit(&kernel_mutex);}/**************************************************************************Moves a thread from another state to the QUE_THR_RUNNING state. Incrementsthe n_active_thrs counters of the query graph and transaction if thr wasnot active. */voidque_thr_move_to_run_state_for_mysql(/*================================*/ que_thr_t* thr, /* in: an query thread */ trx_t* trx) /* in: transaction */{ if (thr->magic_n != QUE_THR_MAGIC_N) { fprintf(stderr, "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); mem_analyze_corruption((byte*)thr); ut_error; } if (!thr->is_active) { thr->graph->n_active_thrs++; trx->n_active_thrs++; thr->is_active = TRUE; } thr->state = QUE_THR_RUNNING;}/**************************************************************************A patch for MySQL used to 'stop' a dummy query thread used in MySQLselect, when there is no error or lock wait. */voidque_thr_stop_for_mysql_no_error(/*============================*/ que_thr_t* thr, /* in: query thread */ trx_t* trx) /* in: transaction */{ ut_ad(thr->state == QUE_THR_RUNNING); ut_ad(thr->is_active == TRUE); ut_ad(trx->n_active_thrs == 1); ut_ad(thr->graph->n_active_thrs == 1); if (thr->magic_n != QUE_THR_MAGIC_N) { fprintf(stderr, "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); mem_analyze_corruption((byte*)thr); ut_error; } thr->state = QUE_THR_COMPLETED; thr->is_active = FALSE; (thr->graph)->n_active_thrs--; trx->n_active_thrs--;}/**************************************************************************Prints info of an SQL query graph node. */voidque_node_print_info(/*================*/ que_node_t* node) /* in: query graph node */{ ulint type; const char* str; type = que_node_get_type(node); if (type == QUE_NODE_SELECT) { str = "SELECT"; } else if (type == QUE_NODE_INSERT) { str = "INSERT"; } else if (type == QUE_NODE_UPDATE) { str = "UPDATE"; } else if (type == QUE_NODE_WHILE) { str = "WHILE"; } else if (type == QUE_NODE_ASSIGNMENT) { str = "ASSIGNMENT"; } else if (type == QUE_NODE_IF) { str = "IF"; } else if (type == QUE_NODE_FETCH) { str = "FETCH"; } else if (type == QUE_NODE_OPEN) { str = "OPEN"; } else if (type == QUE_NODE_PROC) { str = "STORED PROCEDURE"; } else if (type == QUE_NODE_FUNC) { str = "FUNCTION"; } else if (type == QUE_NODE_LOCK) { str = "LOCK"; } else if (type == QUE_NODE_THR) { str = "QUERY THREAD"; } else if (type == QUE_NODE_COMMIT) { str = "COMMIT"; } else if (type == QUE_NODE_UNDO) { str = "UNDO ROW"; } else if (type == QUE_NODE_PURGE) { str = "PURGE ROW"; } else if (type == QUE_NODE_ROLLBACK) { str = "ROLLBACK"; } else if (type == QUE_NODE_CREATE_TABLE) { str = "CREATE TABLE"; } else if (type == QUE_NODE_CREATE_INDEX) { str = "CREATE INDEX"; } else if (type == QUE_NODE_FOR) { str = "FOR LOOP"; } else if (type == QUE_NODE_RETURN) { str = "RETURN"; } else { str = "UNKNOWN NODE TYPE"; } fprintf(stderr, "Node type %lu: %s, address %p\n", (ulong) type, str, node);}/**************************************************************************Performs an execution step on a query thread. */UNIV_INLINEque_thr_t*que_thr_step(/*=========*/ /* out: query thread to run next: it may differ from the input parameter if, e.g., a subprocedure call is made */ que_thr_t* thr) /* in: query thread */{ que_node_t* node; que_thr_t* old_thr; trx_t* trx; ulint type; ut_ad(thr->state == QUE_THR_RUNNING); thr->resource++; type = que_node_get_type(thr->run_node); node = thr->run_node; old_thr = thr; #ifdef UNIV_DEBUG if (que_trace_on) { fputs("To execute: ", stderr); que_node_print_info(node); }#endif if (type & QUE_NODE_CONTROL_STAT) { if ((thr->prev_node != que_node_get_parent(node)) && que_node_get_next(thr->prev_node)) { /* The control statements, like WHILE, always pass the control to the next child statement if there is any child left */ thr->run_node = que_node_get_next(thr->prev_node); } else if (type == QUE_NODE_IF) { if_step(thr); } else if (type == QUE_NODE_FOR) { for_step(thr); } else if (type == QUE_NODE_PROC) { /* We can access trx->undo_no without reserving trx->undo_mutex, because there cannot be active query threads doing updating or inserting at the moment! */ if (thr->prev_node == que_node_get_parent(node)) { trx = thr_get_trx(thr); trx->last_sql_stat_start.least_undo_no = trx->undo_no; } proc_step(thr); } else if (type == QUE_NODE_WHILE) { while_step(thr); } } else if (type == QUE_NODE_ASSIGNMENT) { assign_step(thr); } else if (type == QUE_NODE_SELECT) { thr = row_sel_step(thr); } else if (type == QUE_NODE_INSERT) { thr = row_ins_step(thr); } else if (type == QUE_NODE_UPDATE) { thr = row_upd_step(thr); } else if (type == QUE_NODE_FETCH) { thr = fetch_step(thr); } else if (type == QUE_NODE_OPEN) { thr = open_step(thr); } else if (type == QUE_NODE_FUNC) { proc_eval_step(thr); } else if (type == QUE_NODE_LOCK) { ut_error;/* thr = que_lock_step(thr);*/ } else if (type == QUE_NODE_THR) { thr = que_thr_node_step(thr); } else if (type == QUE_NODE_COMMIT) { thr = trx_commit_step(thr); } else if (type == QUE_NODE_UNDO) { thr = row_undo_step(thr); } else if (type == QUE_NODE_PURGE) { thr = row_purge_step(thr); } else if (type == QUE_NODE_RETURN) { thr = return_step(thr); } else if (type == QUE_NODE_ROLLBACK) { thr = trx_rollback_step(thr); } else if (type == QUE_NODE_CREATE_TABLE) { thr = dict_create_table_step(thr); } else if (type == QUE_NODE_CREATE_INDEX) { thr = dict_create_index_step(thr); } else if (type == QUE_NODE_ROW_PRINTF) { thr = row_printf_step(thr); } else { ut_error; } old_thr->prev_node = node; return(thr);}/**************************************************************************Runs query threads. Note that the individual query thread which is runwithin this function may change if, e.g., the OS thread executing thisfunction uses a threshold amount of resources. */voidque_run_threads(/*============*/ que_thr_t* thr) /* in: query thread which is run initially */{ que_thr_t* next_thr; ulint cumul_resource; ulint loop_count; ut_ad(thr->state == QUE_THR_RUNNING);#ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */ /* cumul_resource counts how much resources the OS thread (NOT the query thread) has spent in this function */ loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; cumul_resource = 0; loop: /* Check that there is enough space in the log to accommodate possible log entries by this query step; if the operation can touch more than about 4 pages, checks must be made also within the query step! */ log_free_check(); /* Perform the actual query step: note that the query thread may change if, e.g., a subprocedure call is made */ /*-------------------------*/ next_thr = que_thr_step(thr); /*-------------------------*/ /* Test the effect on performance of adding extra mutex reservations *//* if (srv_test_extra_mutexes) { mutex_enter(&kernel_mutex); mutex_exit(&kernel_mutex); } */ loop_count++; if (next_thr != thr) { ut_a(next_thr == NULL); que_thr_dec_refer_count(thr, &next_thr); if (next_thr == NULL) { return; } loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; thr = next_thr; } goto loop;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -