📄 row0mysql.c
字号:
return(DB_SUCCESS); } trx->op_info = "unlock_row"; index = btr_pcur_get_btr_cur(pcur)->index; if (UNIV_UNLIKELY(index == NULL)) { fprintf(stderr,"InnoDB: Error: Index is not set for persistent cursor.\n"); ut_print_buf(stderr, (const byte*)pcur, sizeof(btr_pcur_t)); ut_error; } if (trx_new_rec_locks_contain(trx, index)) { mtr_start(&mtr); /* Restore the cursor position and find the record */ if (!has_latches_on_recs) { btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr); } rec = btr_pcur_get_rec(pcur); lock_rec_unlock(trx, rec, prebuilt->select_lock_type); mtr_commit(&mtr); /* If the search was done through the clustered index, then we have not used clust_pcur at all, and we must NOT try to reset locks on clust_pcur. The values in clust_pcur may be garbage! */ if (index->type & DICT_CLUSTERED) { goto func_exit; } } index = btr_pcur_get_btr_cur(clust_pcur)->index; if (index != NULL && trx_new_rec_locks_contain(trx, index)) { mtr_start(&mtr); /* Restore the cursor position and find the record */ if (!has_latches_on_recs) { btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur, &mtr); } rec = btr_pcur_get_rec(clust_pcur); lock_rec_unlock(trx, rec, prebuilt->select_lock_type); mtr_commit(&mtr); } func_exit: trx->op_info = ""; return(DB_SUCCESS);}/**************************************************************************Does a cascaded delete or set null in a foreign key operation. */ulintrow_update_cascade_for_mysql(/*=========================*/ /* out: error code or DB_SUCCESS */ que_thr_t* thr, /* in: query thread */ upd_node_t* node, /* in: update node used in the cascade or set null operation */ dict_table_t* table) /* in: table where we do the operation */{ ulint err; trx_t* trx; trx = thr_get_trx(thr);run_again: thr->run_node = node; thr->prev_node = node; row_upd_step(thr); err = trx->error_state; /* Note that the cascade node is a subnode of another InnoDB query graph node. We do a normal lock wait in this node, but all errors are handled by the parent node. */ if (err == DB_LOCK_WAIT) { /* Handle lock wait here */ que_thr_stop_for_mysql(thr); srv_suspend_mysql_thread(thr); /* Note that a lock wait may also end in a lock wait timeout, or this transaction is picked as a victim in selective deadlock resolution */ if (trx->error_state != DB_SUCCESS) { return(trx->error_state); } /* Retry operation after a normal lock wait */ goto run_again; } if (err != DB_SUCCESS) { return(err); } if (node->is_delete) { if (table->stat_n_rows > 0) { table->stat_n_rows--; } srv_n_rows_deleted++; } else { srv_n_rows_updated++; } row_update_statistics_if_needed(table); return(err);}/*************************************************************************Checks if a table is such that we automatically created a clusteredindex on it (on row id). */iboolrow_table_got_default_clust_index(/*==============================*/ dict_table_t* table){ dict_index_t* clust_index; clust_index = dict_table_get_first_index(table); if (dtype_get_mtype(dict_index_get_nth_type(clust_index, 0)) == DATA_SYS) { return(TRUE); } return(FALSE);}/*************************************************************************Calculates the key number used inside MySQL for an Innobase index. We haveto take into account if we generated a default clustered index for the table */ulintrow_get_mysql_key_number_for_index(/*===============================*/ dict_index_t* index){ dict_index_t* ind; ulint i; ut_a(index); i = 0; ind = dict_table_get_first_index(index->table); while (index != ind) { ind = dict_table_get_next_index(ind); i++; } if (row_table_got_default_clust_index(index->table)) { ut_a(i > 0); i--; } return(i);}/*************************************************************************Recovers an orphaned tmp table inside InnoDB by renaming it. In the tablename #sql becomes rsql, and "_recover_innodb_tmp_table" is catenated tothe end of name. table->name should be of the form"dbname/rsql..._recover_innodb_tmp_table". This renames a table whosename is "#sql..." */staticintrow_mysql_recover_tmp_table(/*========================*/ /* out: error code or DB_SUCCESS */ dict_table_t* table, /* in: table definition */ trx_t* trx) /* in: transaction handle */{ const char* ptr = strstr(table->name, "/rsql"); if (!ptr) { /* table name does not begin with "/rsql" */ trx_commit_for_mysql(trx); return(DB_ERROR); } else { int status; int namelen = (int) strlen(table->name); char* old_name = mem_strdupl(table->name, namelen); /* replace "rsql" with "#sql" */ old_name[ptr - table->name + 1] = '#'; /* remove "_recover_innodb_tmp_table" suffix */ ut_ad(namelen > (int) sizeof S_recover_innodb_tmp_table); ut_ad(!strcmp(old_name + namelen + 1 - sizeof S_recover_innodb_tmp_table, S_recover_innodb_tmp_table)); old_name[namelen + 1 - sizeof S_recover_innodb_tmp_table] = 0; status = row_rename_table_for_mysql(old_name, table->name, trx); mem_free(old_name); return(status); }}/*************************************************************************Locks the data dictionary in shared mode from modifications, for performingforeign key check, rollback, or other operation invisible to MySQL. */voidrow_mysql_freeze_data_dictionary(/*=============================*/ trx_t* trx) /* in: transaction */{ ut_a(trx->dict_operation_lock_mode == 0); rw_lock_s_lock(&dict_operation_lock); trx->dict_operation_lock_mode = RW_S_LATCH;}/*************************************************************************Unlocks the data dictionary shared lock. */voidrow_mysql_unfreeze_data_dictionary(/*===============================*/ trx_t* trx) /* in: transaction */{ ut_a(trx->dict_operation_lock_mode == RW_S_LATCH); rw_lock_s_unlock(&dict_operation_lock); trx->dict_operation_lock_mode = 0;}/*************************************************************************Locks the data dictionary exclusively for performing a table create or otherdata dictionary modification operation. */voidrow_mysql_lock_data_dictionary(/*===========================*/ trx_t* trx) /* in: transaction */{ ut_a(trx->dict_operation_lock_mode == 0 || trx->dict_operation_lock_mode == RW_X_LATCH); /* Serialize data dictionary operations with dictionary mutex: no deadlocks or lock waits can occur then in these operations */ rw_lock_x_lock(&dict_operation_lock); trx->dict_operation_lock_mode = RW_X_LATCH; mutex_enter(&(dict_sys->mutex));}/*************************************************************************Unlocks the data dictionary exclusive lock. */voidrow_mysql_unlock_data_dictionary(/*=============================*/ trx_t* trx) /* in: transaction */{ ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ mutex_exit(&(dict_sys->mutex)); rw_lock_x_unlock(&dict_operation_lock); trx->dict_operation_lock_mode = 0;}/*************************************************************************Does a table creation operation for MySQL. If the name of the tableto be created is equal with one of the predefined magic table names,then this also starts printing the corresponding monitor output bythe master thread. */introw_create_table_for_mysql(/*=======================*/ /* out: error code or DB_SUCCESS */ dict_table_t* table, /* in: table definition */ trx_t* trx) /* in: transaction handle */{ tab_node_t* node; mem_heap_t* heap; que_thr_t* thr; const char* table_name; ulint table_name_len; ulint err; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); if (srv_created_new_raw) { fputs( "InnoDB: A new raw disk partition was initialized or\n" "InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" "InnoDB: with raw, and innodb_force_... is removed.\n", stderr); trx_commit_for_mysql(trx); return(DB_ERROR); } trx->op_info = "creating table"; if (row_mysql_is_system_table(table->name)) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" "InnoDB: MySQL system tables must be of the MyISAM type!\n", table->name); trx_commit_for_mysql(trx); return(DB_ERROR); } trx_start_if_not_started(trx); if (row_mysql_is_recovered_tmp_table(table->name)) { /* MySQL prevents accessing of tables whose name begins with #sql, that is temporary tables. If mysqld crashes in the middle of an ALTER TABLE, we may get an orphaned #sql-table in the tablespace. We have here a special mechanism to recover such tables by renaming them to rsql... */ return(row_mysql_recover_tmp_table(table, trx)); } /* The table name is prefixed with the database name and a '/'. Certain table names starting with 'innodb_' have their special meaning regardless of the database name. Thus, we need to ignore the database name prefix in the comparisons. */ table_name = strchr(table->name, '/'); ut_a(table_name); table_name++; table_name_len = strlen(table_name) + 1; if (table_name_len == sizeof S_innodb_monitor && !memcmp(table_name, S_innodb_monitor, sizeof S_innodb_monitor)) { /* Table equals "innodb_monitor": start monitor prints */ srv_print_innodb_monitor = TRUE; /* The lock timeout monitor thread also takes care of InnoDB monitor prints */ os_event_set(srv_lock_timeout_thread_event); } else if (table_name_len == sizeof S_innodb_lock_monitor && !memcmp(table_name, S_innodb_lock_monitor, sizeof S_innodb_lock_monitor)) { srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } else if (table_name_len == sizeof S_innodb_tablespace_monitor && !memcmp(table_name, S_innodb_tablespace_monitor, sizeof S_innodb_tablespace_monitor)) { srv_print_innodb_tablespace_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } else if (table_name_len == sizeof S_innodb_table_monitor && !memcmp(table_name, S_innodb_table_monitor, sizeof S_innodb_table_monitor)) { srv_print_innodb_table_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } else if (table_name_len == sizeof S_innodb_mem_validate && !memcmp(table_name, S_innodb_mem_validate, sizeof S_innodb_mem_validate)) { /* We define here a debugging feature intended for developers */ fputs("Validating InnoDB memory:\n" "to use this feature you must compile InnoDB with\n" "UNIV_MEM_DEBUG defined in univ.i and the server must be\n" "quiet because allocation from a mem heap is not protected\n" "by any semaphore.\n", stderr);#ifdef UNIV_MEM_DEBUG ut_a(mem_validate()); fputs("Memory validated\n", stderr);#else /* UNIV_MEM_DEBUG */ fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n", stderr);#endif /* UNIV_MEM_DEBUG */ } heap = mem_heap_create(512); trx->dict_operation = TRUE; node = tab_create_graph_create(table, heap); thr = pars_complete_graph_for_exec(node, trx, heap); ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); que_run_threads(thr); err = trx->error_state; if (err != DB_SUCCESS) { /* We have special error handling here */ trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); if (err == DB_OUT_OF_FILE_SPACE) { ut_print_timestamp(stderr); fputs(" InnoDB: Warning: cannot create table ", stderr); ut_print_name(stderr, trx, table->name); fputs(" because tablespace full\n", stderr); if (dict_table_get_low(table->name)) { row_drop_table_for_mysql(table->name, trx, FALSE); } } else if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); ut_print_name(stderr, trx, table->name); fputs(" already exists in InnoDB internal\n" "InnoDB: data dictionary. Have you deleted the .frm file\n" "InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n" "InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n" "InnoDB: See the Restrictions section of the InnoDB manual.\n" "InnoDB: You can drop the orphaned table inside InnoDB by\n" "InnoDB: creating an InnoDB table with the same name in another\n" "InnoDB: database and copying the .frm file to the current database.\n" "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" "InnoDB: succeed.\n" "InnoDB: You can look for further help from\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n", stderr); } /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ trx->error_state = DB_SUCCESS; } que_graph_free((que_t*) que_node_get_parent(thr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -