mirror of
https://github.com/MariaDB/server.git
synced 2025-01-28 17:54:16 +01:00
query_id and my_xid -> ulonglong
fix for binlog+autocommit+tclog comments, style fixes libmysqld/libmysqld.rc: Change mode to -rw-rw-r-- libmysqld/resource.h: Change mode to -rw-rw-r-- configure.in: check for getpagesize include/my_global.h: typo ? include/my_pthread.h: bug in thread_safe_decrement_and_test() mysql-test/r/bdb.result: results updated mysql-test/r/innodb.result: results updated mysql-test/r/mix_innodb_myisam_binlog.result: results updated mysql-test/r/rpl_relayrotate.result: results updated sql/ha_berkeley.cc: style fixes sql/ha_innodb.cc: fixes to follow innodb coding style sql/handler.cc: more comments. XA COMMIT ONE PHASE fix. sql/handler.h: my_xid -> ulonglong. comments sql/item_func.cc: DO RELEASE_LOCK("...") is no cache_stmt sql/log.cc: comments, better error messages sql/log_event.cc: even in autocommit mode we may need to cache_stmt xid is ulonglong sql/log_event.h: more comments. sql/mysql_priv.h: query_id is ulonglong sql/mysqld.cc: default value for --log-tc changed sql/share/errmsg.txt: better error messages sql/sql_class.h: cleanup, comments sql/sql_delete.cc: deleting from temporary tables is not always transactional sql/sql_insert.cc: insert into temporary table is not always transactional sql/sql_load.cc: load data into temp table is not always transactional sql/sql_parse.cc: comments. bad merge fixed. xa_state_names[] sql/sql_table.cc: create/drop temp table is not always transactional sql/sql_update.cc: update temp table is not always transactional
This commit is contained in:
parent
a7401bf7cc
commit
042448aa33
27 changed files with 377 additions and 301 deletions
|
@ -1914,7 +1914,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
|
|||
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
|
||||
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
|
||||
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
|
||||
mkstemp mlockall perror poll pread pthread_attr_create mmap \
|
||||
mkstemp mlockall perror poll pread pthread_attr_create mmap getpagesize \
|
||||
pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
|
||||
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
|
||||
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
|
||||
|
|
|
@ -751,7 +751,7 @@ typedef long int32;
|
|||
#endif
|
||||
typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
|
||||
#else
|
||||
error "Neither int or long is of 4 bytes width"
|
||||
#error "Neither int or long is of 4 bytes width"
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC)
|
||||
|
|
|
@ -692,7 +692,7 @@ static inline bool thread_safe_dec_and_test(ulong &V, pthread_mutex_t *L)
|
|||
{
|
||||
ulong res;
|
||||
pthread_mutex_lock(L);
|
||||
res=V--;
|
||||
res=--V;
|
||||
pthread_mutex_unlock(L);
|
||||
return res==0;
|
||||
}
|
||||
|
|
0
libmysqld/libmysqld.rc
Executable file → Normal file
0
libmysqld/libmysqld.rc
Executable file → Normal file
0
libmysqld/resource.h
Executable file → Normal file
0
libmysqld/resource.h
Executable file → Normal file
|
@ -1445,7 +1445,7 @@ qq
|
|||
*a *a*a *
|
||||
explain select * from t1 where v='a';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref v,v_2 v 13 const 10 Using where
|
||||
1 SIMPLE t1 ref v,v_2 # 13 const # Using where
|
||||
select v,count(*) from t1 group by v limit 10;
|
||||
v count(*)
|
||||
a 1
|
||||
|
|
|
@ -1609,14 +1609,14 @@ t2 CREATE TABLE `t2` (
|
|||
drop table t2, t1;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 24
|
||||
Binlog_cache_use 150
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 0
|
||||
create table t1 (a int) engine=innodb;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 25
|
||||
Binlog_cache_use 151
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 1
|
||||
|
@ -1625,7 +1625,7 @@ delete from t1;
|
|||
commit;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 26
|
||||
Binlog_cache_use 152
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 1
|
||||
|
|
|
@ -12,7 +12,7 @@ master-bin.000001 96 Query 1 # use `test`; BEGIN
|
|||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(1)
|
||||
master-bin.000001 239 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 327 Xid 1 # xid=7
|
||||
master-bin.000001 350 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 354 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -49,7 +49,7 @@ master-bin.000001 318 Query 1 # use `test`; insert into t1 values(4)
|
|||
master-bin.000001 399 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 487 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 578 Xid 1 # xid=24
|
||||
master-bin.000001 601 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 605 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -77,7 +77,7 @@ master-bin.000001 399 Query 1 # use `test`; insert into t2 select * from t1
|
|||
master-bin.000001 487 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 578 Query 1 # use `test`; insert into t1 values(7)
|
||||
master-bin.000001 659 Xid 1 # xid=36
|
||||
master-bin.000001 682 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 686 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -96,6 +96,7 @@ master-bin.000001 96 Query 1 # use `test`; BEGIN
|
|||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(8)
|
||||
master-bin.000001 239 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 327 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 392 Query 1 # use `test`; DO RELEASE_LOCK("a")
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -103,8 +104,11 @@ insert into t1 values(9);
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 96;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 96 Query 1 # use `test`; insert into t1 values(9)
|
||||
master-bin.000001 177 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 96 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(9)
|
||||
master-bin.000001 239 Xid 1 # xid=59
|
||||
master-bin.000001 266 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 329 Query 1 # use `test`; insert into t2 select * from t1
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -113,18 +117,24 @@ begin;
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 96;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 96 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 178 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 96 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 240 Xid 1 # xid=65
|
||||
master-bin.000001 267 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 330 Query 1 # use `test`; insert into t2 select * from t1
|
||||
insert into t1 values(11);
|
||||
commit;
|
||||
show binlog events from 96;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 96 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 178 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 266 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 328 Query 1 # use `test`; insert into t1 values(11)
|
||||
master-bin.000001 410 Xid 1 # xid=67
|
||||
master-bin.000001 433 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 96 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 240 Xid 1 # xid=65
|
||||
master-bin.000001 267 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 330 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 418 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 480 Query 1 # use `test`; insert into t1 values(11)
|
||||
master-bin.000001 562 Xid 1 # xid=67
|
||||
master-bin.000001 589 Query 1 # use `test`; COMMIT
|
||||
alter table t2 engine=INNODB;
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
|
@ -139,7 +149,7 @@ master-bin.000001 96 Query 1 # use `test`; BEGIN
|
|||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(12)
|
||||
master-bin.000001 240 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 328 Xid 1 # xid=77
|
||||
master-bin.000001 351 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 355 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -164,7 +174,7 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
|||
master-bin.000001 96 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(14)
|
||||
master-bin.000001 240 Xid 1 # xid=93
|
||||
master-bin.000001 263 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 267 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -186,7 +196,7 @@ master-bin.000001 96 Query 1 # use `test`; BEGIN
|
|||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(16)
|
||||
master-bin.000001 240 Query 1 # use `test`; insert into t1 values(18)
|
||||
master-bin.000001 322 Xid 1 # xid=104
|
||||
master-bin.000001 345 Query 1 # use `test`; COMMIT
|
||||
master-bin.000001 349 Query 1 # use `test`; COMMIT
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
alter table t2 type=MyISAM;
|
||||
|
|
|
@ -18,5 +18,5 @@ max(a)
|
|||
8000
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 687231 # # master-bin.000001 Yes Yes 0 0 687231 # None 0 No #
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 687235 # # master-bin.000001 Yes Yes 0 0 687235 # None 0 No #
|
||||
drop table t1;
|
||||
|
|
|
@ -238,15 +238,13 @@ static int berkeley_commit(THD *thd, bool all)
|
|||
DBUG_ENTER("berkeley_commit");
|
||||
DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
int error=txn_commit(all ? trx->all : trx->stmt,0);
|
||||
DB_TXN **txn= all ? &trx->all : &trx->stmt;
|
||||
int error=txn_commit(*txn,0);
|
||||
*txn=0;
|
||||
#ifndef DBUG_OFF
|
||||
if (error)
|
||||
DBUG_PRINT("error",("error: %d",error));
|
||||
#endif
|
||||
if (all)
|
||||
trx->all=0;
|
||||
else
|
||||
trx->stmt=0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -255,11 +253,9 @@ static int berkeley_rollback(THD *thd, bool all)
|
|||
DBUG_ENTER("berkeley_rollback");
|
||||
DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
int error=txn_abort(all ? trx->all : trx->stmt);
|
||||
if (all)
|
||||
trx->all=0;
|
||||
else
|
||||
trx->stmt=0;
|
||||
DB_TXN **txn= all ? &trx->all : &trx->stmt;
|
||||
int error=txn_abort(*txn);
|
||||
*txn=0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -1904,7 +1900,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
|
|||
if (trx->stmt)
|
||||
{
|
||||
/*
|
||||
F_UNLOCK is done without a transaction commit / rollback.
|
||||
F_UNLCK is done without a transaction commit / rollback.
|
||||
This happens if the thread didn't update any rows
|
||||
We must in this case commit the work to keep the row locks
|
||||
*/
|
||||
|
@ -1929,6 +1925,7 @@ int ha_berkeley::start_stmt(THD *thd)
|
|||
int error=0;
|
||||
DBUG_ENTER("ha_berkeley::start_stmt");
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
DBUG_ASSERT(trx);
|
||||
/*
|
||||
note that trx->stmt may have been already initialized as start_stmt()
|
||||
is called for *each table* not for each storage engine,
|
||||
|
@ -2277,6 +2274,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
|||
DB_BTREE_STAT *stat=0;
|
||||
DB_TXN_STAT *txn_stat_ptr= 0;
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
DBUG_ASSERT(trx);
|
||||
|
||||
/*
|
||||
Original bdb documentation says:
|
||||
|
@ -2291,10 +2289,10 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
|||
txn_stat_ptr && txn_stat_ptr->st_nactive>=2)
|
||||
{
|
||||
DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0;
|
||||
|
||||
|
||||
u_int32_t all_id= trx->all->id(trx->all);
|
||||
u_int32_t stmt_id= trx->stmt->id(trx->stmt);
|
||||
|
||||
|
||||
DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray;
|
||||
DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive;
|
||||
for (; cur!=end && (!atxn_stmt || !atxn_all); cur++)
|
||||
|
@ -2302,7 +2300,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
|||
if (cur->txnid==all_id) atxn_all= cur;
|
||||
if (cur->txnid==stmt_id) atxn_stmt= cur;
|
||||
}
|
||||
|
||||
|
||||
if (atxn_stmt && atxn_all &&
|
||||
log_compare(&atxn_stmt->lsn,&atxn_all->lsn))
|
||||
{
|
||||
|
|
|
@ -698,7 +698,7 @@ ha_innobase::update_thd(
|
|||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
trx_t* trx;
|
||||
|
||||
|
||||
trx = check_trx_exists(thd);
|
||||
|
||||
if (prebuilt->trx != trx) {
|
||||
|
@ -711,11 +711,23 @@ ha_innobase::update_thd(
|
|||
return(0);
|
||||
}
|
||||
|
||||
static void register_trans(THD *thd)
|
||||
/*************************************************************************
|
||||
Registers the InnoDB transaction in MySQL, to receive commit/rollback
|
||||
events. This function must be called every time InnoDB starts a
|
||||
transaction internally. */
|
||||
static
|
||||
void
|
||||
register_trans(
|
||||
/*============*/
|
||||
THD* thd) /* in: thd to use the handle */
|
||||
{
|
||||
trans_register_ha(thd, FALSE, &innobase_hton);
|
||||
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
||||
trans_register_ha(thd, TRUE, &innobase_hton);
|
||||
/* register the start of the statement */
|
||||
trans_register_ha(thd, FALSE, &innobase_hton);
|
||||
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
|
||||
|
||||
/* no autocommit mode, register for a transaction */
|
||||
trans_register_ha(thd, TRUE, &innobase_hton);
|
||||
}
|
||||
}
|
||||
|
||||
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
|
||||
|
@ -1459,12 +1471,12 @@ innobase_report_binlog_offset_and_commit(
|
|||
|
||||
ut_a(trx != NULL);
|
||||
|
||||
trx->mysql_log_file_name = log_file_name;
|
||||
trx->mysql_log_file_name = log_file_name;
|
||||
trx->mysql_log_offset = (ib_longlong)end_offset;
|
||||
|
||||
|
||||
trx->flush_log_later = TRUE;
|
||||
|
||||
innobase_commit(thd, trx_handle);
|
||||
innobase_commit(thd, trx_handle);
|
||||
|
||||
trx->flush_log_later = FALSE;
|
||||
|
||||
|
@ -1474,18 +1486,18 @@ innobase_report_binlog_offset_and_commit(
|
|||
/***********************************************************************
|
||||
This function stores the binlog offset and flushes logs. */
|
||||
|
||||
void
|
||||
void
|
||||
innobase_store_binlog_offset_and_flush_log(
|
||||
/*=======================================*/
|
||||
char *binlog_name, /* in: binlog name */
|
||||
longlong offset) /* in: binlog offset */
|
||||
longlong offset) /* in: binlog offset */
|
||||
{
|
||||
mtr_t mtr;
|
||||
|
||||
|
||||
assert(binlog_name != NULL);
|
||||
|
||||
/* Start a mini-transaction */
|
||||
mtr_start_noninline(&mtr);
|
||||
mtr_start_noninline(&mtr);
|
||||
|
||||
/* Update the latest MySQL binlog name and offset info
|
||||
in trx sys header */
|
||||
|
@ -1497,7 +1509,7 @@ innobase_store_binlog_offset_and_flush_log(
|
|||
|
||||
/* Commits the mini-transaction */
|
||||
mtr_commit(&mtr);
|
||||
|
||||
|
||||
/* Syncronous flush of the log buffer to disk */
|
||||
log_buffer_flush_to_disk();
|
||||
}
|
||||
|
@ -1520,14 +1532,14 @@ innobase_commit_complete(
|
|||
|
||||
if (trx && trx->active_trans) {
|
||||
|
||||
trx->active_trans = 0;
|
||||
trx->active_trans = 0;
|
||||
|
||||
if (srv_flush_log_at_trx_commit == 0) {
|
||||
if (srv_flush_log_at_trx_commit == 0) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
trx_commit_complete_for_mysql(trx);
|
||||
trx_commit_complete_for_mysql(trx);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
|
|
@ -59,8 +59,15 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
|
|||
|
||||
static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
|
||||
|
||||
/* list of all available storage engines (of their handlertons) */
|
||||
handlerton *handlertons[MAX_HA]={0};
|
||||
ulong total_ha, total_ha_2pc, savepoint_alloc_size;
|
||||
|
||||
/* number of entries in handlertons[] */
|
||||
ulong total_ha;
|
||||
/* number of storage engines (from handlertons[]) that support 2pc */
|
||||
ulong total_ha_2pc;
|
||||
/* size of savepoint storage area (see ha_init) */
|
||||
ulong savepoint_alloc_size;
|
||||
|
||||
struct show_table_type_st sys_table_types[]=
|
||||
{
|
||||
|
@ -120,7 +127,7 @@ enum db_type ha_resolve_by_name(const char *name, uint namelen)
|
|||
if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) {
|
||||
return (enum db_type) thd->variables.table_type;
|
||||
}
|
||||
|
||||
|
||||
show_table_type_st *types;
|
||||
for (types= sys_table_types; types->type; types++)
|
||||
{
|
||||
|
@ -138,7 +145,7 @@ const char *ha_get_storage_engine(enum db_type db_type)
|
|||
if (db_type == types->db_type)
|
||||
return types->type;
|
||||
}
|
||||
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
|
@ -439,6 +446,7 @@ int ha_commit_trans(THD *thd, bool all)
|
|||
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
|
||||
bool is_real_trans= all || thd->transaction.all.nht == 0;
|
||||
handlerton **ht= trans->ht;
|
||||
my_xid xid= thd->transaction.xid.get_my_xid();
|
||||
DBUG_ENTER("ha_commit_trans");
|
||||
#ifdef USING_TRANSACTIONS
|
||||
if (trans->nht)
|
||||
|
@ -455,9 +463,8 @@ int ha_commit_trans(THD *thd, bool all)
|
|||
}
|
||||
statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
|
||||
}
|
||||
if (error || (is_real_trans &&
|
||||
(error= !(cookie= tc_log->log(thd,
|
||||
thd->transaction.xid.quick_get_my_xid())))))
|
||||
if (error || (is_real_trans && xid &&
|
||||
(error= !(cookie= tc_log->log(thd, xid)))))
|
||||
{
|
||||
ha_rollback_trans(thd, all);
|
||||
return 1;
|
||||
|
@ -465,7 +472,7 @@ int ha_commit_trans(THD *thd, bool all)
|
|||
}
|
||||
error=ha_commit_one_phase(thd, all) ? cookie ? 2 : 1 : 0;
|
||||
if (cookie)
|
||||
tc_log->unlog(cookie, thd->transaction.xid.quick_get_my_xid());
|
||||
tc_log->unlog(cookie, xid);
|
||||
}
|
||||
#endif /* USING_TRANSACTIONS */
|
||||
DBUG_RETURN(error);
|
||||
|
@ -486,7 +493,7 @@ int ha_commit_one_phase(THD *thd, bool all)
|
|||
{
|
||||
if ((error= wait_if_global_read_lock(thd, 0, 0)))
|
||||
{
|
||||
my_error(ER_SERVER_SHUTDOWN, MYF(0)); // we're killed
|
||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
||||
error= 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -195,7 +195,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
|
|||
#define HA_CREATE_USED_COMMENT (1L << 16)
|
||||
#define HA_CREATE_USED_PASSWORD (1L << 17)
|
||||
|
||||
typedef ulong my_xid;
|
||||
typedef ulonglong my_xid;
|
||||
#define MYSQL_XID_PREFIX "MySQLXid"
|
||||
#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
|
||||
#define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
|
||||
|
@ -215,11 +215,11 @@ struct xid_t {
|
|||
bool eq(long g, long b, const char *d)
|
||||
{ return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
|
||||
void set(LEX_STRING *l) { set(l->length, 0, l->str); }
|
||||
void set(ulong l)
|
||||
void set(ulonglong l)
|
||||
{
|
||||
set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
|
||||
*(ulong*)(data+MYSQL_XID_PREFIX_LEN)=server_id;
|
||||
*(ulong*)(data+MYSQL_XID_OFFSET)=l;
|
||||
*(my_xid*)(data+MYSQL_XID_OFFSET)=l;
|
||||
gtrid_length=MYSQL_XID_GTRID_LEN;
|
||||
}
|
||||
void set(long g, long b, const char *d)
|
||||
|
@ -233,7 +233,7 @@ struct xid_t {
|
|||
void null() { formatID= -1; }
|
||||
my_xid quick_get_my_xid()
|
||||
{
|
||||
return *(ulong*)(data+MYSQL_XID_OFFSET);
|
||||
return *(my_xid*)(data+MYSQL_XID_OFFSET);
|
||||
}
|
||||
my_xid get_my_xid()
|
||||
{
|
||||
|
@ -319,8 +319,11 @@ typedef struct
|
|||
|
||||
typedef struct st_thd_trans
|
||||
{
|
||||
/* number of entries in the ht[] */
|
||||
uint nht;
|
||||
/* true is not all entries in the ht[] support 2pc */
|
||||
bool no_2pc;
|
||||
/* storage engines that registered themselves for this transaction */
|
||||
handlerton *ht[MAX_HA];
|
||||
} THD_TRANS;
|
||||
|
||||
|
|
|
@ -2096,7 +2096,7 @@ void item_user_lock_release(User_level_lock *ull)
|
|||
tmp.copy(command, strlen(command), tmp.charset());
|
||||
tmp.append(ull->key,ull->key_length);
|
||||
tmp.append("\")", 2);
|
||||
Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1, FALSE);
|
||||
Query_log_event qev(current_thd, tmp.ptr(), tmp.length(), 0, FALSE);
|
||||
qev.error_code=0; // this query is always safe to run on slave
|
||||
mysql_bin_log.write(&qev);
|
||||
}
|
||||
|
|
229
sql/log.cc
229
sql/log.cc
|
@ -75,6 +75,7 @@ handlerton *binlog_init()
|
|||
static int binlog_close_connection(THD *thd)
|
||||
{
|
||||
IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
|
||||
DBUG_ASSERT(mysql_bin_log.is_open() && !my_b_tell(trans_log));
|
||||
close_cached_file(trans_log);
|
||||
my_free((gptr)trans_log, MYF(0));
|
||||
return 0;
|
||||
|
@ -109,7 +110,7 @@ static int binlog_commit(THD *thd, bool all)
|
|||
IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
|
||||
DBUG_ENTER("binlog_commit");
|
||||
DBUG_ASSERT(mysql_bin_log.is_open() &&
|
||||
(all || !(thd->options & OPTION_NOT_AUTOCOMMIT)));
|
||||
(all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))));
|
||||
|
||||
if (!my_b_tell(trans_log))
|
||||
{
|
||||
|
@ -1247,7 +1248,7 @@ void MYSQL_LOG::new_file(bool need_lock)
|
|||
{
|
||||
pthread_mutex_lock(&LOCK_log);
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
}
|
||||
}
|
||||
safe_mutex_assert_owner(&LOCK_log);
|
||||
safe_mutex_assert_owner(&LOCK_index);
|
||||
|
||||
|
@ -1567,10 +1568,14 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
goto err;
|
||||
}
|
||||
trans_log->end_of_file= max_binlog_cache_size;
|
||||
trans_register_ha(thd, TRUE, &binlog_hton);
|
||||
trans_register_ha(thd,
|
||||
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN),
|
||||
&binlog_hton);
|
||||
}
|
||||
else if (!my_b_tell(trans_log))
|
||||
trans_register_ha(thd, TRUE, &binlog_hton);
|
||||
trans_register_ha(thd,
|
||||
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN),
|
||||
&binlog_hton);
|
||||
file= trans_log;
|
||||
}
|
||||
else if (trans_log && my_b_tell(trans_log))
|
||||
|
@ -2057,8 +2062,7 @@ void MYSQL_LOG::close(uint exiting)
|
|||
{
|
||||
my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
|
||||
char flags=LOG_EVENT_BINLOG_CLOSED_F;
|
||||
my_pwrite(log_file.file, &flags, 1,
|
||||
BIN_LOG_HEADER_SIZE + FLAGS_OFFSET, MYF(0));
|
||||
my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
|
||||
}
|
||||
|
||||
if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
|
||||
|
@ -2382,26 +2386,33 @@ void sql_print_information(const char *format, ...)
|
|||
(usable size of the first page is smaller because of log header)
|
||||
there's PAGE control structure for each page
|
||||
each page (or rather PAGE control structure) can be in one of three
|
||||
states - active, in_sync, pool.
|
||||
there could be only one page in active or in_sync states,
|
||||
states - active, syncing, pool.
|
||||
there could be only one page in active or syncing states,
|
||||
but many in pool - pool is fifo queue.
|
||||
usual lifecycle of a page is pool->active->in_sync->pool
|
||||
usual lifecycle of a page is pool->active->syncing->pool
|
||||
"active" page - is a page where new xid's are logged.
|
||||
the page stays active as long as in_sync slot is taken.
|
||||
"in_sync" page is being synced to disk. no new xid can be added to it.
|
||||
the page stays active as long as syncing slot is taken.
|
||||
"syncing" page is being synced to disk. no new xid can be added to it.
|
||||
when the sync is done the page is moved to a pool and an active page
|
||||
becomes "in_sync".
|
||||
becomes "syncing".
|
||||
|
||||
when a xid is added to an active page, the thread of this xid waits for
|
||||
a page's condition until the page is synced. when in_sync slot becomes vacant
|
||||
one of these waiters is awaken to take care of syncing. it syncs the page
|
||||
and signals all waiters that the page is synced.
|
||||
the result of such an architecture is a natural "commit grouping" -
|
||||
If commits are coming faster than the system can sync, they do not
|
||||
stall. Instead, all commit that came since the last sync are
|
||||
logged to the same page, and they all are synced with the next -
|
||||
one - sync. Thus, thought individual commits are delayed, throughput
|
||||
is not decreasing.
|
||||
|
||||
when a xid is added to an active page, the thread of this xid waits
|
||||
for a page's condition until the page is synced. when syncing slot
|
||||
becomes vacant one of these waiters is awaken to take care of syncing.
|
||||
it syncs the page and signals all waiters that the page is synced.
|
||||
PAGE::waiters is used to count these waiters, and a page may never
|
||||
become active again until waiters==0 (that is all waiters from the
|
||||
previous sync have noticed the sync was completed)
|
||||
|
||||
note, that the page becomes "dirty" and has to be synced only when
|
||||
a new xid is added into it. Removing a xid from a page does not make it
|
||||
note, that the page becomes "dirty" and has to be synced only when a
|
||||
new xid is added into it. Removing a xid from a page does not make it
|
||||
dirty - we don't sync removals to disk.
|
||||
*/
|
||||
#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
|
||||
|
@ -2433,35 +2444,38 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
|||
#endif
|
||||
|
||||
fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
|
||||
fd=my_open(logname, O_RDWR, MYF(0)); // TODO use O_CREAT and check len==0 ?
|
||||
fd= my_open(logname, O_RDWR, MYF(0));
|
||||
if (fd == -1)
|
||||
{
|
||||
if (my_errno != ENOENT)
|
||||
goto err;
|
||||
if (using_heuristic_recover())
|
||||
return 1;
|
||||
fd=my_open(logname, O_RDWR|O_CREAT, MYF(MY_WME));
|
||||
fd= my_create(logname, O_RDWR, 0, MYF(MY_WME));
|
||||
if (fd == -1)
|
||||
goto err;
|
||||
inited=1;
|
||||
file_length=opt_tc_log_size;
|
||||
file_length= opt_tc_log_size;
|
||||
if (my_chsize(fd, file_length, 0, MYF(MY_WME)))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
inited=1;
|
||||
crashed=TRUE;
|
||||
inited= 1;
|
||||
crashed= TRUE;
|
||||
sql_print_information("Recovering after a crash");
|
||||
if (tc_heuristic_recover)
|
||||
{
|
||||
sql_print_error("Cannot perform automatic crash recovery when "
|
||||
"--tc-heuristic-recover is used");
|
||||
goto err;
|
||||
}
|
||||
file_length = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
|
||||
file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
|
||||
if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
|
||||
goto err;
|
||||
}
|
||||
|
||||
data=(uchar *)my_mmap(0, file_length, PROT_READ|PROT_WRITE,
|
||||
data= (uchar *)my_mmap(0, file_length, PROT_READ|PROT_WRITE,
|
||||
MAP_NOSYNC|MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED)
|
||||
{
|
||||
|
@ -2486,18 +2500,15 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
|||
pg->end=(my_xid *)(pg->start + tc_log_page_size);
|
||||
pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
|
||||
}
|
||||
pages[0].start=(my_xid *)(data+TC_LOG_HEADER_SIZE);
|
||||
pages[0].size=pages[0].free=
|
||||
(tc_log_page_size-TC_LOG_HEADER_SIZE)/sizeof(my_xid);
|
||||
pages[0].start=pages[0].end-pages[0].size;
|
||||
pages[npages-1].next=0;
|
||||
inited=4;
|
||||
|
||||
if (crashed)
|
||||
{
|
||||
sql_print_error("Recovering after a crash");
|
||||
if (recover())
|
||||
if (crashed && recover())
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(data, tc_log_magic, sizeof(tc_log_magic));
|
||||
data[sizeof(tc_log_magic)]= total_ha_2pc;
|
||||
my_msync(fd, data, tc_log_page_size, MS_SYNC);
|
||||
|
@ -2511,7 +2522,7 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
|||
|
||||
inited=6;
|
||||
|
||||
in_sync= 0;
|
||||
syncing= 0;
|
||||
active=pages;
|
||||
pool=pages+1;
|
||||
pool_last=pages+npages-1;
|
||||
|
@ -2524,6 +2535,8 @@ err:
|
|||
}
|
||||
|
||||
/*
|
||||
there is no active page, let's got one from the pool
|
||||
|
||||
two strategies here:
|
||||
1. take the first from the pool
|
||||
2. if there're waiters - take the one with the most free space
|
||||
|
@ -2536,13 +2549,16 @@ void TC_LOG_MMAP::get_active_from_pool()
|
|||
PAGE **p, **best_p=0;
|
||||
int best_free;
|
||||
|
||||
if (syncing)
|
||||
pthread_mutex_lock(&LOCK_pool);
|
||||
|
||||
do
|
||||
{
|
||||
best_p= p= &pool;
|
||||
if ((*p)->waiters == 0)
|
||||
break;
|
||||
if ((*p)->waiters == 0) // can the first page be used ?
|
||||
break; // yes - take it.
|
||||
|
||||
best_free=0;
|
||||
best_free=0; // no - trying second strategy
|
||||
for (p=&(*p)->next; *p; p=&(*p)->next)
|
||||
{
|
||||
if ((*p)->waiters == 0 && (*p)->free > best_free)
|
||||
|
@ -2555,16 +2571,19 @@ void TC_LOG_MMAP::get_active_from_pool()
|
|||
while ((*best_p == 0 || best_free == 0) && overflow());
|
||||
|
||||
active=*best_p;
|
||||
if (active->free == active->size)
|
||||
if (active->free == active->size) // we've chosen an empty page
|
||||
{
|
||||
tc_log_cur_pages_used++;
|
||||
set_if_bigger(tc_log_max_pages_used, tc_log_cur_pages_used);
|
||||
}
|
||||
|
||||
if ((*best_p)->next)
|
||||
if ((*best_p)->next) // unlink the page from the pool
|
||||
*best_p=(*best_p)->next;
|
||||
else
|
||||
pool_last=*best_p;
|
||||
|
||||
if (syncing)
|
||||
pthread_mutex_unlock(&LOCK_pool);
|
||||
}
|
||||
|
||||
int TC_LOG_MMAP::overflow()
|
||||
|
@ -2576,14 +2595,22 @@ int TC_LOG_MMAP::overflow()
|
|||
*/
|
||||
tc_log_page_waits++;
|
||||
pthread_cond_wait(&COND_pool, &LOCK_pool);
|
||||
return 1; // returns always 1
|
||||
return 1; // always return 1
|
||||
}
|
||||
|
||||
/*
|
||||
all access to active page is serialized but it's not a problem, as we're
|
||||
assuming that fsync() will be a bottleneck anyway.
|
||||
That is, parallelizing writes to log pages we'll decrease number of threads
|
||||
waiting for a page, but then all these threads will be waiting for fsync()
|
||||
all access to active page is serialized but it's not a problem, as
|
||||
we're assuming that fsync() will be a main bottleneck.
|
||||
That is, parallelizing writes to log pages we'll decrease number of
|
||||
threads waiting for a page, but then all these threads will be waiting
|
||||
for a fsync() anyway
|
||||
|
||||
RETURN
|
||||
0 - error
|
||||
otherwise - "cookie", a number that will be passed as an argument
|
||||
to unlog() call. tc_log can define it any way it wants,
|
||||
and use for whatever purposes. TC_LOG_MMAP sets it
|
||||
to the position in memory where xid was logged to.
|
||||
*/
|
||||
|
||||
int TC_LOG_MMAP::log(THD *thd, my_xid xid)
|
||||
|
@ -2594,42 +2621,50 @@ int TC_LOG_MMAP::log(THD *thd, my_xid xid)
|
|||
|
||||
pthread_mutex_lock(&LOCK_active);
|
||||
|
||||
/*
|
||||
if active page is full - just wait...
|
||||
frankly speaking, active->free here accessed outside of mutex
|
||||
protection, but it's safe, because it only means we may miss an
|
||||
unlog() for the active page, and we're not waiting for it here -
|
||||
unlog() does not signal COND_active.
|
||||
*/
|
||||
while (unlikely(active && active->free == 0))
|
||||
pthread_cond_wait(&COND_active, &LOCK_active);
|
||||
|
||||
/* no active page ? take one from the pool */
|
||||
if (active == 0)
|
||||
{
|
||||
lock_queue(&LOCK_pool);
|
||||
get_active_from_pool();
|
||||
unlock_queue(&LOCK_pool);
|
||||
}
|
||||
|
||||
p=active;
|
||||
pthread_mutex_lock(&p->lock);
|
||||
|
||||
/* searching for an empty slot */
|
||||
while (*p->ptr)
|
||||
{
|
||||
p->ptr++;
|
||||
DBUG_ASSERT(p->ptr < p->end); // because p->free > 0
|
||||
}
|
||||
|
||||
cookie= (ulong)((uchar *)p->ptr - data); // Can never be zero
|
||||
/* found! store xid there and mark the page dirty */
|
||||
cookie= (ulong)((uchar *)p->ptr - data); // can never be zero
|
||||
*p->ptr++= xid;
|
||||
p->free--;
|
||||
p->state= DIRTY;
|
||||
|
||||
/* to sync or not to sync - this is the question */
|
||||
pthread_mutex_unlock(&LOCK_active);
|
||||
pthread_mutex_lock(&LOCK_sync);
|
||||
pthread_mutex_unlock(&p->lock);
|
||||
|
||||
if (in_sync)
|
||||
if (syncing)
|
||||
{ // somebody's syncing. let's wait
|
||||
pthread_mutex_unlock(&LOCK_active);
|
||||
p->waiters++;
|
||||
do
|
||||
{
|
||||
/*
|
||||
note - it must be while(), not do ... while() here
|
||||
as p->state may be not DIRTY when we come here
|
||||
*/
|
||||
while (p->state == DIRTY && syncing)
|
||||
pthread_cond_wait(&p->cond, &LOCK_sync);
|
||||
} while (p->state == DIRTY && in_sync);
|
||||
p->waiters--;
|
||||
err= p->state == ERROR;
|
||||
if (p->state != DIRTY) // page was synced
|
||||
|
@ -2640,9 +2675,10 @@ int TC_LOG_MMAP::log(THD *thd, my_xid xid)
|
|||
goto done; // we're done
|
||||
}
|
||||
} // page was not synced! do it now
|
||||
in_sync=p; // place is vacant - take it
|
||||
DBUG_ASSERT(active == p);
|
||||
active=0;
|
||||
DBUG_ASSERT(active == p && syncing == 0);
|
||||
pthread_mutex_lock(&LOCK_active);
|
||||
syncing=p; // place is vacant - take it
|
||||
active=0; // page is not active anymore
|
||||
pthread_cond_broadcast(&COND_active); // in case somebody's waiting
|
||||
pthread_mutex_unlock(&LOCK_active);
|
||||
pthread_mutex_unlock(&LOCK_sync);
|
||||
|
@ -2656,30 +2692,36 @@ int TC_LOG_MMAP::sync()
|
|||
{
|
||||
int err;
|
||||
|
||||
DBUG_ASSERT(in_sync != active);
|
||||
DBUG_ASSERT(syncing != active);
|
||||
|
||||
/*
|
||||
sit down and relax - this can take a while...
|
||||
note - no locks are held at this point
|
||||
*/
|
||||
err= my_msync(fd, in_sync->start, 1, MS_SYNC);
|
||||
err= my_msync(fd, syncing->start, 1, MS_SYNC);
|
||||
|
||||
/* page is synced. let's move it to the pool */
|
||||
pthread_mutex_lock(&LOCK_pool);
|
||||
pool_last->next=in_sync;
|
||||
pool_last=in_sync;
|
||||
in_sync->next=0;
|
||||
in_sync->state= err ? ERROR : POOL;
|
||||
pthread_cond_broadcast(&in_sync->cond); // signal "sync done"
|
||||
pool_last->next=syncing;
|
||||
pool_last=syncing;
|
||||
syncing->next=0;
|
||||
syncing->state= err ? ERROR : POOL;
|
||||
pthread_cond_broadcast(&syncing->cond); // signal "sync done"
|
||||
pthread_cond_signal(&COND_pool); // in case somebody's waiting
|
||||
pthread_mutex_unlock(&LOCK_pool);
|
||||
|
||||
/* marking 'syncing' slot free */
|
||||
pthread_mutex_lock(&LOCK_sync);
|
||||
in_sync=0;
|
||||
syncing=0;
|
||||
pthread_cond_signal(&active->cond); // wake up a new syncer
|
||||
pthread_mutex_unlock(&LOCK_sync);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
erase xid from the page, update page free space counters/pointers.
|
||||
cookie points directly to the memory where xid was logged
|
||||
*/
|
||||
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
|
||||
{
|
||||
PAGE *p=pages+(cookie/tc_log_page_size);
|
||||
|
@ -2693,10 +2735,10 @@ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
|
|||
p->free++;
|
||||
DBUG_ASSERT(p->free <= p->size);
|
||||
set_if_smaller(p->ptr, x);
|
||||
if (p->free == p->size)
|
||||
if (p->free == p->size) // the page is completely empty
|
||||
statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
|
||||
if (p->waiters == 0) // the page is in pool and ready to rock
|
||||
pthread_cond_signal(&COND_pool); // ping ... in case somebody's waiting
|
||||
pthread_cond_signal(&COND_pool); // ping ... for overflow()
|
||||
pthread_mutex_unlock(&p->lock);
|
||||
}
|
||||
|
||||
|
@ -2747,8 +2789,10 @@ int TC_LOG_MMAP::recover()
|
|||
*/
|
||||
if (data[sizeof(tc_log_magic)] != total_ha_2pc)
|
||||
{
|
||||
sql_print_error("For recovery to work all storage engines and binary log "
|
||||
"must have exactly the same settings as before the crash!");
|
||||
sql_print_error("Recovery failed! You must have enabled "
|
||||
"exactly %d storage engines that support "
|
||||
"two-phase commit protocol",
|
||||
data[sizeof(tc_log_magic)]);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
|
@ -2793,6 +2837,7 @@ int TC_LOG::using_heuristic_recover()
|
|||
}
|
||||
|
||||
/****** transaction coordinator log for 2pc - binlog() based solution ******/
|
||||
#define TC_LOG_BINLOG MYSQL_LOG
|
||||
|
||||
/*
|
||||
TODO keep in-memory list of prepared transactions
|
||||
|
@ -2801,9 +2846,10 @@ int TC_LOG::using_heuristic_recover()
|
|||
but let's check the behaviour of tc_log_page_waits first!
|
||||
*/
|
||||
|
||||
int MYSQL_LOG::open(const char *opt_name)
|
||||
int TC_LOG_BINLOG::open(const char *opt_name)
|
||||
{
|
||||
LOG_INFO log_info, new_log_info;
|
||||
int error;
|
||||
|
||||
DBUG_ASSERT(total_ha_2pc > 1);
|
||||
|
||||
|
@ -2821,8 +2867,11 @@ int MYSQL_LOG::open(const char *opt_name)
|
|||
let's keep it happy.
|
||||
*/
|
||||
|
||||
if (find_log_pos(&new_log_info, NullS, 1))
|
||||
if ((error= find_log_pos(&new_log_info, NullS, 1)))
|
||||
{
|
||||
sql_print_error("find_log_pos() failed (error: %d)", error);
|
||||
goto err; // er ? where's the current entry ?
|
||||
}
|
||||
|
||||
if (strcmp(log_file_name, new_log_info.log_file_name))
|
||||
{
|
||||
|
@ -2830,9 +2879,8 @@ int MYSQL_LOG::open(const char *opt_name)
|
|||
char last_event_type=UNKNOWN_EVENT;
|
||||
IO_CACHE log;
|
||||
File file;
|
||||
int error;
|
||||
Log_event *ev;
|
||||
Format_description_log_event fdle(4);
|
||||
Log_event *ev=0;
|
||||
Format_description_log_event fdle(BINLOG_VERSION);
|
||||
|
||||
if (! fdle.is_valid())
|
||||
goto err;
|
||||
|
@ -2842,8 +2890,11 @@ int MYSQL_LOG::open(const char *opt_name)
|
|||
log_info.index_file_offset=new_log_info.index_file_offset;
|
||||
log_info.index_file_start_offset=new_log_info.index_file_offset;
|
||||
strcpy(log_info.log_file_name, new_log_info.log_file_name);
|
||||
if (find_next_log(&new_log_info, 1))
|
||||
goto err; // er ? where's the current entry ?
|
||||
if ((error= find_next_log(&new_log_info, 1)))
|
||||
{
|
||||
sql_print_error("find_log_pos() failed (error: %d)", error);
|
||||
goto err; // er ? where's the current entry ?
|
||||
}
|
||||
} while (strcmp(log_file_name, new_log_info.log_file_name));
|
||||
|
||||
if ((file= open_binlog(&log, log_info.log_file_name, &errmsg)) < 0)
|
||||
|
@ -2853,11 +2904,14 @@ int MYSQL_LOG::open(const char *opt_name)
|
|||
}
|
||||
|
||||
if (((ev= Log_event::read_log_event(&log, 0, &fdle))) &&
|
||||
(ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) &&
|
||||
(ev->flags & LOG_EVENT_BINLOG_CLOSED_F))
|
||||
error=0;
|
||||
else
|
||||
error= recover(&log, (Format_description_log_event *)ev);
|
||||
(ev->get_type_code() == FORMAT_DESCRIPTION_EVENT))
|
||||
{
|
||||
if (ev->flags & LOG_EVENT_BINLOG_CLOSED_F)
|
||||
error=0;
|
||||
else
|
||||
error= recover(&log, (Format_description_log_event *)ev);
|
||||
}
|
||||
// else nothing to do (probably MySQL 4.x binlog)
|
||||
|
||||
delete ev;
|
||||
end_io_cache(&log);
|
||||
|
@ -2873,15 +2927,22 @@ err:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void MYSQL_LOG::close()
|
||||
/* this is called on shutdown, after ha_panic */
|
||||
void TC_LOG_BINLOG::close()
|
||||
{
|
||||
DBUG_ASSERT(prepared_xids==0);
|
||||
pthread_mutex_destroy(&LOCK_prep_xids);
|
||||
pthread_cond_destroy (&COND_prep_xids);
|
||||
}
|
||||
|
||||
/* TODO group commit */
|
||||
int MYSQL_LOG::log(THD *thd, my_xid xid)
|
||||
/*
|
||||
TODO group commit
|
||||
|
||||
RETURN
|
||||
0 - error
|
||||
1 - success
|
||||
*/
|
||||
int TC_LOG_BINLOG::log(THD *thd, my_xid xid)
|
||||
{
|
||||
Xid_log_event xle(thd, xid);
|
||||
if (xle.write((IO_CACHE*)thd->ha_data[binlog_hton.slot]))
|
||||
|
@ -2890,13 +2951,13 @@ int MYSQL_LOG::log(THD *thd, my_xid xid)
|
|||
return !binlog_commit(thd,1); // invert return value
|
||||
}
|
||||
|
||||
void MYSQL_LOG::unlog(ulong cookie, my_xid xid)
|
||||
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
|
||||
{
|
||||
if (thread_safe_dec_and_test(prepared_xids, &LOCK_prep_xids))
|
||||
pthread_cond_signal(&COND_prep_xids);
|
||||
}
|
||||
|
||||
int MYSQL_LOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
|
||||
int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
|
||||
{
|
||||
Log_event *ev;
|
||||
HASH xids;
|
||||
|
|
|
@ -288,8 +288,6 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
|
|||
server_id= thd->server_id;
|
||||
when= thd->start_time;
|
||||
cache_stmt= using_trans;
|
||||
cache_stmt= (using_trans &&
|
||||
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,12 +314,12 @@ Log_event::Log_event()
|
|||
*/
|
||||
|
||||
Log_event::Log_event(const char* buf,
|
||||
const Format_description_log_event* description_event)
|
||||
const Format_description_log_event* description_event)
|
||||
:temp_buf(0), cache_stmt(0)
|
||||
{
|
||||
#ifndef MYSQL_CLIENT
|
||||
thd = 0;
|
||||
#endif
|
||||
#endif
|
||||
when = uint4korr(buf);
|
||||
server_id = uint4korr(buf + SERVER_ID_OFFSET);
|
||||
if (description_event->binlog_version==1)
|
||||
|
@ -2982,11 +2980,19 @@ void Xid_log_event::pack_info(Protocol *protocol)
|
|||
{
|
||||
char buf[64], *pos;
|
||||
pos= strmov(buf, "xid=");
|
||||
pos= int10_to_str(xid, pos, 10);
|
||||
pos= longlong10_to_str(xid, pos, 10);
|
||||
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
NOTE it's ok not to use int8store here,
|
||||
as long as xid_t::set(ulonglong) and
|
||||
xid_t::get_my_xid doesn't do it either
|
||||
|
||||
we don't care about actual values of xids as long as
|
||||
identical numbers compare identically
|
||||
*/
|
||||
Xid_log_event::Xid_log_event(const char* buf,
|
||||
const Format_description_log_event* description_event)
|
||||
:Log_event(buf, description_event)
|
||||
|
@ -3006,14 +3012,15 @@ bool Xid_log_event::write(IO_CACHE* file)
|
|||
#ifdef MYSQL_CLIENT
|
||||
void Xid_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
|
||||
{
|
||||
char buf[512];
|
||||
if (!short_form)
|
||||
{
|
||||
char buf[64];
|
||||
longlong10_to_str(xid, buf, 10);
|
||||
|
||||
print_header(file);
|
||||
fprintf(file, "\tXid\n");
|
||||
fprintf(file, "\tXid = %s\n", buf);
|
||||
fflush(file);
|
||||
}
|
||||
fprintf(file, "/* == %lu == */\n", xid);
|
||||
fflush(file);
|
||||
}
|
||||
#endif /* MYSQL_CLIENT */
|
||||
|
||||
|
|
|
@ -305,7 +305,10 @@ struct sql_ex_info
|
|||
/*
|
||||
This flag only makes sense for Format_description_log_event.
|
||||
It is set not when the event is written, but when a binlog file
|
||||
is closed.
|
||||
is closed. It serves as a reliable indicator that binlog was
|
||||
closed correctly. (Stop_log_event is not enough, there's always
|
||||
a small chance that mysqld crashes in the middle of insert
|
||||
and end of the binlog would look like a Stop_log_event)
|
||||
*/
|
||||
|
||||
#define LOG_EVENT_BINLOG_CLOSED_F 0x1
|
||||
|
@ -355,20 +358,26 @@ enum Log_event_type
|
|||
{
|
||||
/*
|
||||
Every time you update this enum (when you add a type), you have to
|
||||
update the code of Format_description_log_event::Format_description_log_event().
|
||||
Make sure you always insert new types ***BEFORE*** ENUM_END_EVENT.
|
||||
fix Format_description_log_event::Format_description_log_event().
|
||||
*/
|
||||
UNKNOWN_EVENT= 0, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT,
|
||||
INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT,
|
||||
APPEND_BLOCK_EVENT, EXEC_LOAD_EVENT, DELETE_FILE_EVENT,
|
||||
/*
|
||||
NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer sql_ex,
|
||||
allowing multibyte TERMINATED BY etc; both types share the same class
|
||||
(Load_log_event)
|
||||
NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer
|
||||
sql_ex, allowing multibyte TERMINATED BY etc; both types share the
|
||||
same class (Load_log_event)
|
||||
*/
|
||||
NEW_LOAD_EVENT, XID_EVENT,
|
||||
NEW_LOAD_EVENT,
|
||||
RAND_EVENT, USER_VAR_EVENT,
|
||||
FORMAT_DESCRIPTION_EVENT,
|
||||
XID_EVENT,
|
||||
|
||||
/*
|
||||
add new events here - right above this comment!
|
||||
existing events should never change their numbers
|
||||
*/
|
||||
|
||||
ENUM_END_EVENT /* end marker */
|
||||
};
|
||||
|
||||
|
|
|
@ -1247,26 +1247,11 @@ SQL_CRYPT *get_crypt_for_frm(void);
|
|||
|
||||
/* query_id */
|
||||
|
||||
typedef ulong query_id_t;
|
||||
typedef ulonglong query_id_t;
|
||||
extern query_id_t query_id;
|
||||
|
||||
/*
|
||||
increment query_id and return it.
|
||||
but be sure it's never a 0
|
||||
(2^32 at 1000 q/s rate will means an overflow every ~50 days.
|
||||
*/
|
||||
inline query_id_t next_query_id()
|
||||
{
|
||||
if (sizeof(query_id_t) <= 5) // assuming the compiler optimizes dead code away
|
||||
{
|
||||
query_id_t old_query_id=query_id;
|
||||
if (unlikely(++query_id == 0))
|
||||
query_id=1;
|
||||
return old_query_id;
|
||||
}
|
||||
else
|
||||
return query_id++;
|
||||
}
|
||||
/* increment query_id and return it. */
|
||||
inline query_id_t next_query_id() { return query_id++; }
|
||||
|
||||
/* Some inline functions for more speed */
|
||||
|
||||
|
|
|
@ -2162,8 +2162,8 @@ static void check_data_home(const char *path)
|
|||
|
||||
|
||||
/*
|
||||
All global error messages are sent here where the first one is stored for
|
||||
the client
|
||||
All global error messages are sent here where the first one is stored
|
||||
for the client
|
||||
*/
|
||||
|
||||
|
||||
|
@ -2199,7 +2199,7 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||
(thd->lex->current_select ?
|
||||
thd->lex->current_select->no_error : 0),
|
||||
(int) thd->is_fatal_error));
|
||||
|
||||
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
|
||||
}
|
||||
else
|
||||
|
@ -5601,7 +5601,7 @@ static void mysql_init_variables(void)
|
|||
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
|
||||
opt_disable_networking= opt_skip_show_db=0;
|
||||
opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
|
||||
opt_tc_log_file= "mysqld-tc.log"; // no hostname in tc_log file name !
|
||||
opt_tc_log_file= "tc.log"; // no hostname in tc_log file name !
|
||||
opt_secure_auth= 0;
|
||||
opt_bootstrap= opt_myisam_log= 0;
|
||||
mqh_used= 0;
|
||||
|
|
|
@ -5237,10 +5237,10 @@ ER_XAER_NOTA XAE04
|
|||
ER_XAER_INVAL XAE05
|
||||
eng "XAER_INVAL: Invalid arguments (or unsupported command)"
|
||||
ER_XAER_RMFAIL XAE07
|
||||
eng "XAER_RMFAIL: The command cannot be executed in this state"
|
||||
eng "XAER_RMFAIL: The command cannot be executed in the %.64s state"
|
||||
ER_XAER_OUTSIDE XAE09
|
||||
eng "XAER_OUTSIDE: Some work is done outside global transaction"
|
||||
ER_XAER_RMERR XAE03
|
||||
eng "XAER_RMERR: fatal error occurred in the transaction branch - check your data for consistency"
|
||||
eng "XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency"
|
||||
ER_XA_RBROLLBACK XA100
|
||||
eng "XA_RBROLLBACK: Transaction branch was rolled back"
|
||||
|
|
|
@ -105,7 +105,13 @@ class TC_LOG_MMAP: public TC_LOG
|
|||
File fd;
|
||||
uint file_length, npages, inited;
|
||||
uchar *data;
|
||||
struct st_page *pages, *in_sync, *active, *pool, *pool_last;
|
||||
struct st_page *pages, *syncing, *active, *pool, *pool_last;
|
||||
/*
|
||||
note that, e.g. LOCK_active is only used to protect
|
||||
'active' pointer, to protect the content of the active page
|
||||
one has to use active->lock.
|
||||
Same for LOCK_pool and LOCK_sync
|
||||
*/
|
||||
pthread_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
|
||||
pthread_cond_t COND_pool, COND_active;
|
||||
|
||||
|
@ -121,17 +127,6 @@ class TC_LOG_MMAP: public TC_LOG
|
|||
void get_active_from_pool();
|
||||
int sync();
|
||||
int overflow();
|
||||
void compact_active();
|
||||
void lock_queue(pthread_mutex_t *lock)
|
||||
{
|
||||
if (in_sync)
|
||||
pthread_mutex_lock(lock);
|
||||
}
|
||||
void unlock_queue(pthread_mutex_t *lock)
|
||||
{
|
||||
if (in_sync)
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
};
|
||||
|
||||
extern TC_LOG *tc_log;
|
||||
|
@ -881,6 +876,7 @@ struct st_savepoint {
|
|||
};
|
||||
|
||||
enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
|
||||
extern const char *xa_state_names[];
|
||||
|
||||
/*
|
||||
A registry for item tree transformations performed during
|
||||
|
@ -1775,7 +1771,7 @@ class multi_delete :public select_result_interceptor
|
|||
ha_rows deleted, found;
|
||||
uint num_of_tables;
|
||||
int error;
|
||||
bool do_delete, transactional_tables, log_delayed, normal_tables;
|
||||
bool do_delete, transactional_tables, normal_tables;
|
||||
public:
|
||||
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
||||
~multi_delete();
|
||||
|
@ -1802,7 +1798,7 @@ class multi_update :public select_result_interceptor
|
|||
uint table_count;
|
||||
Copy_field *copy_field;
|
||||
enum enum_duplicates handle_duplicates;
|
||||
bool do_update, trans_safe, transactional_tables, log_delayed;
|
||||
bool do_update, trans_safe, transactional_tables;
|
||||
|
||||
public:
|
||||
multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
|
||||
|
|
|
@ -36,8 +36,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
TABLE *table;
|
||||
SQL_SELECT *select=0;
|
||||
READ_RECORD info;
|
||||
bool using_limit=limit != HA_POS_ERROR;
|
||||
bool transactional_table, log_delayed, safe_update, const_cond;
|
||||
bool using_limit=limit != HA_POS_ERROR;
|
||||
bool transactional_table, safe_update, const_cond;
|
||||
ha_rows deleted;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
DBUG_ENTER("mysql_delete");
|
||||
|
@ -233,7 +233,6 @@ cleanup:
|
|||
|
||||
delete select;
|
||||
transactional_table= table->file->has_transactions();
|
||||
log_delayed= (transactional_table || table->tmp_table);
|
||||
/*
|
||||
We write to the binary log even if we deleted no row, because maybe the
|
||||
user is using this command to ensure that a table is clean on master *and
|
||||
|
@ -249,11 +248,11 @@ cleanup:
|
|||
if (error <= 0)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed, FALSE);
|
||||
transactional_table, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
error=1;
|
||||
}
|
||||
if (!log_delayed)
|
||||
if (!transactional_table)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
if (transactional_table)
|
||||
|
@ -398,7 +397,7 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
|
|||
uint num_of_tables_arg)
|
||||
: delete_tables(dt), thd(thd_arg), deleted(0), found(0),
|
||||
num_of_tables(num_of_tables_arg), error(0),
|
||||
do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
|
||||
do_delete(0), transactional_tables(0), normal_tables(0)
|
||||
{
|
||||
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
|
||||
}
|
||||
|
@ -445,9 +444,7 @@ multi_delete::initialize_tables(JOIN *join)
|
|||
tbl->no_cache= 1;
|
||||
tbl->used_keys.clear_all();
|
||||
if (tbl->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
else if (tbl->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1;
|
||||
transactional_tables= 1;
|
||||
else
|
||||
normal_tables= 1;
|
||||
}
|
||||
|
@ -670,14 +667,14 @@ bool multi_delete::send_eof()
|
|||
if (error <= 0)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed, FALSE);
|
||||
transactional_tables, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||
local_error=1; // Log write failed: roll back the SQL statement
|
||||
}
|
||||
if (!log_delayed)
|
||||
if (!transactional_tables)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
/* Commit or rollback the current SQL statement */
|
||||
/* Commit or rollback the current SQL statement */
|
||||
if (transactional_tables)
|
||||
if (ha_autocommit_or_rollback(thd,local_error > 0))
|
||||
local_error=1;
|
||||
|
@ -768,7 +765,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
|
|||
|
||||
*fn_ext(path)=0; // Remove the .frm extension
|
||||
error= ha_create_table(path,&create_info,1);
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
end:
|
||||
if (!dont_send_ok)
|
||||
|
@ -779,7 +776,7 @@ end:
|
|||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
thd->tmp_table, FALSE);
|
||||
0, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
send_ok(thd); // This should return record count
|
||||
|
|
|
@ -168,7 +168,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
runs without --log-update or --log-bin).
|
||||
*/
|
||||
bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL));
|
||||
bool transactional_table, log_delayed;
|
||||
bool transactional_table;
|
||||
bool ignore_err= (thd->lex->duplicates == DUP_IGNORE);
|
||||
uint value_count;
|
||||
ulong counter = 1;
|
||||
|
@ -447,7 +447,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
|
||||
transactional_table= table->file->has_transactions();
|
||||
|
||||
log_delayed= (transactional_table || table->tmp_table);
|
||||
if ((info.copied || info.deleted || info.updated) &&
|
||||
(error <= 0 || !transactional_table))
|
||||
{
|
||||
|
@ -456,11 +455,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
if (error <= 0)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed, FALSE);
|
||||
transactional_table, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
error=1;
|
||||
}
|
||||
if (!log_delayed)
|
||||
if (!transactional_table)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
if (transactional_table)
|
||||
|
|
|
@ -105,7 +105,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
char *tdb= thd->db ? thd->db : db; // Result is never null
|
||||
ulong skip_lines= ex->skip_lines;
|
||||
int res;
|
||||
bool transactional_table, log_delayed;
|
||||
bool transactional_table;
|
||||
DBUG_ENTER("mysql_load");
|
||||
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
|
@ -133,7 +133,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
}
|
||||
table= table_list->table;
|
||||
transactional_table= table->file->has_transactions();
|
||||
log_delayed= (transactional_table || table->tmp_table);
|
||||
|
||||
if (!fields.elements)
|
||||
{
|
||||
|
@ -261,7 +260,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
lf_info.handle_dup = handle_duplicates;
|
||||
lf_info.wrote_create_file = 0;
|
||||
lf_info.last_pos_in_file = HA_POS_ERROR;
|
||||
lf_info.log_delayed= log_delayed;
|
||||
lf_info.log_delayed= transactional_table;
|
||||
read_info.set_io_cache_arg((void*) &lf_info);
|
||||
}
|
||||
#endif /*!EMBEDDED_LIBRARY*/
|
||||
|
@ -363,7 +362,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
/* If the file was not empty, wrote_create_file is true */
|
||||
if (lf_info.wrote_create_file)
|
||||
{
|
||||
Delete_file_log_event d(thd, db, log_delayed);
|
||||
Delete_file_log_event d(thd, db, transactional_table);
|
||||
mysql_bin_log.write(&d);
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +374,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||
send_ok(thd,info.copied+info.deleted,0L,name);
|
||||
|
||||
if (!log_delayed)
|
||||
if (!transactional_table)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (mysql_bin_log.is_open())
|
||||
|
@ -385,16 +384,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
block will be logged only after Execute_load_log_event (which is wrong),
|
||||
when read_info is destroyed.
|
||||
*/
|
||||
read_info.end_io_cache();
|
||||
read_info.end_io_cache();
|
||||
if (lf_info.wrote_create_file)
|
||||
{
|
||||
Execute_load_log_event e(thd, db, log_delayed);
|
||||
Execute_load_log_event e(thd, db, transactional_table);
|
||||
mysql_bin_log.write(&e);
|
||||
}
|
||||
}
|
||||
#endif /*!EMBEDDED_LIBRARY*/
|
||||
if (transactional_table)
|
||||
error=ha_autocommit_or_rollback(thd,error);
|
||||
error=ha_autocommit_or_rollback(thd,error);
|
||||
|
||||
err:
|
||||
if (thd->lock)
|
||||
|
@ -402,7 +401,7 @@ err:
|
|||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock=0;
|
||||
}
|
||||
thd->abort_on_warning= 0;
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -732,12 +731,11 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
|
|||
my_free((gptr) buffer,MYF(0)); /* purecov: inspected */
|
||||
error=1;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
/*
|
||||
init_io_cache() will not initialize read_function member
|
||||
if the cache is READ_NET. The reason is explained in
|
||||
mysys/mf_iocache.c. So we work around the problem with a
|
||||
if the cache is READ_NET. So we work around the problem with a
|
||||
manual assignment
|
||||
*/
|
||||
need_end_io_cache = 1;
|
||||
|
|
|
@ -83,6 +83,10 @@ const char *command_name[]={
|
|||
"Error" // Last command number
|
||||
};
|
||||
|
||||
const char *xa_state_names[]={
|
||||
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
|
||||
};
|
||||
|
||||
static char empty_c_string[1]= {0}; // Used for not defined 'db'
|
||||
|
||||
#ifdef __WIN__
|
||||
|
@ -524,6 +528,12 @@ void free_max_user_conn(void)
|
|||
|
||||
sql_command is actually set to SQLCOM_END sometimes
|
||||
so we need the +1 to include it in the array.
|
||||
|
||||
numbers are:
|
||||
0 - read-only query
|
||||
!= 0 - query that may change a table
|
||||
2 - query that returns meaningful ROW_COUNT() -
|
||||
a number of modified rows
|
||||
*/
|
||||
|
||||
char uc_update_queries[SQLCOM_END+1];
|
||||
|
@ -559,7 +569,7 @@ void init_update_queries(void)
|
|||
bool is_update_query(enum enum_sql_command command)
|
||||
{
|
||||
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
|
||||
return uc_update_queries[command] > 0;
|
||||
return uc_update_queries[command];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2153,7 +2163,7 @@ mysql_execute_command(THD *thd)
|
|||
*/
|
||||
if (opt_readonly &&
|
||||
!(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
|
||||
(uc_update_queries[lex->sql_command] > 0))
|
||||
uc_update_queries[lex->sql_command])
|
||||
{
|
||||
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
|
||||
DBUG_RETURN(-1);
|
||||
|
@ -4056,7 +4066,6 @@ create_error:
|
|||
break;
|
||||
}
|
||||
case SQLCOM_XA_START:
|
||||
res= FALSE;
|
||||
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
|
||||
{
|
||||
if (! thd->transaction.xid.eq(&thd->lex->ident))
|
||||
|
@ -4066,7 +4075,7 @@ create_error:
|
|||
}
|
||||
thd->transaction.xa_state=XA_ACTIVE;
|
||||
send_ok(thd);
|
||||
res=0;
|
||||
res=TRUE;
|
||||
break;
|
||||
}
|
||||
if (thd->lex->ident.length > MAXGTRIDSIZE || thd->lex->xa_opt != XA_NONE)
|
||||
|
@ -4076,7 +4085,8 @@ create_error:
|
|||
}
|
||||
if (thd->transaction.xa_state != XA_NOTR)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0));
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xa_state]);
|
||||
break;
|
||||
}
|
||||
if (thd->active_transaction() || thd->locked_tables)
|
||||
|
@ -4091,11 +4101,10 @@ create_error:
|
|||
OPTION_BEGIN);
|
||||
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
send_ok(thd);
|
||||
res=0;
|
||||
res=TRUE;
|
||||
break;
|
||||
case SQLCOM_XA_END:
|
||||
/* fake it */
|
||||
res= FALSE;
|
||||
if (thd->lex->xa_opt != XA_NONE)
|
||||
{ // SUSPEND and FOR MIGRATE are not supported yet. TODO
|
||||
my_error(ER_XAER_INVAL, MYF(0));
|
||||
|
@ -4103,7 +4112,8 @@ create_error:
|
|||
}
|
||||
if (thd->transaction.xa_state != XA_ACTIVE)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0));
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xa_state]);
|
||||
break;
|
||||
}
|
||||
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
||||
|
@ -4113,13 +4123,13 @@ create_error:
|
|||
}
|
||||
thd->transaction.xa_state=XA_IDLE;
|
||||
send_ok(thd);
|
||||
res=0;
|
||||
res=TRUE;
|
||||
break;
|
||||
case SQLCOM_XA_PREPARE:
|
||||
res= FALSE;
|
||||
if (thd->transaction.xa_state != XA_IDLE)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0));
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xa_state]);
|
||||
break;
|
||||
}
|
||||
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
||||
|
@ -4133,7 +4143,7 @@ create_error:
|
|||
thd->transaction.xa_state=XA_NOTR;
|
||||
break;
|
||||
}
|
||||
res=0;
|
||||
res=TRUE;
|
||||
thd->transaction.xa_state=XA_PREPARED;
|
||||
send_ok(thd);
|
||||
break;
|
||||
|
@ -4146,29 +4156,30 @@ create_error:
|
|||
}
|
||||
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
|
||||
{
|
||||
if (res=ha_commit(thd))
|
||||
{
|
||||
my_error(res==1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
|
||||
res= FALSE;
|
||||
}
|
||||
int r;
|
||||
if ((r= ha_commit(thd)))
|
||||
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
|
||||
else
|
||||
{
|
||||
send_ok(thd);
|
||||
res= TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (thd->transaction.xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
|
||||
{
|
||||
if (ha_commit_one_phase(thd, 1))
|
||||
{
|
||||
my_error(ER_XAER_RMERR, MYF(0));
|
||||
res= FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_ok(thd);
|
||||
res= TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res= FALSE;
|
||||
my_error(ER_XAER_RMFAIL, MYF(0));
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xa_state]);
|
||||
break;
|
||||
}
|
||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
||||
|
@ -4185,23 +4196,23 @@ create_error:
|
|||
if (thd->transaction.xa_state != XA_IDLE &&
|
||||
thd->transaction.xa_state != XA_PREPARED)
|
||||
{
|
||||
res= FALSE;
|
||||
my_error(ER_XAER_RMFAIL, MYF(0));
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xa_state]);
|
||||
break;
|
||||
}
|
||||
if (ha_rollback(thd))
|
||||
{
|
||||
my_error(ER_XAER_RMERR, MYF(0));
|
||||
res= FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_ok(thd);
|
||||
res= TRUE;
|
||||
}
|
||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||
thd->transaction.xa_state=XA_NOTR;
|
||||
break;
|
||||
case SQLCOM_XA_RECOVER:
|
||||
res= mysql_xa_recover(thd);
|
||||
res= !mysql_xa_recover(thd);
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0); /* Impossible */
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
/* drop and alter of tables */
|
||||
|
||||
#include "mysql_priv.h"
|
||||
|
@ -274,9 +273,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||
{
|
||||
if (!error)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
tmp_table_deleted && !some_tables_deleted,
|
||||
FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
}
|
||||
|
@ -1286,7 +1283,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||
create_info Create information (like MAX_ROWS)
|
||||
fields List of fields to create
|
||||
keys List of keys to create
|
||||
tmp_table Set to 1 if this is an internal temporary table
|
||||
internal_tmp_table Set to 1 if this is an internal temporary table
|
||||
(From ALTER TABLE)
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -1305,7 +1302,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
List<create_field> &fields,
|
||||
List<Key> &keys,bool tmp_table,
|
||||
List<Key> &keys,bool internal_tmp_table,
|
||||
uint select_field_count)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
|
@ -1374,7 +1371,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||
}
|
||||
|
||||
if (mysql_prepare_table(thd, create_info, fields,
|
||||
keys, tmp_table, db_options, file,
|
||||
keys, internal_tmp_table, db_options, file,
|
||||
key_info_buffer, &key_count,
|
||||
select_field_count))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -1408,7 +1405,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||
if (wait_if_global_read_lock(thd, 0, 1))
|
||||
DBUG_RETURN(error);
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
if (!tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||
{
|
||||
if (!access(path,F_OK))
|
||||
{
|
||||
|
@ -1475,13 +1472,10 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||
}
|
||||
thd->tmp_table_used= 1;
|
||||
}
|
||||
if (!tmp_table && mysql_bin_log.is_open())
|
||||
if (!internal_tmp_table && mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
test(create_info->options &
|
||||
HA_LEX_CREATE_TMP_TABLE),
|
||||
FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
error= FALSE;
|
||||
|
@ -2459,10 +2453,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
test(create_info->options &
|
||||
HA_LEX_CREATE_TMP_TABLE),
|
||||
FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
res= FALSE;
|
||||
|
@ -2572,7 +2563,7 @@ mysql_discard_or_import_tablespace(THD *thd,
|
|||
goto err;
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
err:
|
||||
|
@ -2961,7 +2952,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if (do_send_ok)
|
||||
|
@ -3377,7 +3368,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
goto end_temporary;
|
||||
|
@ -3511,7 +3502,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||
|
|
|
@ -118,7 +118,7 @@ int mysql_update(THD *thd,
|
|||
{
|
||||
bool using_limit= limit != HA_POS_ERROR;
|
||||
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
||||
bool used_key_is_modified, transactional_table, log_delayed;
|
||||
bool used_key_is_modified, transactional_table;
|
||||
bool ignore_err= (thd->lex->duplicates == DUP_IGNORE);
|
||||
int res;
|
||||
int error=0;
|
||||
|
@ -474,7 +474,6 @@ int mysql_update(THD *thd,
|
|||
query_cache_invalidate3(thd, table_list, 1);
|
||||
}
|
||||
|
||||
log_delayed= (transactional_table || table->tmp_table);
|
||||
if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
|
||||
{
|
||||
if (mysql_bin_log.is_open())
|
||||
|
@ -482,11 +481,11 @@ int mysql_update(THD *thd,
|
|||
if (error <= 0)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed, FALSE);
|
||||
transactional_table, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||
error=1; // Rollback update
|
||||
}
|
||||
if (!log_delayed)
|
||||
if (!transactional_table)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
if (transactional_table)
|
||||
|
@ -1001,7 +1000,6 @@ multi_update::initialize_tables(JOIN *join)
|
|||
DBUG_RETURN(1);
|
||||
main_table=join->join_tab->table;
|
||||
trans_safe= transactional_tables= main_table->file->has_transactions();
|
||||
log_delayed= trans_safe || main_table->tmp_table != NO_TMP_TABLE;
|
||||
table_to_update= 0;
|
||||
|
||||
/* Create a temporary table for keys to all tables, except main table */
|
||||
|
@ -1339,17 +1337,13 @@ int multi_update::do_updates(bool from_send_error)
|
|||
goto err;
|
||||
}
|
||||
updated++;
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated != org_updated)
|
||||
{
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1; // Tmp tables forces delay log
|
||||
if (table->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
transactional_tables= 1;
|
||||
else
|
||||
trans_safe= 0; // Can't do safe rollback
|
||||
}
|
||||
|
@ -1370,10 +1364,8 @@ err:
|
|||
|
||||
if (updated != org_updated)
|
||||
{
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1;
|
||||
if (table->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
transactional_tables= 1;
|
||||
else
|
||||
trans_safe= 0;
|
||||
}
|
||||
|
@ -1415,11 +1407,11 @@ bool multi_update::send_eof()
|
|||
if (local_error <= 0)
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed, FALSE);
|
||||
transactional_tables, FALSE);
|
||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||
local_error= 1; // Rollback update
|
||||
}
|
||||
if (!log_delayed)
|
||||
if (!transactional_tables)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue