📄 srv0srv.c
字号:
srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)); for (i = 0; i < OS_THREAD_MAX_N; i++) { slot = srv_mysql_table + i; slot->in_use = FALSE; slot->type = 0; slot->event = os_event_create(NULL); ut_a(slot->event); } srv_lock_timeout_thread_event = os_event_create(NULL); for (i = 0; i < SRV_MASTER + 1; i++) { srv_n_threads_active[i] = 0; srv_n_threads[i] = 0; srv_meter[i] = 30; srv_meter_low_water[i] = 50; srv_meter_high_water[i] = 100; srv_meter_high_water2[i] = 200; srv_meter_foreground[i] = 250; } srv_sys->operational = os_event_create(NULL); ut_a(srv_sys->operational); UT_LIST_INIT(srv_sys->tasks); /* create dummy table and index for old-style infimum and supremum */ table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, FALSE); dict_mem_table_add_col(table, "DUMMY", DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0); srv_sys->dummy_ind1 = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1", DICT_HDR_SPACE, 0, 1); dict_index_add_col(srv_sys->dummy_ind1, dict_table_get_nth_col(table, 0), 0, 0); srv_sys->dummy_ind1->table = table; /* create dummy table and index for new-style infimum and supremum */ table = dict_mem_table_create("SYS_DUMMY2", DICT_HDR_SPACE, 1, TRUE); dict_mem_table_add_col(table, "DUMMY", DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0); srv_sys->dummy_ind2 = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2", DICT_HDR_SPACE, 0, 1); dict_index_add_col(srv_sys->dummy_ind2, dict_table_get_nth_col(table, 0), 0, 0); srv_sys->dummy_ind2->table = table; /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ srv_sys->dummy_ind1->cached = srv_sys->dummy_ind2->cached = TRUE; /* Init the server concurrency restriction data structures */ os_fast_mutex_init(&srv_conc_mutex); UT_LIST_INIT(srv_conc_queue); srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t)); for (i = 0; i < OS_THREAD_MAX_N; i++) { conc_slot = srv_conc_slots + i; conc_slot->reserved = FALSE; conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); }} /*************************************************************************Frees the OS fast mutex created in srv_init(). */voidsrv_free(void)/*==========*/{ os_fast_mutex_free(&srv_conc_mutex);}/*************************************************************************Initializes the synchronization primitives, memory system, and the threadlocal storage. */voidsrv_general_init(void)/*==================*/{ os_sync_init(); sync_init(); mem_init(srv_mem_pool_size); thr_local_init();}/*======================= InnoDB Server FIFO queue =======================*//* Maximum allowable purge history length. <=0 means 'infinite'. */ulong srv_max_purge_lag = 0;/*************************************************************************Puts an OS thread to wait if there are too many concurrent threads(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */voidsrv_conc_enter_innodb(/*==================*/ trx_t* trx) /* in: transaction object associated with the thread */{ ibool has_slept = FALSE; srv_conc_slot_t* slot = NULL; ulint i; /* If trx has 'free tickets' to enter the engine left, then use one such ticket */ if (trx->n_tickets_to_enter_innodb > 0) { trx->n_tickets_to_enter_innodb--; return; } os_fast_mutex_lock(&srv_conc_mutex);retry: if (trx->declared_to_be_inside_innodb) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: trying to declare trx to enter InnoDB, but\n""InnoDB: it already is declared.\n", stderr); trx_print(stderr, trx, 0); putc('\n', stderr); os_fast_mutex_unlock(&srv_conc_mutex); return; } if (srv_conc_n_threads < (lint)srv_thread_concurrency) { srv_conc_n_threads++; trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; os_fast_mutex_unlock(&srv_conc_mutex); return; } /* If the transaction is not holding resources, let it sleep for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */ if (!has_slept && !trx->has_search_latch && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) { has_slept = TRUE; /* We let is sleep only once to avoid starvation */ srv_conc_n_waiting_threads++; os_fast_mutex_unlock(&srv_conc_mutex); trx->op_info = "sleeping before joining InnoDB queue"; /* Peter Zaitsev suggested that we take the sleep away altogether. But the sleep may be good in pathological situations of lots of thread switches. Simply put some threads aside for a while to reduce the number of thread switches. */ if (SRV_THREAD_SLEEP_DELAY > 0) { os_thread_sleep(SRV_THREAD_SLEEP_DELAY); } trx->op_info = ""; os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_waiting_threads--; goto retry; } /* Too many threads inside: put the current thread to a queue */ for (i = 0; i < OS_THREAD_MAX_N; i++) { slot = srv_conc_slots + i; if (!slot->reserved) { break; } } if (i == OS_THREAD_MAX_N) { /* Could not find a free wait slot, we must let the thread enter */ srv_conc_n_threads++; trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 0; os_fast_mutex_unlock(&srv_conc_mutex); return; } /* Release possible search system latch this thread has */ if (trx->has_search_latch) { trx_search_latch_release_if_reserved(trx); } /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); os_event_reset(slot->event); srv_conc_n_waiting_threads++; os_fast_mutex_unlock(&srv_conc_mutex); /* Go to wait for the event; when a thread leaves InnoDB it will release this thread */ trx->op_info = "waiting in InnoDB queue"; os_event_wait(slot->event); trx->op_info = ""; os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_waiting_threads--; /* NOTE that the thread which released this thread already incremented the thread counter on behalf of this thread */ slot->reserved = FALSE; UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; os_fast_mutex_unlock(&srv_conc_mutex);}/*************************************************************************This lets a thread enter InnoDB regardless of the number of threads insideInnoDB. This must be called when a thread ends a lock wait. */voidsrv_conc_force_enter_innodb(/*========================*/ trx_t* trx) /* in: transaction object associated with the thread */{ if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_threads++; trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 0; os_fast_mutex_unlock(&srv_conc_mutex);}/*************************************************************************This must be called when a thread exits InnoDB in a lock wait or at theend of an SQL statement. */voidsrv_conc_force_exit_innodb(/*=======================*/ trx_t* trx) /* in: transaction object associated with the thread */{ srv_conc_slot_t* slot = NULL; if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } if (trx->declared_to_be_inside_innodb == FALSE) { return; } os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_threads--; trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; if (srv_conc_n_threads < (lint)srv_thread_concurrency) { /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ slot = UT_LIST_GET_FIRST(srv_conc_queue); while (slot && slot->wait_ended == TRUE) { slot = UT_LIST_GET_NEXT(srv_conc_queue, slot); } if (slot != NULL) { slot->wait_ended = TRUE; /* We increment the count on behalf of the released thread */ srv_conc_n_threads++; } } os_fast_mutex_unlock(&srv_conc_mutex); if (slot != NULL) { os_event_set(slot->event); }}/*************************************************************************This must be called when a thread exits InnoDB. */voidsrv_conc_exit_innodb(/*=================*/ trx_t* trx) /* in: transaction object associated with the thread */{ if (trx->n_tickets_to_enter_innodb > 0) { /* We will pretend the thread is still inside InnoDB though it now leaves the InnoDB engine. In this way we save a lot of semaphore operations. srv_conc_force_exit_innodb is used to declare the thread definitely outside InnoDB. It should be called when there is a lock wait or an SQL statement ends. */ return; } srv_conc_force_exit_innodb(trx);}/*========================================================================*//*************************************************************************Normalizes init parameter values to use units we use inside InnoDB. */staticulintsrv_normalize_init_values(void)/*===========================*/ /* out: DB_SUCCESS or error code */{ ulint n; ulint i; n = srv_n_data_files; for (i = 0; i < n; i++) { srv_data_file_sizes[i] = srv_data_file_sizes[i] * ((1024 * 1024) / UNIV_PAGE_SIZE); } srv_last_file_size_max = srv_last_file_size_max * ((1024 * 1024) / UNIV_PAGE_SIZE); srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE; srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE; srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024); srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE; if (srv_use_awe) { /* If we are using AWE we must save memory in the 32-bit address space of the process, and cannot bind the lock table size to the real buffer pool size. */ srv_lock_table_size = 20 * srv_awe_window_size; } else { srv_lock_table_size = 5 * srv_pool_size; } return(DB_SUCCESS);}/*************************************************************************Boots the InnoDB server. */ulintsrv_boot(void)/*==========*/ /* out: DB_SUCCESS or error code */{ ulint err; /* Transform the init parameter values given by MySQL to use units we use inside InnoDB: */ err = srv_normalize_init_values(); if (err != DB_SUCCESS) { return(err); } /* Initialize synchronization primitives, memory management, and thread local storage */ srv_general_init(); /* Initialize this module */ srv_init(); return(DB_SUCCESS);}#ifndef UNIV_HOTBACKUP/*************************************************************************Reserves a slot in the thread table for the current MySQL OS thread.NOTE! The kernel mutex has to be reserved by the caller! */staticsrv_slot_t*srv_table_reserve_slot_for_mysql(void)/*==================================*/ /* out: reserved slot */{ srv_slot_t* slot; ulint i;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */ i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -