3869 Dmitry Shulga 2012-02-09
Fixed bug#11748899 (formerly known as 37666): Event set to DISABLED status
and ON COMPLETION NOT PRESERVE is deleted at server restart.
From user's point of view when user creates event with default on
completion behaviour and its status is DISABLE,
then after restart of server this event is deleted from schema.
The problem was that during loading of events from mysql.event table
server was used incorrect implementation for 'on completion' behaviour, i.e.
if event loaded from table had status value DISABLE and ON COMPLETION flag
was equal to true, then server deleted event from table without regarding
status value. The root of cause was at the method Events::load_events_from_db()
(this method called by Events::init() during server startup initialization).
This method reads every event from table and creates event object from
loaded data. When event that was disabled and had the default ON COMPLETION
NOT PRESERVE behaviour was loaded from mysql.event table into
object of class Event_queue_element then it had attribute
on_completion=Event_parse_data::ON_COMPLETION_DROP and
status = Event_parse_data::DISABLED. After loading completed it tries to
put event into queue but this failed because status == DISABLE.
Then this event dropped since the condition
'else if (drop_on_completion)' is true.
The solution is to change wrong condition. The right condition is
to check for value of attribute Event_queue_element::dropped that is set
to true when event really should dropped because it expired
(this check is implemented at
Event_queue_element::compute_next_execution_time).
This patch also fix a bug related to deleting of expired events from
mysql.event table after server restart.
The problem was that if there was an event that expired at time T
and before that time came server was down and started again after
time T was elapsed then expired event will never be removed.
The reason for this bug is that when the server initializes scheduler
structures at Events::init() it's never calls set_time()
for new THD object and so THD::start_time attribute has value 0.
Afterwards when events is loaded from mysql.event table into memory
server checks end_time of event against value of
current_thd->query_start() that returns value 0. As a result expired
events is considered as expired.
The solution is to call THD::set_time() for new created THD at Events::init.
@ mysql-test/r/events_restart.result
Added testcase's results of patch for bug#11748899.
@ mysql-test/t/events_restart.test
Added testcase of patch for bug#11748899.
modified:
mysql-test/r/events_restart.result
mysql-test/t/events_restart.test
sql/events.cc
3868 Venkata Sidagam 2012-02-09
Bug #11755870-47704: HASH INDEX ON VARCHAR PREFIX NOT WORKING CORRECTLY.
Brief description: Insert some rows to MEMORY table with HASH key on varchar field.
A select on specific existing tuple is showing empty set.
Problem Analysis/solution: In hp_key_cmp() when the seg->type == HA_KEYTYPE_VARTEXT1
the char_length_rec is the length of pos string and it is compared with key string for
char_length_key bytes. Here both char_length_rec and char_length_key will be of different
values when we have hash index on column prefix. So the comparition is failing and
the result set is empty.
So the fix is, if char_length_rec has more value than the char_length_key make
char_length_rec as same as char_length_key
@ storage/heap/hp_hash.c
Modified hp_key_cmp() function
modified:
mysql-test/r/heap.result
mysql-test/t/heap.test
storage/heap/hp_hash.c
=== modified file 'mysql-test/r/events_restart.result'
--- a/mysql-test/r/events_restart.result 2011-05-04 12:59:24 +0000
+++ b/mysql-test/r/events_restart.result 2012-02-09 14:56:44 +0000
@@ -65,3 +65,26 @@ select @@event_scheduler;
ON
drop table execution_log;
drop database events_test;
+#
+# Test for bug#11748899 -- EVENT SET TO DISABLED AND ON COMPLETION
+# NOT PRESERVE IS DELETED AT SERVER
+#
+SELECT @@event_scheduler;
+@@event_scheduler
+ON
+USE test;
+DROP EVENT IF EXISTS e1;
+CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO SELECT 1;
+SHOW EVENTS;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+test e1 root@localhost SYSTEM RECURRING # 1 SECOND # # DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
+"Now we restart the server"
+USE test;
+SELECT @@event_scheduler;
+@@event_scheduler
+ON
+SHOW EVENTS;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+test e1 root@localhost SYSTEM RECURRING # 1 SECOND # # DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
+DROP EVENT e1;
+# end test for bug#11748899
=== modified file 'mysql-test/t/events_restart.test'
--- a/mysql-test/t/events_restart.test 2011-05-04 12:59:24 +0000
+++ b/mysql-test/t/events_restart.test 2012-02-09 14:56:44 +0000
@@ -106,3 +106,26 @@ let $wait_condition=
select count(*) = 0 from information_schema.processlist
where db='events_test' and command = 'Connect' and user=current_user();
--source include/wait_condition.inc
+
+--echo #
+--echo # Test for bug#11748899 -- EVENT SET TO DISABLED AND ON COMPLETION
+--echo # NOT PRESERVE IS DELETED AT SERVER
+--echo #
+SELECT @@event_scheduler;
+USE test;
+--disable_warnings
+DROP EVENT IF EXISTS e1;
+--enable_warnings
+CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO SELECT 1;
+--replace_column 6 # 9 # 10 #
+SHOW EVENTS;
+
+--echo "Now we restart the server"
+--source include/restart_mysqld.inc
+USE test;
+SELECT @@event_scheduler;
+--replace_column 6 # 9 # 10 #
+SHOW EVENTS;
+DROP EVENT e1;
+
+--echo # end test for bug#11748899
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2011-10-27 08:43:56 +0000
+++ b/sql/events.cc 2012-02-09 14:56:44 +0000
@@ -825,7 +825,16 @@ Events::init(my_bool opt_noacl_or_bootst
*/
thd->thread_stack= (char*) &thd;
thd->store_globals();
-
+ /*
+ Set current time for the thread that handles events.
+ Current time is stored in data member start_time of THD class.
+ Subsequently, this value is used to check whether event was expired
+ when make loading events from storage. Check for event expiration time
+ is done at Event_queue_element::compute_next_execution_time() where
+ event's status set to Event_parse_data::DISABLED and dropped flag set
+ to true if event was expired.
+ */
+ thd->set_time();
/*
We will need Event_db_repository anyway, even if the scheduler is
disabled - to perform events DDL.
@@ -1109,7 +1118,6 @@ Events::load_events_from_db(THD *thd)
{
Event_queue_element *et;
bool created;
- bool drop_on_completion;
if (!(et= new Event_queue_element))
goto end;
@@ -1124,9 +1132,6 @@ Events::load_events_from_db(THD *thd)
delete et;
goto end;
}
- drop_on_completion= (et->on_completion ==
- Event_parse_data::ON_COMPLETION_DROP);
-
if (event_queue->create_event(thd, et, &created))
{
@@ -1136,7 +1141,7 @@ Events::load_events_from_db(THD *thd)
}
if (created)
count++;
- else if (drop_on_completion)
+ else if (et->dropped)
{
/*
If not created, a stale event - drop if immediately if
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (Dmitry.Shulga:3868 to 3869) Bug#11748899 | Dmitry Shulga | 10 Feb |