summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in2
-rw-r--r--include/my_global.h2
-rw-r--r--include/my_pthread.h2
-rw-r--r--[-rwxr-xr-x]libmysqld/libmysqld.rc0
-rw-r--r--[-rwxr-xr-x]libmysqld/resource.h0
-rw-r--r--mysql-test/r/bdb.result2
-rw-r--r--mysql-test/r/innodb.result6
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result42
-rw-r--r--mysql-test/r/rpl_relayrotate.result2
-rw-r--r--sql/ha_berkeley.cc26
-rw-r--r--sql/ha_innodb.cc48
-rw-r--r--sql/handler.cc23
-rw-r--r--sql/handler.h11
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/log.cc231
-rw-r--r--sql/log_event.cc25
-rw-r--r--sql/log_event.h23
-rw-r--r--sql/mysql_priv.h21
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/share/errmsg.txt4
-rw-r--r--sql/sql_class.h24
-rw-r--r--sql/sql_delete.cc25
-rw-r--r--sql/sql_insert.cc7
-rw-r--r--sql/sql_load.cc22
-rw-r--r--sql/sql_parse.cc67
-rw-r--r--sql/sql_table.cc33
-rw-r--r--sql/sql_update.cc22
27 files changed, 378 insertions, 302 deletions
diff --git a/configure.in b/configure.in
index 5c16dd2063c..5cae7d17adc 100644
--- a/configure.in
+++ b/configure.in
@@ -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 \
diff --git a/include/my_global.h b/include/my_global.h
index e8f93ee5d7a..9eb22c3561c 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -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)
diff --git a/include/my_pthread.h b/include/my_pthread.h
index f108bc02801..10556b49c41 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -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;
}
diff --git a/libmysqld/libmysqld.rc b/libmysqld/libmysqld.rc
index 5b6142faddf..5b6142faddf 100755..100644
--- a/libmysqld/libmysqld.rc
+++ b/libmysqld/libmysqld.rc
diff --git a/libmysqld/resource.h b/libmysqld/resource.h
index f770fe490a6..f770fe490a6 100755..100644
--- a/libmysqld/resource.h
+++ b/libmysqld/resource.h
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 3570f74065e..68252106a5f 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -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
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 9a6c69b7bea..e7be5fc5823 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -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
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
index 015d2a87a53..9fe44b30ac0 100644
--- a/mysql-test/r/mix_innodb_myisam_binlog.result
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -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;
diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result
index c9403792dfd..9b53d10771f 100644
--- a/mysql-test/r/rpl_relayrotate.result
+++ b/mysql-test/r/rpl_relayrotate.result
@@ -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;
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 160adf13e40..ed7fcce197d 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -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))
{
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b8aa2df0fa9..60127a0b67c 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -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);
diff --git a/sql/handler.cc b/sql/handler.cc
index 99d295246be..85720b2beff 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -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
diff --git a/sql/handler.h b/sql/handler.h
index c53fe86504b..d11c3eb6c0e 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -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;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index aba53b9b397..10de6b3c5e1 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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);
}
diff --git a/sql/log.cc b/sql/log.cc
index 336e49b02da..7e629ffc97f 100644
--- a/sql/log.cc
+++ b/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".
-
- 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.
+ becomes "syncing".
+
+ 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;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index e6375d85c6d..be1098ae578 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -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 */
diff --git a/sql/log_event.h b/sql/log_event.h
index d69ec935258..bc950441ab0 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -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 */
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e33ac689d5a..f2e1862ef3e 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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 */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3b451331289..24ca493deb1 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index a952b5649c4..5eb6cbde0a7 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -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"
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 8c8880799b1..93c27df0515 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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,
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index f4c5b0f8b59..a9d76052982 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -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
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c9faa516724..a28ac012ff4 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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)
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 21dd2318504..82e8ac25052 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -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;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f0559204559..6462ae6be9c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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 */
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8662eb63ce6..eb2717a36cf 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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));
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 9613e39d403..d31a0c428cd 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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;
}