80
79
#include "drizzled/field/blob.h"
81
80
#include "drizzled/field/varstring.h"
82
81
#include "drizzled/field/timestamp.h"
83
#include "drizzled/plugin/storage_engine.h"
84
#include "drizzled/plugin/info_schema_table.h"
82
#include "drizzled/plugin/xa_storage_engine.h"
85
83
#include "drizzled/memory/multi_malloc.h"
86
84
#include "drizzled/pthread_globals.h"
87
85
#include "drizzled/named_savepoint.h"
161
163
# define EQ_CURRENT_SESSION(session) ((session) == current_session)
162
164
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
164
static plugin::StorageEngine* innodb_engine_ptr= NULL;
166
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
167
static plugin::TableFunction* status_table_function_ptr= NULL;
168
static plugin::TableFunction* cmp_tool= NULL;
169
static plugin::TableFunction* cmp_reset_tool= NULL;
170
static plugin::TableFunction* cmp_mem_tool= NULL;
171
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
172
static plugin::TableFunction* innodb_trx_tool= NULL;
173
static plugin::TableFunction* innodb_locks_tool= NULL;
174
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
166
176
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
167
177
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
248
258
static INNOBASE_SHARE *get_share(const char *table_name);
249
259
static void free_share(INNOBASE_SHARE *share);
251
class InnobaseEngine : public plugin::StorageEngine
261
class InnobaseEngine : public plugin::XaStorageEngine
254
264
InnobaseEngine(string name_arg) :
255
plugin::StorageEngine(name_arg,
265
plugin::XaStorageEngine(name_arg,
256
266
HTON_NULL_IN_KEY |
257
267
HTON_CAN_INDEX_BLOBS |
258
268
HTON_PRIMARY_KEY_REQUIRED_FOR_POSITION |
273
287
Session* session); /* in: handle to the MySQL thread of the user
274
288
whose resources should be free'd */
276
virtual int savepoint_set_hook(Session* session,
290
virtual int doSetSavepoint(Session* session,
277
291
drizzled::NamedSavepoint &savepoint);
278
virtual int savepoint_rollback_hook(Session* session,
279
drizzled::NamedSavepoint &savepoint);
280
virtual int savepoint_release_hook(Session* session,
281
drizzled::NamedSavepoint &savepoint);
282
virtual int commit(Session* session, bool all);
283
virtual int rollback(Session* session, bool all);
292
virtual int doRollbackToSavepoint(Session* session,
293
drizzled::NamedSavepoint &savepoint);
294
virtual int doReleaseSavepoint(Session* session,
295
drizzled::NamedSavepoint &savepoint);
296
virtual int doXaCommit(Session* session, bool all)
298
return doCommit(session, all); /* XA commit just does a SQL COMMIT */
300
virtual int doXaRollback(Session *session, bool all)
302
return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
304
virtual int doCommit(Session* session, bool all);
305
virtual int doRollback(Session* session, bool all);
285
307
/***********************************************************************
286
308
This function is used to prepare X/Open XA distributed transaction */
290
312
/*================*/
291
313
/* out: 0 or error number */
292
314
Session* session, /* in: handle to the MySQL thread of the user
297
319
This function is used to recover X/Open XA distributed transactions */
301
323
/*================*/
302
324
/* out: number of prepared transactions
303
325
stored in xid_list */
304
326
::drizzled::XID* xid_list, /* in/out: prepared transactions */
305
uint len); /* in: number of slots in xid_list */
327
size_t len); /* in: number of slots in xid_list */
306
328
/***********************************************************************
307
329
This function is used to commit one X/Open XA distributed transaction
308
330
which is in the prepared state */
312
334
/*===================*/
313
335
/* out: 0 or error number */
314
336
::drizzled::XID* xid); /* in: X/Open XA transaction identification */
331
353
/*********************************************************************
332
354
Removes all tables in the named database inside InnoDB. */
336
357
/*===================*/
337
358
/* out: error number */
338
char* path); /* in: database path; inside InnoDB the name
359
const std::string &schema_name); /* in: database path; inside InnoDB the name
339
360
of the last directory in the path is used as
340
361
the database name: for example, in 'mysql/data/test'
341
362
the database name is 'test' */
343
/*********************************************************************
344
Creates an InnoDB transaction struct for the session if it does not yet have one.
345
Starts a new InnoDB transaction if a transaction is not yet started. And
346
assigns a new snapshot for a consistent read if the transaction does not yet
350
start_consistent_snapshot(
351
/*====================================*/
353
Session* session); /* in: MySQL thread handle of the user for whom
354
the transaction should be committed */
355
364
/********************************************************************
356
365
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
357
366
the logs, and the name of this function should be innobase_checkpoint. */
517
526
/*================*/
518
527
trx_t* trx); /*!< in: transaction handle */
520
static SHOW_VAR innodb_status_variables[]= {
529
static drizzle_show_var innodb_status_variables[]= {
521
530
{"buffer_pool_pages_data",
522
531
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
523
532
{"buffer_pool_pages_dirty",
611
620
{NULL, NULL, SHOW_LONG}
623
InnodbStatusTool::Generator::Generator(drizzled::Field **fields) :
624
plugin::TableFunction::Generator(fields)
626
srv_export_innodb_status();
627
status_var_ptr= innodb_status_variables;
630
bool InnodbStatusTool::Generator::populate()
632
if (status_var_ptr->name)
634
std::ostringstream oss;
636
const char *value= status_var_ptr->value;
639
push(status_var_ptr->name);
641
switch (status_var_ptr->type)
644
oss << *(int64_t*) value;
645
return_value= oss.str();
648
oss << *(int64_t*) value;
649
return_value= oss.str();
652
return_value= *(bool*) value ? "ON" : "OFF";
659
if (return_value.length())
614
671
/* General functions */
616
673
/******************************************************************//**
1450
1507
update_session(session);
1453
/*********************************************************************//**
1454
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
1455
roll back the statement if the statement results in an error. This MUST be
1456
called for every SQL statement that may be rolled back by MySQL. Calling this
1457
several times to register the same statement is allowed, too. */
1460
innobase_register_stmt(
1461
/*===================*/
1462
plugin::StorageEngine* engine, /*!< in: Innobase hton */
1463
Session* session) /*!< in: MySQL thd (connection) object */
1465
assert(engine == innodb_engine_ptr);
1466
/* Register the statement */
1467
TransactionServices &transaction_services= TransactionServices::singleton();
1468
transaction_services.trans_register_ha(session, FALSE, engine);
1471
/*********************************************************************//**
1472
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1473
to call the InnoDB prepare and commit, or rollback for the transaction. This
1474
MUST be called for every transaction for which the user may call commit or
1475
rollback. Calling this several times to register the same transaction is
1477
This function also registers the current SQL statement. */
1480
innobase_register_trx_and_stmt(
1481
/*===========================*/
1482
plugin::StorageEngine *engine, /*!< in: Innobase StorageEngine */
1483
Session* session) /*!< in: MySQL thd (connection) object */
1485
/* NOTE that actually innobase_register_stmt() registers also
1486
the transaction in the AUTOCOMMIT=1 mode. */
1488
innobase_register_stmt(engine, session);
1490
if (session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1492
/* No autocommit mode, register for a transaction */
1493
TransactionServices &transaction_services= TransactionServices::singleton();
1494
transaction_services.trans_register_ha(session, TRUE, engine);
1498
1510
/*****************************************************************//**
1499
1511
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1500
1512
and quote it if needed.
1662
1674
prebuilt->read_just_key = 0;
1665
/*****************************************************************//**
1666
Call this when you have opened a new table handle in HANDLER, before you
1667
call index_read_idx() etc. Actually, we can let the cursor stay open even
1668
over a transaction commit! Then you should call this before every operation,
1669
fetch next etc. This function inits the necessary things even after a
1670
transaction commit. */
1673
ha_innobase::init_table_handle_for_HANDLER(void)
1674
/*============================================*/
1676
/* If current session does not yet have a trx struct, create one.
1677
If the current handle does not yet have a prebuilt struct, create
1678
one. Update the trx pointers in the prebuilt struct. Normally
1679
this operation is done in external_lock. */
1681
update_session(ha_session());
1683
/* Initialize the prebuilt struct much like it would be inited in
1686
innobase_release_stat_resources(prebuilt->trx);
1688
/* If the transaction is not started yet, start it */
1690
trx_start_if_not_started(prebuilt->trx);
1692
/* Assign a read view if the transaction does not have it yet */
1694
trx_assign_read_view(prebuilt->trx);
1696
/* Set the MySQL flag to mark that there is an active transaction */
1698
if (prebuilt->trx->active_trans == 0) {
1700
innobase_register_trx_and_stmt(engine, user_session);
1702
prebuilt->trx->active_trans = 1;
1705
/* We did the necessary inits in this function, no need to repeat them
1706
in row_search_for_mysql */
1708
prebuilt->sql_stat_start = FALSE;
1710
/* We let HANDLER always to do the reads as consistent reads, even
1711
if the trx isolation level would have been specified as SERIALIZABLE */
1713
prebuilt->select_lock_type = LOCK_NONE;
1714
prebuilt->stored_select_lock_type = LOCK_NONE;
1716
/* Always fetch all columns in the index record */
1718
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1720
/* We want always to fetch all columns in the whole row? Or do
1723
prebuilt->used_in_HANDLER = TRUE;
1724
reset_template(prebuilt);
1727
1677
/*********************************************************************//**
1728
1678
Opens an InnoDB database.
1729
1679
@return 0 on success, error code on failure */
2010
1960
pthread_cond_init(&commit_cond, NULL);
2011
1961
innodb_inited= 1;
2013
if (innodb_locks_init() ||
2014
innodb_trx_init() ||
2015
innodb_lock_waits_init() ||
2017
i_s_cmp_reset_init() ||
2018
i_s_cmpmem_init() ||
2019
i_s_cmpmem_reset_init())
1963
status_table_function_ptr= new InnodbStatusTool;
2022
1965
registry.add(innodb_engine_ptr);
2024
registry.add(innodb_trx_schema_table);
2025
registry.add(innodb_locks_schema_table);
2026
registry.add(innodb_lock_waits_schema_table);
2027
registry.add(innodb_cmp_schema_table);
2028
registry.add(innodb_cmp_reset_schema_table);
2029
registry.add(innodb_cmpmem_schema_table);
2030
registry.add(innodb_cmpmem_reset_schema_table);
1967
registry.add(status_table_function_ptr);
1969
cmp_tool= new(std::nothrow)CmpTool(false);
1970
registry.add(cmp_tool);
1972
cmp_reset_tool= new(std::nothrow)CmpTool(true);
1973
registry.add(cmp_reset_tool);
1975
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
1976
registry.add(cmp_mem_tool);
1978
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
1979
registry.add(cmp_mem_reset_tool);
1981
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
1982
registry.add(innodb_trx_tool);
1984
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
1985
registry.add(innodb_locks_tool);
1987
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
1988
registry.add(innodb_lock_waits_tool);
2032
1990
/* Get the current high water mark format. */
2033
1991
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2045
2003
innobase_deinit(plugin::Registry ®istry)
2048
i_s_common_deinit(registry);
2007
registry.remove(status_table_function_ptr);
2008
delete status_table_function_ptr;
2010
registry.remove(cmp_tool);
2013
registry.remove(cmp_reset_tool);
2014
delete cmp_reset_tool;
2016
registry.remove(cmp_mem_tool);
2017
delete cmp_mem_tool;
2019
registry.remove(cmp_mem_reset_tool);
2020
delete cmp_mem_reset_tool;
2022
registry.remove(innodb_trx_tool);
2023
delete innodb_trx_tool;
2025
registry.remove(innodb_locks_tool);
2026
delete innodb_locks_tool;
2028
registry.remove(innodb_lock_waits_tool);
2029
delete innodb_lock_waits_tool;
2049
2031
registry.remove(innodb_engine_ptr);
2050
2032
delete innodb_engine_ptr;
2114
InnobaseEngine::start_consistent_snapshot(
2096
InnobaseEngine::doStartTransaction(
2115
2097
/*====================================*/
2116
Session* session) /*!< in: MySQL thread handle of the user for whom
2117
the transaction should be committed */
2098
Session* session, /*!< in: MySQL thread handle of the user for whom
2099
the transaction should be committed */
2100
start_transaction_option_t options)
2121
2102
assert(this == innodb_engine_ptr);
2123
2104
/* Create a new trx struct for session, if it does not yet have one */
2125
trx = check_trx_exists(session);
2105
trx_t *trx = check_trx_exists(session);
2127
2107
/* This is just to play safe: release a possible FIFO ticket and
2128
2108
search latch. Since we will reserve the kernel mutex, we have to
2129
2109
release the search system latch first to obey the latching order. */
2131
2110
innobase_release_stat_resources(trx);
2133
2112
/* If the transaction is not started yet, start it */
2135
2113
trx_start_if_not_started(trx);
2137
2115
/* Assign a read view if the transaction does not have it yet */
2139
trx_assign_read_view(trx);
2141
/* Set the MySQL flag to mark that there is an active transaction */
2143
if (trx->active_trans == 0) {
2144
innobase_register_trx_and_stmt(this, current_session);
2145
trx->active_trans = 1;
2116
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2117
trx_assign_read_view(trx);
2151
2122
/*****************************************************************//**
2173
2144
trx_search_latch_release_if_reserved(trx);
2176
/* The flag trx->active_trans is set to 1 in
2178
1. ::external_lock(),
2180
3. innobase_query_caching_of_table_permitted(),
2181
4. InnobaseEngine::savepoint_set(),
2182
5. ::init_table_handle_for_HANDLER(),
2183
6. InnobaseEngine::start_consistent_snapshot(),
2185
and it is only set to 0 in a commit or a rollback. If it is 0 we know
2186
there cannot be resources to be freed and we could return immediately.
2187
For the time being, we play safe and do the cleanup though there should
2188
be nothing to clean up. */
2190
if (trx->active_trans == 0
2191
&& trx->conc_state != TRX_NOT_STARTED) {
2193
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2194
" trx->conc_state != TRX_NOT_STARTED");
2197
2148
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2433
2380
innobase_release_stat_resources(trx);
2435
2382
/* cannot happen outside of transaction */
2436
assert(trx->active_trans);
2383
assert(trx->conc_state != TRX_NOT_STARTED);
2438
/* TODO: use provided savepoint data area to store savepoint data */
2439
2385
error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
2441
2387
return(convert_error_code_to_mysql(error, 0, NULL));
2460
if (trx->active_trans == 0
2461
&& trx->conc_state != TRX_NOT_STARTED) {
2463
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2464
" trx->conc_state != TRX_NOT_STARTED");
2468
if (trx->conc_state != TRX_NOT_STARTED &&
2469
global_system_variables.log_warnings) {
2470
errmsg_printf(ERRMSG_LVL_WARN,
2471
"MySQL is closing a connection that has an active "
2472
"InnoDB transaction. %lu row modifications will "
2474
(ulong) trx->undo_no.low);
2406
assert(session->killed != Session::NOT_KILLED ||
2407
trx->conc_state == TRX_NOT_STARTED);
2409
/* Warn if rolling back some things... */
2410
if (session->killed != Session::NOT_KILLED &&
2411
trx->conc_state != TRX_NOT_STARTED &&
2412
trx->undo_no.low > 0 &&
2413
global_system_variables.log_warnings)
2415
errmsg_printf(ERRMSG_LVL_WARN,
2416
"Drizzle is closing a connection during a KILL operation\n"
2417
"that has an active InnoDB transaction. %lu row modifications will "
2419
(ulong) trx->undo_no.low);
2477
2422
innobase_rollback_trx(trx);
3879
3824
no need to re-acquire locks on it. */
3881
3826
/* Altering to InnoDB format */
3882
engine->commit(user_session, 1);
3883
/* Note that this transaction is still active. */
3884
prebuilt->trx->active_trans = 1;
3827
getTransactionalEngine()->commit(user_session, 1);
3885
3828
/* We will need an IX lock on the destination table. */
3886
3829
prebuilt->sql_stat_start = TRUE;
3896
3839
/* Commit the transaction. This will release the table
3897
3840
locks, so they have to be acquired again. */
3898
engine->commit(user_session, 1);
3899
/* Note that this transaction is still active. */
3900
prebuilt->trx->active_trans = 1;
3841
getTransactionalEngine()->commit(user_session, 1);
3901
3842
/* Re-acquire the table lock on the source table. */
3902
3843
row_lock_table_for_mysql(prebuilt, src_table, mode);
3903
3844
/* We will need an IX lock on the destination table. */
4501
4442
A) if the user has not explicitly set any MySQL table level locks:
4503
1) MySQL calls ::external_lock to set an 'intention' table level lock on
4504
the table of the handle instance. There we set
4505
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
4506
true if we are taking this table handle instance to use in a new SQL
4507
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
4509
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4444
1) Drizzle calls StorageEngine::doStartStatement(), indicating to
4445
InnoDB that a new SQL statement has begun.
4447
2a) For each InnoDB-managed table in the SELECT, Drizzle calls ::external_lock
4448
to set an 'intention' table level lock on the table of the Cursor instance.
4449
There we set prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should
4450
be set true if we are taking this table handle instance to use in a new SQL
4451
statement issued by the user.
4453
2b) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4510
4454
instructions to prebuilt->template of the table handle instance in
4511
4455
::index_read. The template is used to save CPU time in large joins.
4518
4462
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
4519
4463
same table handle instance, if it is a join.
4521
5) When the SELECT ends, MySQL removes its intention table level locks
4522
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
4523
(a) we execute a COMMIT there if the autocommit is on,
4465
5) When the SELECT ends, the Drizzle kernel calls doEndStatement()
4467
(a) we execute a COMMIT there if the autocommit is on. The Drizzle interpreter
4468
does NOT execute autocommit for pure read transactions, though it should.
4469
That is why we must execute the COMMIT in ::doEndStatement().
4524
4470
(b) we also release possible 'SQL statement level resources' InnoDB may
4525
have for this SQL statement. The MySQL interpreter does NOT execute
4526
autocommit for pure read transactions, though it should. That is why the
4527
table Cursor in that case has to execute the COMMIT in ::external_lock.
4471
have for this SQL statement.
4475
Remove need for InnoDB to call autocommit for read-only trx
4477
@todo Check the below is still valid (I don't think it is...)
4529
4479
B) If the user has explicitly set MySQL table level locks, then MySQL
4530
4480
does NOT call ::external_lock at the start of the statement. To determine
5806
if (*trx->mysql_query_str) {
5756
if (trx->mysql_query_str) {
5807
5757
error = row_table_add_foreign_constraints(trx,
5808
*trx->mysql_query_str, norm_name,
5758
trx->mysql_query_str, norm_name,
5809
5759
lex_identified_temp_table);
5811
5761
error = convert_error_code_to_mysql(error, iflags, NULL);
6018
5968
/*****************************************************************//**
6019
5969
Removes all tables in the named database inside InnoDB. */
6021
InnobaseEngine::drop_database(
5971
InnobaseEngine::doDropSchema(
6022
5972
/*===================*/
6023
char* path) /*!< in: database path; inside InnoDB the name
5973
const std::string &schema_name)
5974
/*!< in: database path; inside InnoDB the name
6024
5975
of the last directory in the path is used as
6025
5976
the database name: for example, in 'mysql/data/test'
6026
5977
the database name is 'test' */
5981
string schema_path(schema_name);
6033
5982
Session* session = current_session;
6035
5984
/* Get the transaction associated with the current session, or create one
6048
5997
trx_search_latch_release_if_reserved(parent_trx);
6051
ptr = strchr(path, '\0') - 2;
6053
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
6059
namebuf = (char*) malloc((uint) len + 2);
6061
memcpy(namebuf, ptr, len);
6063
namebuf[len + 1] = '\0';
6065
innobase_casedn_str(namebuf);
6067
#if defined __WIN__ && !defined MYSQL_SERVER
6068
/* In the Windows plugin, thd = current_thd is always NULL */
6069
trx = trx_allocate_for_mysql();
6070
trx->mysql_thd = NULL;
6071
trx->mysql_query_str = NULL;
6000
schema_path.append("/");
6073
6001
trx = innobase_trx_allocate(session);
6075
error = row_drop_database_for_mysql(namebuf, trx);
6002
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6078
6004
/* Flush the log to reduce probability that the .frm files and
6079
6005
the InnoDB data dictionary get out-of-sync if the user runs
7118
7046
/******************************************************************//**
7119
MySQL calls this function at the start of each SQL statement inside LOCK
7120
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
7121
mark SQL statement borders. Note also a special case: if a temporary table
7122
is created inside LOCK TABLES, MySQL has not called external_lock() at all
7124
MySQL-5.0 also calls this before each statement in an execution of a stored
7125
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
7126
locks all tables involved in a stored procedure with full explicit table
7127
locks (session_in_lock_tables(session) holds in store_lock()) before executing
7129
@return 0 or error code */
7132
ha_innobase::start_stmt(
7133
/*====================*/
7134
Session* session, /*!< in: handle to the user thread */
7135
thr_lock_type lock_type)
7139
update_session(session);
7141
trx = prebuilt->trx;
7143
/* Here we release the search latch and the InnoDB thread FIFO ticket
7144
if they were reserved. They should have been released already at the
7145
end of the previous statement, but because inside LOCK TABLES the
7146
lock count method does not work to mark the end of a SELECT statement,
7147
that may not be the case. We MUST release the search latch before an
7148
INSERT, for example. */
7150
innobase_release_stat_resources(trx);
7152
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
7153
trx->n_autoinc_rows = 0;
7155
prebuilt->sql_stat_start = TRUE;
7156
prebuilt->hint_need_to_fetch_extra_cols = 0;
7157
reset_template(prebuilt);
7159
if (!prebuilt->mysql_has_locked) {
7160
/* This handle is for a temporary table created inside
7161
this same LOCK TABLES; since MySQL does NOT call external_lock
7162
in this case, we must use x-row locks inside InnoDB to be
7163
prepared for an update of a row */
7165
prebuilt->select_lock_type = LOCK_X;
7167
if (trx->isolation_level != TRX_ISO_SERIALIZABLE
7168
&& session_sql_command(session) == SQLCOM_SELECT
7169
&& lock_type == TL_READ) {
7171
/* For other than temporary tables, we obtain
7172
no lock for consistent read (plain SELECT). */
7174
prebuilt->select_lock_type = LOCK_NONE;
7176
/* Not a consistent read: restore the
7177
select_lock_type value. The value of
7178
stored_select_lock_type was decided in:
7180
2) ::external_lock(),
7181
3) ::init_table_handle_for_HANDLER(), and
7184
prebuilt->select_lock_type =
7185
prebuilt->stored_select_lock_type;
7189
trx->detailed_error[0] = '\0';
7191
/* Set the MySQL flag to mark that there is an active transaction */
7192
if (trx->active_trans == 0) {
7194
innobase_register_trx_and_stmt(engine, session);
7195
trx->active_trans = 1;
7197
innobase_register_stmt(engine, session);
7203
/******************************************************************//**
7204
7047
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7205
7048
@return InnoDB isolation level */
7221
7064
/******************************************************************//**
7222
7065
As MySQL will execute an external lock for every new table it uses when it
7223
starts to process an SQL statement (an exception is when MySQL calls
7224
start_stmt for the handle) we can use this function to store the pointer to
7225
the Session in the handle. We will also use this function to communicate
7226
to InnoDB that a new SQL statement has started and that we must store a
7227
savepoint to our transaction handle, so that we are able to roll back
7228
the SQL statement in case of an error.
7066
starts to process an SQL statement. We can use this function to store the pointer to
7067
the Session in the handle.
7257
7093
if (lock_type != F_UNLCK) {
7258
7094
/* MySQL is setting a new table lock */
7260
trx->detailed_error[0] = '\0';
7262
/* Set the MySQL flag to mark that there is an active
7264
if (trx->active_trans == 0) {
7266
innobase_register_trx_and_stmt(engine, session);
7267
trx->active_trans = 1;
7268
} else if (trx->n_mysql_tables_in_use == 0) {
7269
innobase_register_stmt(engine, session);
7272
7096
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7273
7097
&& prebuilt->select_lock_type == LOCK_NONE
7274
7098
&& session_test_options(session,
7301
7125
trx->mysql_n_tables_locked++;
7304
trx->n_mysql_tables_in_use++;
7305
7128
prebuilt->mysql_has_locked = TRUE;
7310
7133
/* MySQL is releasing a table lock */
7312
trx->n_mysql_tables_in_use--;
7313
7134
prebuilt->mysql_has_locked = FALSE;
7315
/* Release a possible FIFO ticket and search latch. Since we
7316
may reserve the kernel mutex, we have to release the search
7317
system latch first to obey the latching order. */
7319
innobase_release_stat_resources(trx);
7321
/* If the MySQL lock count drops to zero we know that the current SQL
7322
statement has ended */
7324
if (trx->n_mysql_tables_in_use == 0) {
7326
trx->mysql_n_tables_locked = 0;
7327
prebuilt->used_in_HANDLER = FALSE;
7329
if (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7330
if (trx->active_trans != 0) {
7331
engine->commit(session, TRUE);
7334
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7335
&& trx->global_read_view) {
7337
/* At low transaction isolation levels we let
7338
each consistent read set its own snapshot */
7340
read_view_close_for_mysql(trx);
7135
trx->mysql_n_tables_locked= 0;
7348
7140
/************************************************************************//**
7349
Here we export InnoDB status variables to MySQL. */
7352
innodb_export_status(void)
7353
/*======================*/
7355
if (innodb_inited) {
7356
srv_export_innodb_status();
7360
/************************************************************************//**
7361
7141
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
7362
7142
Monitor to the client. */
7696
7476
trx = check_trx_exists(session);
7698
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7699
Be careful to ignore TL_IGNORE if we are going to do something with
7700
only 'real' locks! */
7702
/* If no MySQL table is in use, we need to set the isolation level
7703
of the transaction. */
7705
if (lock_type != TL_IGNORE
7706
&& trx->n_mysql_tables_in_use == 0) {
7707
trx->isolation_level = innobase_map_isolation_level(
7708
(enum_tx_isolation) session_tx_isolation(session));
7710
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7711
&& trx->global_read_view) {
7713
/* At low transaction isolation levels we let
7714
each consistent read set its own snapshot */
7716
read_view_close_for_mysql(trx);
7720
7478
assert(EQ_CURRENT_SESSION(session));
7721
7479
const uint32_t sql_command = session_sql_command(session);
7797
7555
TABLESPACE or TRUNCATE TABLE then allow multiple
7798
7556
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7799
7557
< TL_WRITE_CONCURRENT_INSERT.
7801
We especially allow multiple writers if MySQL is at the
7802
start of a stored procedure call (SQLCOM_CALL) or a
7803
stored function call (MySQL does have in_lock_tables
7806
7560
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7807
7561
&& lock_type <= TL_WRITE)
7817
7571
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7818
7572
to t2. Convert the lock to a normal read lock to allow
7819
7573
concurrent inserts to t2.
7821
We especially allow concurrent inserts if MySQL is at the
7822
start of a stored procedure call (SQLCOM_CALL)
7823
(MySQL does have session_in_lock_tables() TRUE there). */
7825
7576
if (lock_type == TL_READ_NO_INSERT) {
8196
7947
return(char_length);
7950
* We will also use this function to communicate
7951
* to InnoDB that a new SQL statement has started and that we must store a
7952
* savepoint to our transaction handle, so that we are able to roll back
7953
* the SQL statement in case of an error.
7956
InnobaseEngine::doStartStatement(
7957
Session *session) /*!< in: handle to the Drizzle session */
7960
* Create the InnoDB transaction structure
7963
trx_t *trx= check_trx_exists(session);
7965
/* "reset" the error message for the transaction */
7966
trx->detailed_error[0]= '\0';
7968
/* Set the isolation level of the transaction. */
7969
trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
7973
InnobaseEngine::doEndStatement(
7976
trx_t *trx= check_trx_exists(session);
7978
/* Release a possible FIFO ticket and search latch. Since we
7979
may reserve the kernel mutex, we have to release the search
7980
system latch first to obey the latching order. */
7982
innobase_release_stat_resources(trx);
7984
if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
7986
if (trx->conc_state != TRX_NOT_STARTED)
7988
commit(session, TRUE);
7993
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
7994
trx->global_read_view)
7996
/* At low transaction isolation levels we let
7997
each consistent read set its own snapshot */
7998
read_view_close_for_mysql(trx);
8199
8003
/*******************************************************************//**
8200
8004
This function is used to prepare an X/Open XA distributed transaction.
8201
8005
@return 0 or error number */
8203
InnobaseEngine::prepare(
8007
InnobaseEngine::doXaPrepare(
8204
8008
/*================*/
8205
8009
Session* session,/*!< in: handle to the MySQL thread of
8206
8010
the user whose XA transaction should
8231
8035
innobase_release_stat_resources(trx);
8233
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8235
errmsg_printf(ERRMSG_LVL_ERROR,
8236
"trx->active_trans == 0, but trx->conc_state != "
8241
8038
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8243
8040
/* We were instructed to prepare the whole transaction, or
8244
8041
this is an SQL statement end and autocommit is on */
8246
ut_ad(trx->active_trans);
8043
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8248
8045
error = (int) trx_prepare_for_mysql(trx);
8299
8096
This function is used to recover X/Open XA distributed transactions.
8300
8097
@return number of prepared transactions stored in xid_list */
8302
InnobaseEngine::recover(
8099
InnobaseEngine::doXaRecover(
8303
8100
/*================*/
8304
8101
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8305
uint len) /*!< in: number of slots in xid_list */
8102
size_t len) /*!< in: number of slots in xid_list */
8307
8104
assert(this == innodb_engine_ptr);
8727
8524
*(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
8730
static int show_innodb_vars(SHOW_VAR *var, char *)
8732
innodb_export_status();
8733
var->type= SHOW_ARRAY;
8734
var->value= (char *) &innodb_status_variables;
8738
static st_show_var_func_container
8739
show_innodb_vars_cont = { &show_innodb_vars };
8741
static SHOW_VAR innodb_status_variables_export[]= {
8742
{"Innodb", (char*) &show_innodb_vars_cont, SHOW_FUNC},
8743
{NULL, NULL, SHOW_LONG}
8747
8527
/* plugin options */
8748
8528
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
8749
8529
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,