|
|
|
@ -56,53 +56,6 @@ bool innodb_inited= 0; |
|
|
|
*/ |
|
|
|
static handlerton *legacy_innodb_hton; |
|
|
|
|
|
|
|
/*-----------------------------------------------------------------*/ |
|
|
|
/* These variables are used to implement (semi-)synchronous MySQL binlog
|
|
|
|
replication for InnoDB tables. */ |
|
|
|
|
|
|
|
pthread_cond_t innobase_repl_cond; /* Posix cond variable;
|
|
|
|
this variable is signaled |
|
|
|
when enough binlog has been |
|
|
|
sent to slave, so that a |
|
|
|
waiting trx can return the |
|
|
|
'ok' message to the client |
|
|
|
for a commit */ |
|
|
|
pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex
|
|
|
|
that also protects the next |
|
|
|
innobase_repl_... variables */ |
|
|
|
uint innobase_repl_state; /* 1 if synchronous replication
|
|
|
|
is switched on and is working |
|
|
|
ok; else 0 */ |
|
|
|
uint innobase_repl_file_name_inited = 0; /* This is set to 1 when
|
|
|
|
innobase_repl_file_name |
|
|
|
contains meaningful data */ |
|
|
|
char* innobase_repl_file_name; /* The binlog name up to which
|
|
|
|
we have sent some binlog to |
|
|
|
the slave */ |
|
|
|
my_off_t innobase_repl_pos; /* The position in that file
|
|
|
|
up to which we have sent the |
|
|
|
binlog to the slave */ |
|
|
|
uint innobase_repl_n_wait_threads = 0; /* This tells how many
|
|
|
|
transactions currently are |
|
|
|
waiting for the binlog to be |
|
|
|
sent to the client */ |
|
|
|
uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1
|
|
|
|
when we know the 'smallest' |
|
|
|
wait position */ |
|
|
|
char* innobase_repl_wait_file_name; /* NULL, or the 'smallest'
|
|
|
|
innobase_repl_file_name that |
|
|
|
a transaction is waiting for */ |
|
|
|
my_off_t innobase_repl_wait_pos; /* The smallest position in
|
|
|
|
that file that a trx is |
|
|
|
waiting for: the trx can |
|
|
|
proceed and send an 'ok' to |
|
|
|
the client when MySQL has sent |
|
|
|
the binlog up to this position |
|
|
|
to the slave */ |
|
|
|
/*-----------------------------------------------------------------*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
|
|
|
|
uses unsigned char; the header univ.i which we include next defines |
|
|
|
'byte' as a macro which expands to 'unsigned char' */ |
|
|
|
@ -221,6 +174,139 @@ static handler *innobase_create_handler(handlerton *hton, |
|
|
|
return new (mem_root) ha_innobase(hton, table); |
|
|
|
} |
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
This function is used to prepare X/Open XA distributed transaction */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_xa_prepare( |
|
|
|
/*================*/ |
|
|
|
/* out: 0 or error number */ |
|
|
|
handlerton* hton, |
|
|
|
THD* thd, /* in: handle to the MySQL thread of the user
|
|
|
|
whose XA transaction should be prepared */ |
|
|
|
bool all); /* in: TRUE - commit transaction
|
|
|
|
FALSE - the current SQL statement ended */ |
|
|
|
/***********************************************************************
|
|
|
|
This function is used to recover X/Open XA distributed transactions */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_xa_recover( |
|
|
|
/*================*/ |
|
|
|
/* out: number of prepared transactions
|
|
|
|
stored in xid_list */ |
|
|
|
handlerton* hton, |
|
|
|
XID* xid_list, /* in/out: prepared transactions */ |
|
|
|
uint len); /* in: number of slots in xid_list */ |
|
|
|
/***********************************************************************
|
|
|
|
This function is used to commit one X/Open XA distributed transaction |
|
|
|
which is in the prepared state */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_commit_by_xid( |
|
|
|
/*===================*/ |
|
|
|
/* out: 0 or error number */ |
|
|
|
handlerton* hton, |
|
|
|
XID* xid); /* in: X/Open XA transaction identification */ |
|
|
|
/***********************************************************************
|
|
|
|
This function is used to rollback one X/Open XA distributed transaction |
|
|
|
which is in the prepared state */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_rollback_by_xid( |
|
|
|
/*=====================*/ |
|
|
|
/* out: 0 or error number */ |
|
|
|
handlerton* hton, |
|
|
|
XID *xid); /* in: X/Open XA transaction identification */ |
|
|
|
/***********************************************************************
|
|
|
|
Create a consistent view for a cursor based on current transaction |
|
|
|
which is created if the corresponding MySQL thread still lacks one. |
|
|
|
This consistent view is then used inside of MySQL when accessing records |
|
|
|
using a cursor. */ |
|
|
|
static |
|
|
|
void* |
|
|
|
innobase_create_cursor_view( |
|
|
|
/*========================*/ |
|
|
|
/* out: pointer to cursor view or NULL */ |
|
|
|
handlerton* hton, /* in: innobase hton */ |
|
|
|
THD* thd); /* in: user thread handle */ |
|
|
|
/***********************************************************************
|
|
|
|
Set the given consistent cursor view to a transaction which is created |
|
|
|
if the corresponding MySQL thread still lacks one. If the given |
|
|
|
consistent cursor view is NULL global read view of a transaction is |
|
|
|
restored to a transaction read view. */ |
|
|
|
static |
|
|
|
void |
|
|
|
innobase_set_cursor_view( |
|
|
|
/*=====================*/ |
|
|
|
handlerton* hton, |
|
|
|
THD* thd, /* in: user thread handle */ |
|
|
|
void* curview);/* in: Consistent cursor view to be set */ |
|
|
|
/***********************************************************************
|
|
|
|
Close the given consistent cursor view of a transaction and restore |
|
|
|
global read view to a transaction read view. Transaction is created if the |
|
|
|
corresponding MySQL thread still lacks one. */ |
|
|
|
static |
|
|
|
void |
|
|
|
innobase_close_cursor_view( |
|
|
|
/*=======================*/ |
|
|
|
handlerton* hton, |
|
|
|
THD* thd, /* in: user thread handle */ |
|
|
|
void* curview);/* in: Consistent read view to be closed */ |
|
|
|
/*********************************************************************
|
|
|
|
Removes all tables in the named database inside InnoDB. */ |
|
|
|
static |
|
|
|
void |
|
|
|
innobase_drop_database( |
|
|
|
/*===================*/ |
|
|
|
/* out: error number */ |
|
|
|
handlerton* hton, /* in: handlerton of Innodb */ |
|
|
|
char* path); /* in: database path; inside InnoDB the name
|
|
|
|
of the last directory in the path is used as |
|
|
|
the database name: for example, in 'mysql/data/test' |
|
|
|
the database name is 'test' */ |
|
|
|
/***********************************************************************
|
|
|
|
Closes an InnoDB database. */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_end(handlerton *hton, ha_panic_function type); |
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Creates an InnoDB transaction struct for the thd if it does not yet have one. |
|
|
|
Starts a new InnoDB transaction if a transaction is not yet started. And |
|
|
|
assigns a new snapshot for a consistent read if the transaction does not yet |
|
|
|
have one. */ |
|
|
|
static |
|
|
|
int |
|
|
|
innobase_start_trx_and_assign_read_view( |
|
|
|
/*====================================*/ |
|
|
|
/* out: 0 */ |
|
|
|
handlerton* hton, /* in: Innodb handlerton */ |
|
|
|
THD* thd); /* in: MySQL thread handle of the user for whom
|
|
|
|
the transaction should be committed */ |
|
|
|
/********************************************************************
|
|
|
|
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes |
|
|
|
the logs, and the name of this function should be innobase_checkpoint. */ |
|
|
|
static |
|
|
|
bool |
|
|
|
innobase_flush_logs( |
|
|
|
/*================*/ |
|
|
|
/* out: TRUE if error */ |
|
|
|
handlerton* hton); /* in: InnoDB handlerton */ |
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB |
|
|
|
Monitor to the client. */ |
|
|
|
static |
|
|
|
bool |
|
|
|
innodb_show_status( |
|
|
|
/*===============*/ |
|
|
|
handlerton* hton, /* in: the innodb handlerton */ |
|
|
|
THD* thd, /* in: the MySQL query thread of the caller */ |
|
|
|
stat_print_fn *stat_print); |
|
|
|
static |
|
|
|
bool innobase_show_status(handlerton *hton, THD* thd, |
|
|
|
stat_print_fn* stat_print, |
|
|
|
enum ha_stat_type stat_type); |
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Commits a transaction in an InnoDB database. */ |
|
|
|
@ -378,11 +464,24 @@ innobase_release_stat_resources( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
Obtain the InnoDB transaction of a MySQL thread. */ |
|
|
|
inline |
|
|
|
trx_t*& |
|
|
|
thd_to_trx( |
|
|
|
/*=======*/ |
|
|
|
/* out: reference to transaction pointer */ |
|
|
|
THD* thd, /* in: MySQL thread */ |
|
|
|
handlerton* hton) /* in: InnoDB handlerton */ |
|
|
|
{ |
|
|
|
return(*(trx_t**) thd_ha_data(thd, hton)); |
|
|
|
} |
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
Call this function when mysqld passes control to the client. That is to |
|
|
|
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more |
|
|
|
documentation, see handler.cc. */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_release_temporary_latches( |
|
|
|
/*===============================*/ |
|
|
|
@ -396,7 +495,7 @@ innobase_release_temporary_latches( |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
trx = (trx_t*) thd->ha_data[hton->slot]; |
|
|
|
trx = thd_to_trx(thd, hton); |
|
|
|
|
|
|
|
if (trx) { |
|
|
|
innobase_release_stat_resources(trx); |
|
|
|
@ -855,12 +954,10 @@ check_trx_exists( |
|
|
|
handlerton* hton, /* in: handlerton for innodb */ |
|
|
|
THD* thd) /* in: user thread handle */ |
|
|
|
{ |
|
|
|
trx_t* trx; |
|
|
|
trx_t*& trx = thd_to_trx(thd, hton); |
|
|
|
|
|
|
|
ut_ad(thd == current_thd); |
|
|
|
|
|
|
|
trx = (trx_t*) thd->ha_data[hton->slot]; |
|
|
|
|
|
|
|
if (trx == NULL) { |
|
|
|
DBUG_ASSERT(thd != NULL); |
|
|
|
trx = trx_allocate_for_mysql(); |
|
|
|
@ -872,8 +969,6 @@ check_trx_exists( |
|
|
|
/* Update the info whether we should skip XA steps that eat
|
|
|
|
CPU time */ |
|
|
|
trx->support_xa = (ibool)(thd->variables.innodb_support_xa); |
|
|
|
|
|
|
|
thd->ha_data[hton->slot] = trx; |
|
|
|
} else { |
|
|
|
if (trx->magic_n != TRX_MAGIC_N) { |
|
|
|
mem_analyze_corruption(trx); |
|
|
|
@ -1324,7 +1419,7 @@ ha_innobase::init_table_handle_for_HANDLER(void) |
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Opens an InnoDB database. */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_init(void *p) |
|
|
|
/*===============*/ |
|
|
|
@ -1591,7 +1686,7 @@ error: |
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
Closes an InnoDB database. */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_end(handlerton *hton, ha_panic_function type) |
|
|
|
/*==============*/ |
|
|
|
@ -1629,7 +1724,7 @@ innobase_end(handlerton *hton, ha_panic_function type) |
|
|
|
/********************************************************************
|
|
|
|
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes |
|
|
|
the logs, and the name of this function should be innobase_checkpoint. */ |
|
|
|
|
|
|
|
static |
|
|
|
bool |
|
|
|
innobase_flush_logs(handlerton *hton) |
|
|
|
/*=====================*/ |
|
|
|
@ -1665,7 +1760,7 @@ Creates an InnoDB transaction struct for the thd if it does not yet have one. |
|
|
|
Starts a new InnoDB transaction if a transaction is not yet started. And |
|
|
|
assigns a new snapshot for a consistent read if the transaction does not yet |
|
|
|
have one. */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_start_trx_and_assign_read_view( |
|
|
|
/*====================================*/ |
|
|
|
@ -1879,7 +1974,7 @@ innobase_report_binlog_offset_and_commit( |
|
|
|
#if 0
|
|
|
|
/***********************************************************************
|
|
|
|
This function stores the binlog offset and flushes logs. */ |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
innobase_store_binlog_offset_and_flush_log( |
|
|
|
/*=======================================*/ |
|
|
|
@ -1922,7 +2017,7 @@ innobase_commit_complete( |
|
|
|
{ |
|
|
|
trx_t* trx; |
|
|
|
|
|
|
|
trx = (trx_t*) thd->ha_data[hton->slot]; |
|
|
|
trx = thd_to_trx(thd, hton); |
|
|
|
|
|
|
|
if (trx && trx->active_trans) { |
|
|
|
|
|
|
|
@ -2146,7 +2241,7 @@ innobase_close_connection( |
|
|
|
{ |
|
|
|
trx_t* trx; |
|
|
|
|
|
|
|
trx = (trx_t*)thd->ha_data[hton->slot]; |
|
|
|
trx = thd_to_trx(thd, hton); |
|
|
|
|
|
|
|
ut_a(trx); |
|
|
|
|
|
|
|
@ -2333,7 +2428,7 @@ ha_innobase::open( |
|
|
|
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); |
|
|
|
} |
|
|
|
|
|
|
|
if (ib_table->ibd_file_missing && !thd->tablespace_op) { |
|
|
|
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) { |
|
|
|
ut_print_timestamp(stderr); |
|
|
|
sql_print_error("MySQL is trying to open a table handle but " |
|
|
|
"the .ibd file for\ntable %s does not exist.\n" |
|
|
|
@ -3232,29 +3327,27 @@ ha_innobase::write_row( |
|
|
|
longlong auto_inc; |
|
|
|
longlong dummy; |
|
|
|
ibool auto_inc_used= FALSE; |
|
|
|
THD* thd = current_thd; |
|
|
|
trx_t* trx = thd_to_trx(thd, ht); |
|
|
|
|
|
|
|
DBUG_ENTER("ha_innobase::write_row"); |
|
|
|
|
|
|
|
if (prebuilt->trx != |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]) { |
|
|
|
if (prebuilt->trx != trx) { |
|
|
|
sql_print_error("The transaction object for the table handle is at " |
|
|
|
"%p, but for the current thread it is at %p", |
|
|
|
prebuilt->trx, |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
prebuilt->trx, trx); |
|
|
|
|
|
|
|
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr); |
|
|
|
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200); |
|
|
|
fputs("\n" |
|
|
|
"InnoDB: Dump of 200 bytes around transaction.all: ", |
|
|
|
"InnoDB: Dump of 200 bytes around ha_data: ", |
|
|
|
stderr); |
|
|
|
ut_print_buf(stderr, |
|
|
|
((byte*)(&(current_thd->ha_data[ht->slot]))) - 100, |
|
|
|
200); |
|
|
|
ut_print_buf(stderr, ((const byte*) trx) - 100, 200); |
|
|
|
putc('\n', stderr); |
|
|
|
ut_error; |
|
|
|
} |
|
|
|
|
|
|
|
statistic_increment(current_thd->status_var.ha_write_count, |
|
|
|
statistic_increment(thd->status_var.ha_write_count, |
|
|
|
&LOCK_status); |
|
|
|
|
|
|
|
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) |
|
|
|
@ -3620,11 +3713,11 @@ ha_innobase::update_row( |
|
|
|
{ |
|
|
|
upd_t* uvect; |
|
|
|
int error = 0; |
|
|
|
trx_t* trx = thd_to_trx(current_thd, ht); |
|
|
|
|
|
|
|
DBUG_ENTER("ha_innobase::update_row"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == trx); |
|
|
|
|
|
|
|
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) |
|
|
|
table->timestamp_field->set_time(); |
|
|
|
@ -3633,7 +3726,7 @@ ha_innobase::update_row( |
|
|
|
prebuilt->sql_stat_start = TRUE; |
|
|
|
last_query_id = user_thd->query_id; |
|
|
|
|
|
|
|
innobase_release_stat_resources(prebuilt->trx); |
|
|
|
innobase_release_stat_resources(trx); |
|
|
|
} |
|
|
|
|
|
|
|
if (prebuilt->upd_node) { |
|
|
|
@ -3654,11 +3747,11 @@ ha_innobase::update_row( |
|
|
|
|
|
|
|
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); |
|
|
|
|
|
|
|
innodb_srv_conc_enter_innodb(prebuilt->trx); |
|
|
|
innodb_srv_conc_enter_innodb(trx); |
|
|
|
|
|
|
|
error = row_update_for_mysql((byte*) old_row, prebuilt); |
|
|
|
|
|
|
|
innodb_srv_conc_exit_innodb(prebuilt->trx); |
|
|
|
innodb_srv_conc_exit_innodb(trx); |
|
|
|
|
|
|
|
error = convert_error_code_to_mysql(error, user_thd); |
|
|
|
|
|
|
|
@ -3680,17 +3773,17 @@ ha_innobase::delete_row( |
|
|
|
const mysql_byte* record) /* in: a row in MySQL format */ |
|
|
|
{ |
|
|
|
int error = 0; |
|
|
|
trx_t* trx = thd_to_trx(current_thd, ht); |
|
|
|
|
|
|
|
DBUG_ENTER("ha_innobase::delete_row"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == trx); |
|
|
|
|
|
|
|
if (last_query_id != user_thd->query_id) { |
|
|
|
prebuilt->sql_stat_start = TRUE; |
|
|
|
last_query_id = user_thd->query_id; |
|
|
|
|
|
|
|
innobase_release_stat_resources(prebuilt->trx); |
|
|
|
innobase_release_stat_resources(trx); |
|
|
|
} |
|
|
|
|
|
|
|
if (!prebuilt->upd_node) { |
|
|
|
@ -3701,11 +3794,11 @@ ha_innobase::delete_row( |
|
|
|
|
|
|
|
prebuilt->upd_node->is_delete = TRUE; |
|
|
|
|
|
|
|
innodb_srv_conc_enter_innodb(prebuilt->trx); |
|
|
|
innodb_srv_conc_enter_innodb(trx); |
|
|
|
|
|
|
|
error = row_update_for_mysql((byte*) record, prebuilt); |
|
|
|
|
|
|
|
innodb_srv_conc_exit_innodb(prebuilt->trx); |
|
|
|
innodb_srv_conc_exit_innodb(trx); |
|
|
|
|
|
|
|
error = convert_error_code_to_mysql(error, user_thd); |
|
|
|
|
|
|
|
@ -3733,7 +3826,7 @@ ha_innobase::unlock_row(void) |
|
|
|
sql_print_error("last_query_id is %lu != user_thd_query_id is " |
|
|
|
"%lu", (ulong) last_query_id, |
|
|
|
(ulong) user_thd->query_id); |
|
|
|
mem_analyze_corruption((byte *) prebuilt->trx); |
|
|
|
mem_analyze_corruption(prebuilt->trx); |
|
|
|
ut_error; |
|
|
|
} |
|
|
|
|
|
|
|
@ -3775,8 +3868,7 @@ void |
|
|
|
ha_innobase::try_semi_consistent_read(bool yes) |
|
|
|
/*===========================================*/ |
|
|
|
{ |
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
/* Row read type is set to semi consistent read if this was
|
|
|
|
requested by the MySQL and either innodb_locks_unsafe_for_binlog |
|
|
|
@ -3941,8 +4033,7 @@ ha_innobase::index_read( |
|
|
|
|
|
|
|
DBUG_ENTER("index_read"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
statistic_increment(current_thd->status_var.ha_read_key_count, |
|
|
|
&LOCK_status); |
|
|
|
@ -4050,13 +4141,12 @@ ha_innobase::change_active_index( |
|
|
|
InnoDB */ |
|
|
|
{ |
|
|
|
KEY* key=0; |
|
|
|
statistic_increment(current_thd->status_var.ha_read_key_count, |
|
|
|
&LOCK_status); |
|
|
|
THD* thd = current_thd; |
|
|
|
statistic_increment(thd->status_var.ha_read_key_count, &LOCK_status); |
|
|
|
DBUG_ENTER("change_active_index"); |
|
|
|
|
|
|
|
ut_ad(user_thd == current_thd); |
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_ad(user_thd == thd); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(thd, ht)); |
|
|
|
|
|
|
|
active_index = keynr; |
|
|
|
|
|
|
|
@ -4144,8 +4234,7 @@ ha_innobase::general_fetch( |
|
|
|
|
|
|
|
DBUG_ENTER("general_fetch"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
innodb_srv_conc_enter_innodb(prebuilt->trx); |
|
|
|
|
|
|
|
@ -4377,8 +4466,7 @@ ha_innobase::rnd_pos( |
|
|
|
statistic_increment(current_thd->status_var.ha_read_rnd_count, |
|
|
|
&LOCK_status); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
if (prebuilt->clust_index_was_generated) { |
|
|
|
/* No primary key was defined for the table and we
|
|
|
|
@ -4426,8 +4514,7 @@ ha_innobase::position( |
|
|
|
{ |
|
|
|
uint len; |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
if (prebuilt->clust_index_was_generated) { |
|
|
|
/* No primary key was defined for the table and we
|
|
|
|
@ -4931,9 +5018,9 @@ ha_innobase::discard_or_import_tablespace( |
|
|
|
|
|
|
|
DBUG_ENTER("ha_innobase::discard_or_import_tablespace"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); |
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx); |
|
|
|
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
dict_table = prebuilt->table; |
|
|
|
trx = prebuilt->trx; |
|
|
|
@ -5074,7 +5161,7 @@ ha_innobase::delete_table( |
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Removes all tables in the named database inside InnoDB. */ |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
innobase_drop_database( |
|
|
|
/*===================*/ |
|
|
|
@ -5259,8 +5346,7 @@ ha_innobase::records_in_range( |
|
|
|
|
|
|
|
DBUG_ENTER("records_in_range"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
prebuilt->trx->op_info = (char*)"estimating records in index range"; |
|
|
|
|
|
|
|
@ -5690,8 +5776,7 @@ ha_innobase::check( |
|
|
|
ulint ret; |
|
|
|
|
|
|
|
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); |
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
if (prebuilt->mysql_template == NULL) { |
|
|
|
/* Build the template; we will use a dummy template
|
|
|
|
@ -5988,8 +6073,7 @@ ha_innobase::can_switch_engines(void) |
|
|
|
|
|
|
|
DBUG_ENTER("ha_innobase::can_switch_engines"); |
|
|
|
|
|
|
|
ut_a(prebuilt->trx == |
|
|
|
(trx_t*) current_thd->ha_data[ht->slot]); |
|
|
|
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht)); |
|
|
|
|
|
|
|
prebuilt->trx->op_info = |
|
|
|
"determining if there are foreign key constraints"; |
|
|
|
@ -6097,7 +6181,7 @@ on that table. |
|
|
|
MySQL-5.0 also calls this before each statement in an execution of a stored |
|
|
|
procedure. To make the execution more deterministic for binlogging, MySQL-5.0 |
|
|
|
locks all tables involved in a stored procedure with full explicit table |
|
|
|
locks (thd->in_lock_tables is true in ::store_lock()) before executing the |
|
|
|
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the |
|
|
|
procedure. */ |
|
|
|
|
|
|
|
int |
|
|
|
@ -6270,16 +6354,16 @@ ha_innobase::external_lock( |
|
|
|
VERY easily deadlocks. |
|
|
|
|
|
|
|
We do not set InnoDB table locks if user has not explicitly |
|
|
|
requested a table lock. Note that thd->in_lock_tables |
|
|
|
can be TRUE on some cases e.g. at the start of a stored |
|
|
|
requested a table lock. Note that thd_in_lock_tables(thd) |
|
|
|
can hold in some cases, e.g., at the start of a stored |
|
|
|
procedure call (SQLCOM_CALL). */ |
|
|
|
|
|
|
|
if (prebuilt->select_lock_type != LOCK_NONE) { |
|
|
|
|
|
|
|
if (thd->in_lock_tables && |
|
|
|
thd->lex->sql_command == SQLCOM_LOCK_TABLES && |
|
|
|
thd->variables.innodb_table_locks && |
|
|
|
(thd->options & OPTION_NOT_AUTOCOMMIT)) { |
|
|
|
if (thd->lex->sql_command == SQLCOM_LOCK_TABLES |
|
|
|
&& thd->variables.innodb_table_locks |
|
|
|
&& (thd->options & OPTION_NOT_AUTOCOMMIT) |
|
|
|
&& thd_in_lock_tables(thd)) { |
|
|
|
|
|
|
|
ulint error = row_lock_table_for_mysql( |
|
|
|
prebuilt, NULL, 0); |
|
|
|
@ -6357,7 +6441,8 @@ ha_innobase::transactional_table_lock( |
|
|
|
|
|
|
|
update_thd(thd); |
|
|
|
|
|
|
|
if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) { |
|
|
|
if (prebuilt->table->ibd_file_missing |
|
|
|
&& !thd_tablespace_op(current_thd)) { |
|
|
|
ut_print_timestamp(stderr); |
|
|
|
fprintf(stderr, " InnoDB error:\n" |
|
|
|
"MySQL is trying to use a table handle but the .ibd file for\n" |
|
|
|
@ -6402,7 +6487,7 @@ ha_innobase::transactional_table_lock( |
|
|
|
trx->active_trans = 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (thd->in_lock_tables && thd->variables.innodb_table_locks) { |
|
|
|
if (thd->variables.innodb_table_locks && thd_in_lock_tables(thd)) { |
|
|
|
ulint error = DB_SUCCESS; |
|
|
|
|
|
|
|
error = row_lock_table_for_mysql(prebuilt, NULL, 0); |
|
|
|
@ -6442,7 +6527,7 @@ innodb_export_status() |
|
|
|
/****************************************************************************
|
|
|
|
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB |
|
|
|
Monitor to the client. */ |
|
|
|
|
|
|
|
static |
|
|
|
bool |
|
|
|
innodb_show_status( |
|
|
|
/*===============*/ |
|
|
|
@ -6632,6 +6717,7 @@ innodb_mutex_show_status( |
|
|
|
DBUG_RETURN(FALSE); |
|
|
|
} |
|
|
|
|
|
|
|
static |
|
|
|
bool innobase_show_status(handlerton *hton, THD* thd, |
|
|
|
stat_print_fn* stat_print, |
|
|
|
enum ha_stat_type stat_type) |
|
|
|
@ -6755,14 +6841,16 @@ ha_innobase::store_lock( |
|
|
|
thd->variables.tx_isolation); |
|
|
|
} |
|
|
|
|
|
|
|
const bool in_lock_tables = thd_in_lock_tables(thd); |
|
|
|
|
|
|
|
if (thd->lex->sql_command == SQLCOM_DROP_TABLE) { |
|
|
|
|
|
|
|
/* MySQL calls this function in DROP TABLE though this table
|
|
|
|
handle may belong to another thd that is running a query. Let |
|
|
|
us in that case skip any changes to the prebuilt struct. */ |
|
|
|
|
|
|
|
} else if ((lock_type == TL_READ && thd->in_lock_tables) || |
|
|
|
(lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) || |
|
|
|
} else if ((lock_type == TL_READ && in_lock_tables) || |
|
|
|
(lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) || |
|
|
|
lock_type == TL_READ_WITH_SHARED_LOCKS || |
|
|
|
lock_type == TL_READ_NO_INSERT || |
|
|
|
(thd->lex->sql_command != SQLCOM_SELECT |
|
|
|
@ -6833,7 +6921,7 @@ ha_innobase::store_lock( |
|
|
|
/* Starting from 5.0.7, we weaken also the table locks
|
|
|
|
set at the start of a MySQL stored procedure call, just like |
|
|
|
we weaken the locks set at the start of an SQL statement. |
|
|
|
MySQL does set thd->in_lock_tables TRUE there, but in reality |
|
|
|
MySQL does set in_lock_tables TRUE there, but in reality |
|
|
|
we do not need table locks to make the execution of a |
|
|
|
single transaction stored procedure call deterministic |
|
|
|
(if it does not use a consistent read). */ |
|
|
|
@ -6861,14 +6949,14 @@ ha_innobase::store_lock( |
|
|
|
|
|
|
|
We especially allow multiple writers if MySQL is at the |
|
|
|
start of a stored procedure call (SQLCOM_CALL) or a |
|
|
|
stored function call (MySQL does have thd->in_lock_tables |
|
|
|
stored function call (MySQL does have in_lock_tables |
|
|
|
TRUE there). */ |
|
|
|
|
|
|
|
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT |
|
|
|
&& lock_type <= TL_WRITE) |
|
|
|
&& !(thd->in_lock_tables |
|
|
|
&& !(in_lock_tables |
|
|
|
&& thd->lex->sql_command == SQLCOM_LOCK_TABLES) |
|
|
|
&& !thd->tablespace_op |
|
|
|
&& !thd_tablespace_op(thd) |
|
|
|
&& thd->lex->sql_command != SQLCOM_TRUNCATE |
|
|
|
&& thd->lex->sql_command != SQLCOM_OPTIMIZE |
|
|
|
|
|
|
|
@ -6895,7 +6983,7 @@ ha_innobase::store_lock( |
|
|
|
|
|
|
|
We especially allow concurrent inserts if MySQL is at the |
|
|
|
start of a stored procedure call (SQLCOM_CALL) |
|
|
|
(MySQL does have thd->in_lock_tables TRUE there). */ |
|
|
|
(MySQL does have in_lock_tables TRUE there). */ |
|
|
|
|
|
|
|
if (lock_type == TL_READ_NO_INSERT |
|
|
|
&& thd->lex->sql_command != SQLCOM_LOCK_TABLES) { |
|
|
|
@ -7337,7 +7425,7 @@ innobase_query_is_update(void) |
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
This function is used to prepare X/Open XA distributed transaction */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_xa_prepare( |
|
|
|
/*================*/ |
|
|
|
@ -7433,7 +7521,7 @@ innobase_xa_prepare( |
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
This function is used to recover X/Open XA distributed transactions */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_xa_recover( |
|
|
|
/*================*/ |
|
|
|
@ -7454,7 +7542,7 @@ innobase_xa_recover( |
|
|
|
/***********************************************************************
|
|
|
|
This function is used to commit one X/Open XA distributed transaction |
|
|
|
which is in the prepared state */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_commit_by_xid( |
|
|
|
/*===================*/ |
|
|
|
@ -7478,7 +7566,7 @@ innobase_commit_by_xid( |
|
|
|
/***********************************************************************
|
|
|
|
This function is used to rollback one X/Open XA distributed transaction |
|
|
|
which is in the prepared state */ |
|
|
|
|
|
|
|
static |
|
|
|
int |
|
|
|
innobase_rollback_by_xid( |
|
|
|
/*=====================*/ |
|
|
|
@ -7502,9 +7590,10 @@ Create a consistent view for a cursor based on current transaction |
|
|
|
which is created if the corresponding MySQL thread still lacks one. |
|
|
|
This consistent view is then used inside of MySQL when accessing records |
|
|
|
using a cursor. */ |
|
|
|
|
|
|
|
static |
|
|
|
void* |
|
|
|
innobase_create_cursor_view( |
|
|
|
/*========================*/ |
|
|
|
/* out: pointer to cursor view or NULL */ |
|
|
|
handlerton *hton, /* in: innobase hton */ |
|
|
|
THD* thd) /* in: user thread handle */ |
|
|
|
@ -7517,9 +7606,10 @@ innobase_create_cursor_view( |
|
|
|
Close the given consistent cursor view of a transaction and restore |
|
|
|
global read view to a transaction read view. Transaction is created if the |
|
|
|
corresponding MySQL thread still lacks one. */ |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
innobase_close_cursor_view( |
|
|
|
/*=======================*/ |
|
|
|
handlerton *hton, |
|
|
|
THD* thd, /* in: user thread handle */ |
|
|
|
void* curview)/* in: Consistent read view to be closed */ |
|
|
|
@ -7533,7 +7623,7 @@ Set the given consistent cursor view to a transaction which is created |
|
|
|
if the corresponding MySQL thread still lacks one. If the given |
|
|
|
consistent cursor view is NULL global read view of a transaction is |
|
|
|
restored to a transaction read view. */ |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
innobase_set_cursor_view( |
|
|
|
/*=====================*/ |
|
|
|
|