mirror of
https://github.com/MariaDB/server.git
synced 2025-06-20 21:01:21 +03: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:
@ -1914,7 +1914,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
|
|||||||
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
|
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
|
||||||
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
|
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
|
||||||
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
|
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_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
|
||||||
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
|
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
|
||||||
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
|
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
|
||||||
|
@ -751,7 +751,7 @@ typedef long int32;
|
|||||||
#endif
|
#endif
|
||||||
typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
|
typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
|
||||||
#else
|
#else
|
||||||
error "Neither int or long is of 4 bytes width"
|
#error "Neither int or long is of 4 bytes width"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC)
|
#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;
|
ulong res;
|
||||||
pthread_mutex_lock(L);
|
pthread_mutex_lock(L);
|
||||||
res=V--;
|
res=--V;
|
||||||
pthread_mutex_unlock(L);
|
pthread_mutex_unlock(L);
|
||||||
return res==0;
|
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 *
|
*a *a*a *
|
||||||
explain select * from t1 where v='a';
|
explain select * from t1 where v='a';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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;
|
select v,count(*) from t1 group by v limit 10;
|
||||||
v count(*)
|
v count(*)
|
||||||
a 1
|
a 1
|
||||||
|
@ -1609,14 +1609,14 @@ t2 CREATE TABLE `t2` (
|
|||||||
drop table t2, t1;
|
drop table t2, t1;
|
||||||
show status like "binlog_cache_use";
|
show status like "binlog_cache_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_use 24
|
Binlog_cache_use 150
|
||||||
show status like "binlog_cache_disk_use";
|
show status like "binlog_cache_disk_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_disk_use 0
|
Binlog_cache_disk_use 0
|
||||||
create table t1 (a int) engine=innodb;
|
create table t1 (a int) engine=innodb;
|
||||||
show status like "binlog_cache_use";
|
show status like "binlog_cache_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_use 25
|
Binlog_cache_use 151
|
||||||
show status like "binlog_cache_disk_use";
|
show status like "binlog_cache_disk_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_disk_use 1
|
Binlog_cache_disk_use 1
|
||||||
@ -1625,7 +1625,7 @@ delete from t1;
|
|||||||
commit;
|
commit;
|
||||||
show status like "binlog_cache_use";
|
show status like "binlog_cache_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_use 26
|
Binlog_cache_use 152
|
||||||
show status like "binlog_cache_disk_use";
|
show status like "binlog_cache_disk_use";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Binlog_cache_disk_use 1
|
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 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 239 Query 1 # use `test`; insert into t2 select * from t1
|
||||||
master-bin.000001 327 Xid 1 # xid=7
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
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 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 487 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||||
master-bin.000001 578 Xid 1 # xid=24
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
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 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 578 Query 1 # use `test`; insert into t1 values(7)
|
||||||
master-bin.000001 659 Xid 1 # xid=36
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
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 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 239 Query 1 # use `test`; insert into t2 select * from t1
|
||||||
master-bin.000001 327 Query 1 # use `test`; ROLLBACK
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
reset master;
|
||||||
@ -103,8 +104,11 @@ insert into t1 values(9);
|
|||||||
insert into t2 select * from t1;
|
insert into t2 select * from t1;
|
||||||
show binlog events from 96;
|
show binlog events from 96;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
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 96 Query 1 # use `test`; BEGIN
|
||||||
master-bin.000001 177 Query 1 # use `test`; insert into t2 select * from t1
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
reset master;
|
||||||
@ -113,18 +117,24 @@ begin;
|
|||||||
insert into t2 select * from t1;
|
insert into t2 select * from t1;
|
||||||
show binlog events from 96;
|
show binlog events from 96;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
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 96 Query 1 # use `test`; BEGIN
|
||||||
master-bin.000001 178 Query 1 # use `test`; insert into t2 select * from t1
|
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);
|
insert into t1 values(11);
|
||||||
commit;
|
commit;
|
||||||
show binlog events from 96;
|
show binlog events from 96;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
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 96 Query 1 # use `test`; BEGIN
|
||||||
master-bin.000001 178 Query 1 # use `test`; insert into t2 select * from t1
|
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(10)
|
||||||
master-bin.000001 266 Query 1 # use `test`; BEGIN
|
master-bin.000001 240 Xid 1 # xid=65
|
||||||
master-bin.000001 328 Query 1 # use `test`; insert into t1 values(11)
|
master-bin.000001 267 Query 1 # use `test`; COMMIT
|
||||||
master-bin.000001 410 Xid 1 # xid=67
|
master-bin.000001 330 Query 1 # use `test`; insert into t2 select * from t1
|
||||||
master-bin.000001 433 Query 1 # use `test`; COMMIT
|
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;
|
alter table t2 engine=INNODB;
|
||||||
delete from t1;
|
delete from t1;
|
||||||
delete from t2;
|
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 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 240 Query 1 # use `test`; insert into t2 select * from t1
|
||||||
master-bin.000001 328 Xid 1 # xid=77
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
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 96 Query 1 # use `test`; BEGIN
|
||||||
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(14)
|
master-bin.000001 158 Query 1 # use `test`; insert into t1 values(14)
|
||||||
master-bin.000001 240 Xid 1 # xid=93
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
reset master;
|
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 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 240 Query 1 # use `test`; insert into t1 values(18)
|
||||||
master-bin.000001 322 Xid 1 # xid=104
|
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 t1;
|
||||||
delete from t2;
|
delete from t2;
|
||||||
alter table t2 type=MyISAM;
|
alter table t2 type=MyISAM;
|
||||||
|
@ -18,5 +18,5 @@ max(a)
|
|||||||
8000
|
8000
|
||||||
show slave status;
|
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
|
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;
|
drop table t1;
|
||||||
|
@ -238,15 +238,13 @@ static int berkeley_commit(THD *thd, bool all)
|
|||||||
DBUG_ENTER("berkeley_commit");
|
DBUG_ENTER("berkeley_commit");
|
||||||
DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
|
DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
|
||||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
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
|
#ifndef DBUG_OFF
|
||||||
if (error)
|
if (error)
|
||||||
DBUG_PRINT("error",("error: %d",error));
|
DBUG_PRINT("error",("error: %d",error));
|
||||||
#endif
|
#endif
|
||||||
if (all)
|
|
||||||
trx->all=0;
|
|
||||||
else
|
|
||||||
trx->stmt=0;
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,11 +253,9 @@ static int berkeley_rollback(THD *thd, bool all)
|
|||||||
DBUG_ENTER("berkeley_rollback");
|
DBUG_ENTER("berkeley_rollback");
|
||||||
DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
|
DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
|
||||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||||
int error=txn_abort(all ? trx->all : trx->stmt);
|
DB_TXN **txn= all ? &trx->all : &trx->stmt;
|
||||||
if (all)
|
int error=txn_abort(*txn);
|
||||||
trx->all=0;
|
*txn=0;
|
||||||
else
|
|
||||||
trx->stmt=0;
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1904,7 +1900,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
|
|||||||
if (trx->stmt)
|
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
|
This happens if the thread didn't update any rows
|
||||||
We must in this case commit the work to keep the row locks
|
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;
|
int error=0;
|
||||||
DBUG_ENTER("ha_berkeley::start_stmt");
|
DBUG_ENTER("ha_berkeley::start_stmt");
|
||||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
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()
|
note that trx->stmt may have been already initialized as start_stmt()
|
||||||
is called for *each table* not for each storage engine,
|
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_BTREE_STAT *stat=0;
|
||||||
DB_TXN_STAT *txn_stat_ptr= 0;
|
DB_TXN_STAT *txn_stat_ptr= 0;
|
||||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||||
|
DBUG_ASSERT(trx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Original bdb documentation says:
|
Original bdb documentation says:
|
||||||
|
@ -711,11 +711,23 @@ ha_innobase::update_thd(
|
|||||||
return(0);
|
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);
|
/* register the start of the statement */
|
||||||
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
trans_register_ha(thd, FALSE, &innobase_hton);
|
||||||
trans_register_ha(thd, TRUE, &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
|
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
|
||||||
@ -1464,7 +1476,7 @@ innobase_report_binlog_offset_and_commit(
|
|||||||
|
|
||||||
trx->flush_log_later = TRUE;
|
trx->flush_log_later = TRUE;
|
||||||
|
|
||||||
innobase_commit(thd, trx_handle);
|
innobase_commit(thd, trx_handle);
|
||||||
|
|
||||||
trx->flush_log_later = FALSE;
|
trx->flush_log_later = FALSE;
|
||||||
|
|
||||||
@ -1478,7 +1490,7 @@ void
|
|||||||
innobase_store_binlog_offset_and_flush_log(
|
innobase_store_binlog_offset_and_flush_log(
|
||||||
/*=======================================*/
|
/*=======================================*/
|
||||||
char *binlog_name, /* in: binlog name */
|
char *binlog_name, /* in: binlog name */
|
||||||
longlong offset) /* in: binlog offset */
|
longlong offset) /* in: binlog offset */
|
||||||
{
|
{
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
@ -1520,14 +1532,14 @@ innobase_commit_complete(
|
|||||||
|
|
||||||
if (trx && trx->active_trans) {
|
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);
|
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;
|
static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
|
||||||
|
|
||||||
|
/* list of all available storage engines (of their handlertons) */
|
||||||
handlerton *handlertons[MAX_HA]={0};
|
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[]=
|
struct show_table_type_st sys_table_types[]=
|
||||||
{
|
{
|
||||||
@ -439,6 +446,7 @@ int ha_commit_trans(THD *thd, bool all)
|
|||||||
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
|
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
|
||||||
bool is_real_trans= all || thd->transaction.all.nht == 0;
|
bool is_real_trans= all || thd->transaction.all.nht == 0;
|
||||||
handlerton **ht= trans->ht;
|
handlerton **ht= trans->ht;
|
||||||
|
my_xid xid= thd->transaction.xid.get_my_xid();
|
||||||
DBUG_ENTER("ha_commit_trans");
|
DBUG_ENTER("ha_commit_trans");
|
||||||
#ifdef USING_TRANSACTIONS
|
#ifdef USING_TRANSACTIONS
|
||||||
if (trans->nht)
|
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);
|
statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
|
||||||
}
|
}
|
||||||
if (error || (is_real_trans &&
|
if (error || (is_real_trans && xid &&
|
||||||
(error= !(cookie= tc_log->log(thd,
|
(error= !(cookie= tc_log->log(thd, xid)))))
|
||||||
thd->transaction.xid.quick_get_my_xid())))))
|
|
||||||
{
|
{
|
||||||
ha_rollback_trans(thd, all);
|
ha_rollback_trans(thd, all);
|
||||||
return 1;
|
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;
|
error=ha_commit_one_phase(thd, all) ? cookie ? 2 : 1 : 0;
|
||||||
if (cookie)
|
if (cookie)
|
||||||
tc_log->unlog(cookie, thd->transaction.xid.quick_get_my_xid());
|
tc_log->unlog(cookie, xid);
|
||||||
}
|
}
|
||||||
#endif /* USING_TRANSACTIONS */
|
#endif /* USING_TRANSACTIONS */
|
||||||
DBUG_RETURN(error);
|
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)))
|
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;
|
error= 1;
|
||||||
}
|
}
|
||||||
else
|
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_COMMENT (1L << 16)
|
||||||
#define HA_CREATE_USED_PASSWORD (1L << 17)
|
#define HA_CREATE_USED_PASSWORD (1L << 17)
|
||||||
|
|
||||||
typedef ulong my_xid;
|
typedef ulonglong my_xid;
|
||||||
#define MYSQL_XID_PREFIX "MySQLXid"
|
#define MYSQL_XID_PREFIX "MySQLXid"
|
||||||
#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
|
#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
|
||||||
#define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
|
#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)
|
bool eq(long g, long b, const char *d)
|
||||||
{ return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
|
{ 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(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);
|
set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
|
||||||
*(ulong*)(data+MYSQL_XID_PREFIX_LEN)=server_id;
|
*(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;
|
gtrid_length=MYSQL_XID_GTRID_LEN;
|
||||||
}
|
}
|
||||||
void set(long g, long b, const char *d)
|
void set(long g, long b, const char *d)
|
||||||
@ -233,7 +233,7 @@ struct xid_t {
|
|||||||
void null() { formatID= -1; }
|
void null() { formatID= -1; }
|
||||||
my_xid quick_get_my_xid()
|
my_xid quick_get_my_xid()
|
||||||
{
|
{
|
||||||
return *(ulong*)(data+MYSQL_XID_OFFSET);
|
return *(my_xid*)(data+MYSQL_XID_OFFSET);
|
||||||
}
|
}
|
||||||
my_xid get_my_xid()
|
my_xid get_my_xid()
|
||||||
{
|
{
|
||||||
@ -319,8 +319,11 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct st_thd_trans
|
typedef struct st_thd_trans
|
||||||
{
|
{
|
||||||
|
/* number of entries in the ht[] */
|
||||||
uint nht;
|
uint nht;
|
||||||
|
/* true is not all entries in the ht[] support 2pc */
|
||||||
bool no_2pc;
|
bool no_2pc;
|
||||||
|
/* storage engines that registered themselves for this transaction */
|
||||||
handlerton *ht[MAX_HA];
|
handlerton *ht[MAX_HA];
|
||||||
} THD_TRANS;
|
} THD_TRANS;
|
||||||
|
|
||||||
|
@ -2096,7 +2096,7 @@ void item_user_lock_release(User_level_lock *ull)
|
|||||||
tmp.copy(command, strlen(command), tmp.charset());
|
tmp.copy(command, strlen(command), tmp.charset());
|
||||||
tmp.append(ull->key,ull->key_length);
|
tmp.append(ull->key,ull->key_length);
|
||||||
tmp.append("\")", 2);
|
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
|
qev.error_code=0; // this query is always safe to run on slave
|
||||||
mysql_bin_log.write(&qev);
|
mysql_bin_log.write(&qev);
|
||||||
}
|
}
|
||||||
|
227
sql/log.cc
227
sql/log.cc
@ -75,6 +75,7 @@ handlerton *binlog_init()
|
|||||||
static int binlog_close_connection(THD *thd)
|
static int binlog_close_connection(THD *thd)
|
||||||
{
|
{
|
||||||
IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
|
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);
|
close_cached_file(trans_log);
|
||||||
my_free((gptr)trans_log, MYF(0));
|
my_free((gptr)trans_log, MYF(0));
|
||||||
return 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];
|
IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
|
||||||
DBUG_ENTER("binlog_commit");
|
DBUG_ENTER("binlog_commit");
|
||||||
DBUG_ASSERT(mysql_bin_log.is_open() &&
|
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))
|
if (!my_b_tell(trans_log))
|
||||||
{
|
{
|
||||||
@ -1567,10 +1568,14 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
trans_log->end_of_file= max_binlog_cache_size;
|
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))
|
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;
|
file= trans_log;
|
||||||
}
|
}
|
||||||
else if (trans_log && my_b_tell(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;
|
my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
|
||||||
char flags=LOG_EVENT_BINLOG_CLOSED_F;
|
char flags=LOG_EVENT_BINLOG_CLOSED_F;
|
||||||
my_pwrite(log_file.file, &flags, 1,
|
my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
|
||||||
BIN_LOG_HEADER_SIZE + FLAGS_OFFSET, MYF(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
|
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)
|
(usable size of the first page is smaller because of log header)
|
||||||
there's PAGE control structure for each page
|
there's PAGE control structure for each page
|
||||||
each page (or rather PAGE control structure) can be in one of three
|
each page (or rather PAGE control structure) can be in one of three
|
||||||
states - active, in_sync, pool.
|
states - active, syncing, pool.
|
||||||
there could be only one page in active or in_sync states,
|
there could be only one page in active or syncing states,
|
||||||
but many in pool - pool is fifo queue.
|
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.
|
"active" page - is a page where new xid's are logged.
|
||||||
the page stays active as long as in_sync slot is taken.
|
the page stays active as long as syncing slot is taken.
|
||||||
"in_sync" page is being synced to disk. no new xid can be added to it.
|
"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
|
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
|
the result of such an architecture is a natural "commit grouping" -
|
||||||
a page's condition until the page is synced. when in_sync slot becomes vacant
|
If commits are coming faster than the system can sync, they do not
|
||||||
one of these waiters is awaken to take care of syncing. it syncs the page
|
stall. Instead, all commit that came since the last sync are
|
||||||
and signals all waiters that the page is synced.
|
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
|
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
|
become active again until waiters==0 (that is all waiters from the
|
||||||
previous sync have noticed the sync was completed)
|
previous sync have noticed the sync was completed)
|
||||||
|
|
||||||
note, that the page becomes "dirty" and has to be synced only when
|
note, that the page becomes "dirty" and has to be synced only when a
|
||||||
a new xid is added into it. Removing a xid from a page does not make it
|
new xid is added into it. Removing a xid from a page does not make it
|
||||||
dirty - we don't sync removals to disk.
|
dirty - we don't sync removals to disk.
|
||||||
*/
|
*/
|
||||||
#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
|
#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
|
||||||
@ -2433,35 +2444,38 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
|
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 (fd == -1)
|
||||||
{
|
{
|
||||||
|
if (my_errno != ENOENT)
|
||||||
|
goto err;
|
||||||
if (using_heuristic_recover())
|
if (using_heuristic_recover())
|
||||||
return 1;
|
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)
|
if (fd == -1)
|
||||||
goto err;
|
goto err;
|
||||||
inited=1;
|
inited=1;
|
||||||
file_length=opt_tc_log_size;
|
file_length= opt_tc_log_size;
|
||||||
if (my_chsize(fd, file_length, 0, MYF(MY_WME)))
|
if (my_chsize(fd, file_length, 0, MYF(MY_WME)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inited=1;
|
inited= 1;
|
||||||
crashed=TRUE;
|
crashed= TRUE;
|
||||||
|
sql_print_information("Recovering after a crash");
|
||||||
if (tc_heuristic_recover)
|
if (tc_heuristic_recover)
|
||||||
{
|
{
|
||||||
sql_print_error("Cannot perform automatic crash recovery when "
|
sql_print_error("Cannot perform automatic crash recovery when "
|
||||||
"--tc-heuristic-recover is used");
|
"--tc-heuristic-recover is used");
|
||||||
goto err;
|
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)
|
if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
|
||||||
goto err;
|
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);
|
MAP_NOSYNC|MAP_SHARED, fd, 0);
|
||||||
if (data == MAP_FAILED)
|
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->end=(my_xid *)(pg->start + tc_log_page_size);
|
||||||
pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
|
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=
|
pages[0].size=pages[0].free=
|
||||||
(tc_log_page_size-TC_LOG_HEADER_SIZE)/sizeof(my_xid);
|
(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;
|
pages[npages-1].next=0;
|
||||||
inited=4;
|
inited=4;
|
||||||
|
|
||||||
if (crashed)
|
if (crashed && recover())
|
||||||
{
|
|
||||||
sql_print_error("Recovering after a crash");
|
|
||||||
if (recover())
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
memcpy(data, tc_log_magic, sizeof(tc_log_magic));
|
memcpy(data, tc_log_magic, sizeof(tc_log_magic));
|
||||||
data[sizeof(tc_log_magic)]= total_ha_2pc;
|
data[sizeof(tc_log_magic)]= total_ha_2pc;
|
||||||
my_msync(fd, data, tc_log_page_size, MS_SYNC);
|
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;
|
inited=6;
|
||||||
|
|
||||||
in_sync= 0;
|
syncing= 0;
|
||||||
active=pages;
|
active=pages;
|
||||||
pool=pages+1;
|
pool=pages+1;
|
||||||
pool_last=pages+npages-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:
|
two strategies here:
|
||||||
1. take the first from the pool
|
1. take the first from the pool
|
||||||
2. if there're waiters - take the one with the most free space
|
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;
|
PAGE **p, **best_p=0;
|
||||||
int best_free;
|
int best_free;
|
||||||
|
|
||||||
|
if (syncing)
|
||||||
|
pthread_mutex_lock(&LOCK_pool);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
best_p= p= &pool;
|
best_p= p= &pool;
|
||||||
if ((*p)->waiters == 0)
|
if ((*p)->waiters == 0) // can the first page be used ?
|
||||||
break;
|
break; // yes - take it.
|
||||||
|
|
||||||
best_free=0;
|
best_free=0; // no - trying second strategy
|
||||||
for (p=&(*p)->next; *p; p=&(*p)->next)
|
for (p=&(*p)->next; *p; p=&(*p)->next)
|
||||||
{
|
{
|
||||||
if ((*p)->waiters == 0 && (*p)->free > best_free)
|
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());
|
while ((*best_p == 0 || best_free == 0) && overflow());
|
||||||
|
|
||||||
active=*best_p;
|
active=*best_p;
|
||||||
if (active->free == active->size)
|
if (active->free == active->size) // we've chosen an empty page
|
||||||
{
|
{
|
||||||
tc_log_cur_pages_used++;
|
tc_log_cur_pages_used++;
|
||||||
set_if_bigger(tc_log_max_pages_used, 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;
|
*best_p=(*best_p)->next;
|
||||||
else
|
else
|
||||||
pool_last=*best_p;
|
pool_last=*best_p;
|
||||||
|
|
||||||
|
if (syncing)
|
||||||
|
pthread_mutex_unlock(&LOCK_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TC_LOG_MMAP::overflow()
|
int TC_LOG_MMAP::overflow()
|
||||||
@ -2576,14 +2595,22 @@ int TC_LOG_MMAP::overflow()
|
|||||||
*/
|
*/
|
||||||
tc_log_page_waits++;
|
tc_log_page_waits++;
|
||||||
pthread_cond_wait(&COND_pool, &LOCK_pool);
|
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
|
all access to active page is serialized but it's not a problem, as
|
||||||
assuming that fsync() will be a bottleneck anyway.
|
we're assuming that fsync() will be a main bottleneck.
|
||||||
That is, parallelizing writes to log pages we'll decrease number of threads
|
That is, parallelizing writes to log pages we'll decrease number of
|
||||||
waiting for a page, but then all these threads will be waiting for fsync()
|
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)
|
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);
|
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))
|
while (unlikely(active && active->free == 0))
|
||||||
pthread_cond_wait(&COND_active, &LOCK_active);
|
pthread_cond_wait(&COND_active, &LOCK_active);
|
||||||
|
|
||||||
|
/* no active page ? take one from the pool */
|
||||||
if (active == 0)
|
if (active == 0)
|
||||||
{
|
|
||||||
lock_queue(&LOCK_pool);
|
|
||||||
get_active_from_pool();
|
get_active_from_pool();
|
||||||
unlock_queue(&LOCK_pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
p=active;
|
p=active;
|
||||||
pthread_mutex_lock(&p->lock);
|
pthread_mutex_lock(&p->lock);
|
||||||
|
|
||||||
|
/* searching for an empty slot */
|
||||||
while (*p->ptr)
|
while (*p->ptr)
|
||||||
{
|
{
|
||||||
p->ptr++;
|
p->ptr++;
|
||||||
DBUG_ASSERT(p->ptr < p->end); // because p->free > 0
|
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->ptr++= xid;
|
||||||
p->free--;
|
p->free--;
|
||||||
p->state= DIRTY;
|
p->state= DIRTY;
|
||||||
|
|
||||||
/* to sync or not to sync - this is the question */
|
/* to sync or not to sync - this is the question */
|
||||||
|
pthread_mutex_unlock(&LOCK_active);
|
||||||
pthread_mutex_lock(&LOCK_sync);
|
pthread_mutex_lock(&LOCK_sync);
|
||||||
pthread_mutex_unlock(&p->lock);
|
pthread_mutex_unlock(&p->lock);
|
||||||
|
|
||||||
if (in_sync)
|
if (syncing)
|
||||||
{ // somebody's syncing. let's wait
|
{ // somebody's syncing. let's wait
|
||||||
pthread_mutex_unlock(&LOCK_active);
|
|
||||||
p->waiters++;
|
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);
|
pthread_cond_wait(&p->cond, &LOCK_sync);
|
||||||
} while (p->state == DIRTY && in_sync);
|
|
||||||
p->waiters--;
|
p->waiters--;
|
||||||
err= p->state == ERROR;
|
err= p->state == ERROR;
|
||||||
if (p->state != DIRTY) // page was synced
|
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
|
goto done; // we're done
|
||||||
}
|
}
|
||||||
} // page was not synced! do it now
|
} // page was not synced! do it now
|
||||||
in_sync=p; // place is vacant - take it
|
DBUG_ASSERT(active == p && syncing == 0);
|
||||||
DBUG_ASSERT(active == p);
|
pthread_mutex_lock(&LOCK_active);
|
||||||
active=0;
|
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_cond_broadcast(&COND_active); // in case somebody's waiting
|
||||||
pthread_mutex_unlock(&LOCK_active);
|
pthread_mutex_unlock(&LOCK_active);
|
||||||
pthread_mutex_unlock(&LOCK_sync);
|
pthread_mutex_unlock(&LOCK_sync);
|
||||||
@ -2656,30 +2692,36 @@ int TC_LOG_MMAP::sync()
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
DBUG_ASSERT(in_sync != active);
|
DBUG_ASSERT(syncing != active);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sit down and relax - this can take a while...
|
sit down and relax - this can take a while...
|
||||||
note - no locks are held at this point
|
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);
|
pthread_mutex_lock(&LOCK_pool);
|
||||||
pool_last->next=in_sync;
|
pool_last->next=syncing;
|
||||||
pool_last=in_sync;
|
pool_last=syncing;
|
||||||
in_sync->next=0;
|
syncing->next=0;
|
||||||
in_sync->state= err ? ERROR : POOL;
|
syncing->state= err ? ERROR : POOL;
|
||||||
pthread_cond_broadcast(&in_sync->cond); // signal "sync done"
|
pthread_cond_broadcast(&syncing->cond); // signal "sync done"
|
||||||
pthread_cond_signal(&COND_pool); // in case somebody's waiting
|
pthread_cond_signal(&COND_pool); // in case somebody's waiting
|
||||||
pthread_mutex_unlock(&LOCK_pool);
|
pthread_mutex_unlock(&LOCK_pool);
|
||||||
|
|
||||||
|
/* marking 'syncing' slot free */
|
||||||
pthread_mutex_lock(&LOCK_sync);
|
pthread_mutex_lock(&LOCK_sync);
|
||||||
in_sync=0;
|
syncing=0;
|
||||||
pthread_cond_signal(&active->cond); // wake up a new syncer
|
pthread_cond_signal(&active->cond); // wake up a new syncer
|
||||||
pthread_mutex_unlock(&LOCK_sync);
|
pthread_mutex_unlock(&LOCK_sync);
|
||||||
return err;
|
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)
|
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
|
||||||
{
|
{
|
||||||
PAGE *p=pages+(cookie/tc_log_page_size);
|
PAGE *p=pages+(cookie/tc_log_page_size);
|
||||||
@ -2693,10 +2735,10 @@ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
|
|||||||
p->free++;
|
p->free++;
|
||||||
DBUG_ASSERT(p->free <= p->size);
|
DBUG_ASSERT(p->free <= p->size);
|
||||||
set_if_smaller(p->ptr, x);
|
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);
|
statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
|
||||||
if (p->waiters == 0) // the page is in pool and ready to rock
|
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);
|
pthread_mutex_unlock(&p->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2747,8 +2789,10 @@ int TC_LOG_MMAP::recover()
|
|||||||
*/
|
*/
|
||||||
if (data[sizeof(tc_log_magic)] != total_ha_2pc)
|
if (data[sizeof(tc_log_magic)] != total_ha_2pc)
|
||||||
{
|
{
|
||||||
sql_print_error("For recovery to work all storage engines and binary log "
|
sql_print_error("Recovery failed! You must have enabled "
|
||||||
"must have exactly the same settings as before the crash!");
|
"exactly %d storage engines that support "
|
||||||
|
"two-phase commit protocol",
|
||||||
|
data[sizeof(tc_log_magic)]);
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2793,6 +2837,7 @@ int TC_LOG::using_heuristic_recover()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****** transaction coordinator log for 2pc - binlog() based solution ******/
|
/****** transaction coordinator log for 2pc - binlog() based solution ******/
|
||||||
|
#define TC_LOG_BINLOG MYSQL_LOG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO keep in-memory list of prepared transactions
|
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!
|
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;
|
LOG_INFO log_info, new_log_info;
|
||||||
|
int error;
|
||||||
|
|
||||||
DBUG_ASSERT(total_ha_2pc > 1);
|
DBUG_ASSERT(total_ha_2pc > 1);
|
||||||
|
|
||||||
@ -2821,8 +2867,11 @@ int MYSQL_LOG::open(const char *opt_name)
|
|||||||
let's keep it happy.
|
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 ?
|
goto err; // er ? where's the current entry ?
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(log_file_name, new_log_info.log_file_name))
|
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;
|
char last_event_type=UNKNOWN_EVENT;
|
||||||
IO_CACHE log;
|
IO_CACHE log;
|
||||||
File file;
|
File file;
|
||||||
int error;
|
Log_event *ev=0;
|
||||||
Log_event *ev;
|
Format_description_log_event fdle(BINLOG_VERSION);
|
||||||
Format_description_log_event fdle(4);
|
|
||||||
|
|
||||||
if (! fdle.is_valid())
|
if (! fdle.is_valid())
|
||||||
goto err;
|
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_offset=new_log_info.index_file_offset;
|
||||||
log_info.index_file_start_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);
|
strcpy(log_info.log_file_name, new_log_info.log_file_name);
|
||||||
if (find_next_log(&new_log_info, 1))
|
if ((error= find_next_log(&new_log_info, 1)))
|
||||||
goto err; // er ? where's the current entry ?
|
{
|
||||||
|
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));
|
} while (strcmp(log_file_name, new_log_info.log_file_name));
|
||||||
|
|
||||||
if ((file= open_binlog(&log, log_info.log_file_name, &errmsg)) < 0)
|
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))) &&
|
if (((ev= Log_event::read_log_event(&log, 0, &fdle))) &&
|
||||||
(ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) &&
|
(ev->get_type_code() == FORMAT_DESCRIPTION_EVENT))
|
||||||
(ev->flags & LOG_EVENT_BINLOG_CLOSED_F))
|
{
|
||||||
error=0;
|
if (ev->flags & LOG_EVENT_BINLOG_CLOSED_F)
|
||||||
else
|
error=0;
|
||||||
error= recover(&log, (Format_description_log_event *)ev);
|
else
|
||||||
|
error= recover(&log, (Format_description_log_event *)ev);
|
||||||
|
}
|
||||||
|
// else nothing to do (probably MySQL 4.x binlog)
|
||||||
|
|
||||||
delete ev;
|
delete ev;
|
||||||
end_io_cache(&log);
|
end_io_cache(&log);
|
||||||
@ -2873,15 +2927,22 @@ err:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MYSQL_LOG::close()
|
/* this is called on shutdown, after ha_panic */
|
||||||
|
void TC_LOG_BINLOG::close()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(prepared_xids==0);
|
DBUG_ASSERT(prepared_xids==0);
|
||||||
pthread_mutex_destroy(&LOCK_prep_xids);
|
pthread_mutex_destroy(&LOCK_prep_xids);
|
||||||
pthread_cond_destroy (&COND_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);
|
Xid_log_event xle(thd, xid);
|
||||||
if (xle.write((IO_CACHE*)thd->ha_data[binlog_hton.slot]))
|
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
|
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))
|
if (thread_safe_dec_and_test(prepared_xids, &LOCK_prep_xids))
|
||||||
pthread_cond_signal(&COND_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;
|
Log_event *ev;
|
||||||
HASH xids;
|
HASH xids;
|
||||||
|
@ -288,8 +288,6 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
|
|||||||
server_id= thd->server_id;
|
server_id= thd->server_id;
|
||||||
when= thd->start_time;
|
when= thd->start_time;
|
||||||
cache_stmt= using_trans;
|
cache_stmt= using_trans;
|
||||||
cache_stmt= (using_trans &&
|
|
||||||
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2982,11 +2980,19 @@ void Xid_log_event::pack_info(Protocol *protocol)
|
|||||||
{
|
{
|
||||||
char buf[64], *pos;
|
char buf[64], *pos;
|
||||||
pos= strmov(buf, "xid=");
|
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);
|
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
Xid_log_event::Xid_log_event(const char* buf,
|
||||||
const Format_description_log_event* description_event)
|
const Format_description_log_event* description_event)
|
||||||
:Log_event(buf, description_event)
|
:Log_event(buf, description_event)
|
||||||
@ -3006,14 +3012,15 @@ bool Xid_log_event::write(IO_CACHE* file)
|
|||||||
#ifdef MYSQL_CLIENT
|
#ifdef MYSQL_CLIENT
|
||||||
void Xid_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
|
void Xid_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
|
||||||
{
|
{
|
||||||
char buf[512];
|
|
||||||
if (!short_form)
|
if (!short_form)
|
||||||
{
|
{
|
||||||
|
char buf[64];
|
||||||
|
longlong10_to_str(xid, buf, 10);
|
||||||
|
|
||||||
print_header(file);
|
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 */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
|
@ -305,7 +305,10 @@ struct sql_ex_info
|
|||||||
/*
|
/*
|
||||||
This flag only makes sense for Format_description_log_event.
|
This flag only makes sense for Format_description_log_event.
|
||||||
It is set not when the event is written, but when a binlog file
|
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
|
#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
|
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().
|
fix Format_description_log_event::Format_description_log_event().
|
||||||
Make sure you always insert new types ***BEFORE*** ENUM_END_EVENT.
|
|
||||||
*/
|
*/
|
||||||
UNKNOWN_EVENT= 0, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT,
|
UNKNOWN_EVENT= 0, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT,
|
||||||
INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT,
|
INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT,
|
||||||
APPEND_BLOCK_EVENT, EXEC_LOAD_EVENT, DELETE_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,
|
NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer
|
||||||
allowing multibyte TERMINATED BY etc; both types share the same class
|
sql_ex, allowing multibyte TERMINATED BY etc; both types share the
|
||||||
(Load_log_event)
|
same class (Load_log_event)
|
||||||
*/
|
*/
|
||||||
NEW_LOAD_EVENT, XID_EVENT,
|
NEW_LOAD_EVENT,
|
||||||
RAND_EVENT, USER_VAR_EVENT,
|
RAND_EVENT, USER_VAR_EVENT,
|
||||||
FORMAT_DESCRIPTION_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 */
|
ENUM_END_EVENT /* end marker */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1247,26 +1247,11 @@ SQL_CRYPT *get_crypt_for_frm(void);
|
|||||||
|
|
||||||
/* query_id */
|
/* query_id */
|
||||||
|
|
||||||
typedef ulong query_id_t;
|
typedef ulonglong query_id_t;
|
||||||
extern query_id_t query_id;
|
extern query_id_t query_id;
|
||||||
|
|
||||||
/*
|
/* increment query_id and return it. */
|
||||||
increment query_id and return it.
|
inline query_id_t next_query_id() { return query_id++; }
|
||||||
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some inline functions for more speed */
|
/* 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
|
All global error messages are sent here where the first one is stored
|
||||||
the client
|
for the client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -5601,7 +5601,7 @@ static void mysql_init_variables(void)
|
|||||||
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
|
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
|
||||||
opt_disable_networking= opt_skip_show_db=0;
|
opt_disable_networking= opt_skip_show_db=0;
|
||||||
opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 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_secure_auth= 0;
|
||||||
opt_bootstrap= opt_myisam_log= 0;
|
opt_bootstrap= opt_myisam_log= 0;
|
||||||
mqh_used= 0;
|
mqh_used= 0;
|
||||||
|
@ -5237,10 +5237,10 @@ ER_XAER_NOTA XAE04
|
|||||||
ER_XAER_INVAL XAE05
|
ER_XAER_INVAL XAE05
|
||||||
eng "XAER_INVAL: Invalid arguments (or unsupported command)"
|
eng "XAER_INVAL: Invalid arguments (or unsupported command)"
|
||||||
ER_XAER_RMFAIL XAE07
|
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
|
ER_XAER_OUTSIDE XAE09
|
||||||
eng "XAER_OUTSIDE: Some work is done outside global transaction"
|
eng "XAER_OUTSIDE: Some work is done outside global transaction"
|
||||||
ER_XAER_RMERR XAE03
|
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
|
ER_XA_RBROLLBACK XA100
|
||||||
eng "XA_RBROLLBACK: Transaction branch was rolled back"
|
eng "XA_RBROLLBACK: Transaction branch was rolled back"
|
||||||
|
@ -105,7 +105,13 @@ class TC_LOG_MMAP: public TC_LOG
|
|||||||
File fd;
|
File fd;
|
||||||
uint file_length, npages, inited;
|
uint file_length, npages, inited;
|
||||||
uchar *data;
|
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_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
|
||||||
pthread_cond_t COND_pool, COND_active;
|
pthread_cond_t COND_pool, COND_active;
|
||||||
|
|
||||||
@ -121,17 +127,6 @@ class TC_LOG_MMAP: public TC_LOG
|
|||||||
void get_active_from_pool();
|
void get_active_from_pool();
|
||||||
int sync();
|
int sync();
|
||||||
int overflow();
|
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;
|
extern TC_LOG *tc_log;
|
||||||
@ -881,6 +876,7 @@ struct st_savepoint {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
|
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
|
A registry for item tree transformations performed during
|
||||||
@ -1775,7 +1771,7 @@ class multi_delete :public select_result_interceptor
|
|||||||
ha_rows deleted, found;
|
ha_rows deleted, found;
|
||||||
uint num_of_tables;
|
uint num_of_tables;
|
||||||
int error;
|
int error;
|
||||||
bool do_delete, transactional_tables, log_delayed, normal_tables;
|
bool do_delete, transactional_tables, normal_tables;
|
||||||
public:
|
public:
|
||||||
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
||||||
~multi_delete();
|
~multi_delete();
|
||||||
@ -1802,7 +1798,7 @@ class multi_update :public select_result_interceptor
|
|||||||
uint table_count;
|
uint table_count;
|
||||||
Copy_field *copy_field;
|
Copy_field *copy_field;
|
||||||
enum enum_duplicates handle_duplicates;
|
enum enum_duplicates handle_duplicates;
|
||||||
bool do_update, trans_safe, transactional_tables, log_delayed;
|
bool do_update, trans_safe, transactional_tables;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
|
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;
|
TABLE *table;
|
||||||
SQL_SELECT *select=0;
|
SQL_SELECT *select=0;
|
||||||
READ_RECORD info;
|
READ_RECORD info;
|
||||||
bool using_limit=limit != HA_POS_ERROR;
|
bool using_limit=limit != HA_POS_ERROR;
|
||||||
bool transactional_table, log_delayed, safe_update, const_cond;
|
bool transactional_table, safe_update, const_cond;
|
||||||
ha_rows deleted;
|
ha_rows deleted;
|
||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
DBUG_ENTER("mysql_delete");
|
DBUG_ENTER("mysql_delete");
|
||||||
@ -233,7 +233,6 @@ cleanup:
|
|||||||
|
|
||||||
delete select;
|
delete select;
|
||||||
transactional_table= table->file->has_transactions();
|
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
|
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
|
user is using this command to ensure that a table is clean on master *and
|
||||||
@ -249,11 +248,11 @@ cleanup:
|
|||||||
if (error <= 0)
|
if (error <= 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
log_delayed, FALSE);
|
transactional_table, FALSE);
|
||||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
if (!log_delayed)
|
if (!transactional_table)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
}
|
}
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
@ -398,7 +397,7 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
|
|||||||
uint num_of_tables_arg)
|
uint num_of_tables_arg)
|
||||||
: delete_tables(dt), thd(thd_arg), deleted(0), found(0),
|
: delete_tables(dt), thd(thd_arg), deleted(0), found(0),
|
||||||
num_of_tables(num_of_tables_arg), error(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));
|
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->no_cache= 1;
|
||||||
tbl->used_keys.clear_all();
|
tbl->used_keys.clear_all();
|
||||||
if (tbl->file->has_transactions())
|
if (tbl->file->has_transactions())
|
||||||
log_delayed= transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else if (tbl->tmp_table != NO_TMP_TABLE)
|
|
||||||
log_delayed= 1;
|
|
||||||
else
|
else
|
||||||
normal_tables= 1;
|
normal_tables= 1;
|
||||||
}
|
}
|
||||||
@ -670,11 +667,11 @@ bool multi_delete::send_eof()
|
|||||||
if (error <= 0)
|
if (error <= 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
log_delayed, FALSE);
|
transactional_tables, FALSE);
|
||||||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||||
local_error=1; // Log write failed: roll back the SQL statement
|
local_error=1; // Log write failed: roll back the SQL statement
|
||||||
}
|
}
|
||||||
if (!log_delayed)
|
if (!transactional_tables)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
}
|
}
|
||||||
/* Commit or rollback the current SQL statement */
|
/* Commit or rollback the current SQL statement */
|
||||||
@ -779,7 +776,7 @@ end:
|
|||||||
{
|
{
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
thd->tmp_table, FALSE);
|
0, FALSE);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
send_ok(thd); // This should return record count
|
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).
|
runs without --log-update or --log-bin).
|
||||||
*/
|
*/
|
||||||
bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL));
|
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);
|
bool ignore_err= (thd->lex->duplicates == DUP_IGNORE);
|
||||||
uint value_count;
|
uint value_count;
|
||||||
ulong counter = 1;
|
ulong counter = 1;
|
||||||
@ -447,7 +447,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
|
|
||||||
transactional_table= table->file->has_transactions();
|
transactional_table= table->file->has_transactions();
|
||||||
|
|
||||||
log_delayed= (transactional_table || table->tmp_table);
|
|
||||||
if ((info.copied || info.deleted || info.updated) &&
|
if ((info.copied || info.deleted || info.updated) &&
|
||||||
(error <= 0 || !transactional_table))
|
(error <= 0 || !transactional_table))
|
||||||
{
|
{
|
||||||
@ -456,11 +455,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
if (error <= 0)
|
if (error <= 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
log_delayed, FALSE);
|
transactional_table, FALSE);
|
||||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
if (!log_delayed)
|
if (!transactional_table)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
}
|
}
|
||||||
if (transactional_table)
|
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
|
char *tdb= thd->db ? thd->db : db; // Result is never null
|
||||||
ulong skip_lines= ex->skip_lines;
|
ulong skip_lines= ex->skip_lines;
|
||||||
int res;
|
int res;
|
||||||
bool transactional_table, log_delayed;
|
bool transactional_table;
|
||||||
DBUG_ENTER("mysql_load");
|
DBUG_ENTER("mysql_load");
|
||||||
|
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
@ -133,7 +133,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
transactional_table= table->file->has_transactions();
|
transactional_table= table->file->has_transactions();
|
||||||
log_delayed= (transactional_table || table->tmp_table);
|
|
||||||
|
|
||||||
if (!fields.elements)
|
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.handle_dup = handle_duplicates;
|
||||||
lf_info.wrote_create_file = 0;
|
lf_info.wrote_create_file = 0;
|
||||||
lf_info.last_pos_in_file = HA_POS_ERROR;
|
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);
|
read_info.set_io_cache_arg((void*) &lf_info);
|
||||||
}
|
}
|
||||||
#endif /*!EMBEDDED_LIBRARY*/
|
#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 the file was not empty, wrote_create_file is true */
|
||||||
if (lf_info.wrote_create_file)
|
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);
|
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);
|
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||||
send_ok(thd,info.copied+info.deleted,0L,name);
|
send_ok(thd,info.copied+info.deleted,0L,name);
|
||||||
|
|
||||||
if (!log_delayed)
|
if (!transactional_table)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
@ -388,7 +387,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
read_info.end_io_cache();
|
read_info.end_io_cache();
|
||||||
if (lf_info.wrote_create_file)
|
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);
|
mysql_bin_log.write(&e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -736,8 +735,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
init_io_cache() will not initialize read_function member
|
init_io_cache() will not initialize read_function member
|
||||||
if the cache is READ_NET. The reason is explained in
|
if the cache is READ_NET. So we work around the problem with a
|
||||||
mysys/mf_iocache.c. So we work around the problem with a
|
|
||||||
manual assignment
|
manual assignment
|
||||||
*/
|
*/
|
||||||
need_end_io_cache = 1;
|
need_end_io_cache = 1;
|
||||||
|
@ -83,6 +83,10 @@ const char *command_name[]={
|
|||||||
"Error" // Last command number
|
"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'
|
static char empty_c_string[1]= {0}; // Used for not defined 'db'
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
@ -524,6 +528,12 @@ void free_max_user_conn(void)
|
|||||||
|
|
||||||
sql_command is actually set to SQLCOM_END sometimes
|
sql_command is actually set to SQLCOM_END sometimes
|
||||||
so we need the +1 to include it in the array.
|
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];
|
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)
|
bool is_update_query(enum enum_sql_command command)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
|
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 &&
|
if (opt_readonly &&
|
||||||
!(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
|
!(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");
|
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@ -4056,7 +4066,6 @@ create_error:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_XA_START:
|
case SQLCOM_XA_START:
|
||||||
res= FALSE;
|
|
||||||
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
|
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
|
||||||
{
|
{
|
||||||
if (! thd->transaction.xid.eq(&thd->lex->ident))
|
if (! thd->transaction.xid.eq(&thd->lex->ident))
|
||||||
@ -4066,7 +4075,7 @@ create_error:
|
|||||||
}
|
}
|
||||||
thd->transaction.xa_state=XA_ACTIVE;
|
thd->transaction.xa_state=XA_ACTIVE;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
res=0;
|
res=TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (thd->lex->ident.length > MAXGTRIDSIZE || thd->lex->xa_opt != XA_NONE)
|
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)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (thd->active_transaction() || thd->locked_tables)
|
if (thd->active_transaction() || thd->locked_tables)
|
||||||
@ -4091,11 +4101,10 @@ create_error:
|
|||||||
OPTION_BEGIN);
|
OPTION_BEGIN);
|
||||||
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
res=0;
|
res=TRUE;
|
||||||
break;
|
break;
|
||||||
case SQLCOM_XA_END:
|
case SQLCOM_XA_END:
|
||||||
/* fake it */
|
/* fake it */
|
||||||
res= FALSE;
|
|
||||||
if (thd->lex->xa_opt != XA_NONE)
|
if (thd->lex->xa_opt != XA_NONE)
|
||||||
{ // SUSPEND and FOR MIGRATE are not supported yet. TODO
|
{ // SUSPEND and FOR MIGRATE are not supported yet. TODO
|
||||||
my_error(ER_XAER_INVAL, MYF(0));
|
my_error(ER_XAER_INVAL, MYF(0));
|
||||||
@ -4103,7 +4112,8 @@ create_error:
|
|||||||
}
|
}
|
||||||
if (thd->transaction.xa_state != XA_ACTIVE)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
||||||
@ -4113,13 +4123,13 @@ create_error:
|
|||||||
}
|
}
|
||||||
thd->transaction.xa_state=XA_IDLE;
|
thd->transaction.xa_state=XA_IDLE;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
res=0;
|
res=TRUE;
|
||||||
break;
|
break;
|
||||||
case SQLCOM_XA_PREPARE:
|
case SQLCOM_XA_PREPARE:
|
||||||
res= FALSE;
|
|
||||||
if (thd->transaction.xa_state != XA_IDLE)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
if (!thd->transaction.xid.eq(&thd->lex->ident))
|
||||||
@ -4133,7 +4143,7 @@ create_error:
|
|||||||
thd->transaction.xa_state=XA_NOTR;
|
thd->transaction.xa_state=XA_NOTR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res=0;
|
res=TRUE;
|
||||||
thd->transaction.xa_state=XA_PREPARED;
|
thd->transaction.xa_state=XA_PREPARED;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
break;
|
break;
|
||||||
@ -4146,29 +4156,30 @@ create_error:
|
|||||||
}
|
}
|
||||||
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
|
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
|
||||||
{
|
{
|
||||||
if (res=ha_commit(thd))
|
int r;
|
||||||
{
|
if ((r= ha_commit(thd)))
|
||||||
my_error(res==1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
|
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
|
||||||
res= FALSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
res= TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (thd->transaction.xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
|
if (thd->transaction.xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
|
||||||
{
|
{
|
||||||
if (ha_commit_one_phase(thd, 1))
|
if (ha_commit_one_phase(thd, 1))
|
||||||
{
|
|
||||||
my_error(ER_XAER_RMERR, MYF(0));
|
my_error(ER_XAER_RMERR, MYF(0));
|
||||||
res= FALSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
res= TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
break;
|
||||||
}
|
}
|
||||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
||||||
@ -4185,23 +4196,23 @@ create_error:
|
|||||||
if (thd->transaction.xa_state != XA_IDLE &&
|
if (thd->transaction.xa_state != XA_IDLE &&
|
||||||
thd->transaction.xa_state != XA_PREPARED)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (ha_rollback(thd))
|
if (ha_rollback(thd))
|
||||||
{
|
|
||||||
my_error(ER_XAER_RMERR, MYF(0));
|
my_error(ER_XAER_RMERR, MYF(0));
|
||||||
res= FALSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
res= TRUE;
|
||||||
|
}
|
||||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
|
||||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||||
thd->transaction.xa_state=XA_NOTR;
|
thd->transaction.xa_state=XA_NOTR;
|
||||||
break;
|
break;
|
||||||
case SQLCOM_XA_RECOVER:
|
case SQLCOM_XA_RECOVER:
|
||||||
res= mysql_xa_recover(thd);
|
res= !mysql_xa_recover(thd);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0); /* Impossible */
|
DBUG_ASSERT(0); /* Impossible */
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
|
||||||
/* drop and alter of tables */
|
/* drop and alter of tables */
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
@ -274,9 +273,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||||
tmp_table_deleted && !some_tables_deleted,
|
|
||||||
FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
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)
|
create_info Create information (like MAX_ROWS)
|
||||||
fields List of fields to create
|
fields List of fields to create
|
||||||
keys List of keys 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)
|
(From ALTER TABLE)
|
||||||
|
|
||||||
DESCRIPTION
|
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,
|
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields,
|
List<create_field> &fields,
|
||||||
List<Key> &keys,bool tmp_table,
|
List<Key> &keys,bool internal_tmp_table,
|
||||||
uint select_field_count)
|
uint select_field_count)
|
||||||
{
|
{
|
||||||
char path[FN_REFLEN];
|
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,
|
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,
|
key_info_buffer, &key_count,
|
||||||
select_field_count))
|
select_field_count))
|
||||||
DBUG_RETURN(TRUE);
|
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))
|
if (wait_if_global_read_lock(thd, 0, 1))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
VOID(pthread_mutex_lock(&LOCK_open));
|
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))
|
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;
|
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();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||||
test(create_info->options &
|
|
||||||
HA_LEX_CREATE_TMP_TABLE),
|
|
||||||
FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
@ -2459,10 +2453,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||||
test(create_info->options &
|
|
||||||
HA_LEX_CREATE_TMP_TABLE),
|
|
||||||
FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
res= FALSE;
|
res= FALSE;
|
||||||
@ -2572,7 +2563,7 @@ mysql_discard_or_import_tablespace(THD *thd,
|
|||||||
goto err;
|
goto err;
|
||||||
if (mysql_bin_log.is_open())
|
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);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
@ -2961,7 +2952,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
thd->clear_error();
|
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);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
if (do_send_ok)
|
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())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
thd->clear_error();
|
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);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
goto end_temporary;
|
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())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
thd->clear_error();
|
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);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||||
|
@ -118,7 +118,7 @@ int mysql_update(THD *thd,
|
|||||||
{
|
{
|
||||||
bool using_limit= limit != HA_POS_ERROR;
|
bool using_limit= limit != HA_POS_ERROR;
|
||||||
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
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);
|
bool ignore_err= (thd->lex->duplicates == DUP_IGNORE);
|
||||||
int res;
|
int res;
|
||||||
int error=0;
|
int error=0;
|
||||||
@ -474,7 +474,6 @@ int mysql_update(THD *thd,
|
|||||||
query_cache_invalidate3(thd, table_list, 1);
|
query_cache_invalidate3(thd, table_list, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_delayed= (transactional_table || table->tmp_table);
|
|
||||||
if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
|
if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
@ -482,11 +481,11 @@ int mysql_update(THD *thd,
|
|||||||
if (error <= 0)
|
if (error <= 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
log_delayed, FALSE);
|
transactional_table, FALSE);
|
||||||
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
if (mysql_bin_log.write(&qinfo) && transactional_table)
|
||||||
error=1; // Rollback update
|
error=1; // Rollback update
|
||||||
}
|
}
|
||||||
if (!log_delayed)
|
if (!transactional_table)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
}
|
}
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
@ -1001,7 +1000,6 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
main_table=join->join_tab->table;
|
main_table=join->join_tab->table;
|
||||||
trans_safe= transactional_tables= main_table->file->has_transactions();
|
trans_safe= transactional_tables= main_table->file->has_transactions();
|
||||||
log_delayed= trans_safe || main_table->tmp_table != NO_TMP_TABLE;
|
|
||||||
table_to_update= 0;
|
table_to_update= 0;
|
||||||
|
|
||||||
/* Create a temporary table for keys to all tables, except main table */
|
/* 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;
|
goto err;
|
||||||
}
|
}
|
||||||
updated++;
|
updated++;
|
||||||
if (table->tmp_table != NO_TMP_TABLE)
|
|
||||||
log_delayed= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated != org_updated)
|
if (updated != org_updated)
|
||||||
{
|
{
|
||||||
if (table->tmp_table != NO_TMP_TABLE)
|
|
||||||
log_delayed= 1; // Tmp tables forces delay log
|
|
||||||
if (table->file->has_transactions())
|
if (table->file->has_transactions())
|
||||||
log_delayed= transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else
|
else
|
||||||
trans_safe= 0; // Can't do safe rollback
|
trans_safe= 0; // Can't do safe rollback
|
||||||
}
|
}
|
||||||
@ -1370,10 +1364,8 @@ err:
|
|||||||
|
|
||||||
if (updated != org_updated)
|
if (updated != org_updated)
|
||||||
{
|
{
|
||||||
if (table->tmp_table != NO_TMP_TABLE)
|
|
||||||
log_delayed= 1;
|
|
||||||
if (table->file->has_transactions())
|
if (table->file->has_transactions())
|
||||||
log_delayed= transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else
|
else
|
||||||
trans_safe= 0;
|
trans_safe= 0;
|
||||||
}
|
}
|
||||||
@ -1415,11 +1407,11 @@ bool multi_update::send_eof()
|
|||||||
if (local_error <= 0)
|
if (local_error <= 0)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||||
log_delayed, FALSE);
|
transactional_tables, FALSE);
|
||||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||||
local_error= 1; // Rollback update
|
local_error= 1; // Rollback update
|
||||||
}
|
}
|
||||||
if (!log_delayed)
|
if (!transactional_tables)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user