Skip to content

Commit 059ddfa

Browse files
Tatiana Azundris Nuernbergdahlerlend
Tatiana Azundris Nuernberg
authored andcommitted
Bug#31464539: SET PERSISTED LOG_ERROR_SERVICES WAS RESTORED PREMATURELY
Issue: Setting log_error_services ends the buffered logging phase and begins the normal logging phase, with all and any services the user may have configured. SET PERSISTs are restored immediately before log_error_services is set "traditionally" (i.e. initialized from the command-line value if any, or set to the default otherwise), and the buffered messages are flushed. SET PERSISTed system variables are restored in the order they were set. This lets the user restore a persisted log_error_services first, thereby ending buffered logging, and then restore other system variables, which may result in messages. In that case, those messages are logged right away (as full logging has become available via the earlier setting of log_error_services). The buffered events (which were thrown earlier, but not logged yet) will then be flushed afterwards. This can lead to unexpected ordering of the messages in the log, where messages resulting from restoring PERSISTs are followed by messages logged earlier. For this to happen, buffered logging must be used (e.g. with a loadable log-service like the JSON-logger), the configuration must be set with SET PERSIST (rather than regular configuration files or command-line options), and a variable must be restored after log_error_services and result in messages (either directly to the error-log, or intended for a client but redirected to the error log as no client is attached yet). Solution: If we flag log_error_services as PERSIST_AS_READONLY, it will be restored via the command-line. That means that the value will be set in the same one defined place no matter whether we're restoring a PERSISTed system variable or using an option set from a configuration file or from the command-line. It is important to remember that PERSIST_AS_READONLY guarantees that the value is set on the command-line, and set very early during start-up; there is however no guarantee that the assignment will take effect immediately. In the present patch, using PERSIST_AS_READONLY results in the value taking effect slightly later (rather than earlier) than it would be as from a regular PERSIST. In this case, we need PERSIST_AS_READONLY not because we need an extraordinarily early assignment, but to prevent log_error_services from being restored as a system-variable. It serves the enforce a certain order on the restoring of the configuration during start-up, rather than leaving it to the user. Note: While this takes a very specific configuration to become visible and is perhaps closer to a wart than to a major issue, updating the variable's timestamp (by re-PERSISTing it) to make it the latest to be set (and thus the latest to be restored) should hotfix this: > SET PERSIST log_error_services=@@global.log_error_services; Approved by: Jens Even Blomsoy <[email protected]>
1 parent 0faa432 commit 059ddfa

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

mysql-test/r/log_components_split.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,37 @@ FLUSH ERROR LOGS;
182182
{ "prio" : 3, "subsystem" : "Server", "source_file" : "sql_parse.cc", "function" : "dispatch_command", "msg" : "Parser saw: SELECT \"double dutch!\"", "time" : "1970-01-01T00:00:00.000000Z", "ts" : 0, "thread" : 0, "err_symbol" : "ER_PARSER_TRACE", "SQL_state" : "XX999", "label" : "Note" }
183183
{ "prio" : 0, "subsystem" : "Server", "source_file" : "sql_parse.cc", "function" : "dispatch_command", "msg" : "Parser saw: SELECT \"double dutch!\"", "time" : "1970-01-01T00:00:00.000000Z", "ts" : 0, "thread" : 0, "err_symbol" : "ER_PARSER_TRACE", "SQL_state" : "XX999", "label" : "System" }
184184

185+
#
186+
# Bug#31464539: SET PERSISTED LOG_ERROR_SERVICES WAS RESTORED PREMATURELY
187+
#
188+
189+
# Set up logging via PERSISTs. Order of the PERSISTs matters!
190+
INSTALL COMPONENT "file://component_log_sink_json";
191+
RESET PERSIST;
192+
SET PERSIST log_error_verbosity=3;
193+
SET PERSIST log_error_services="log_filter_internal; log_sink_internal; log_sink_json";
194+
SET PERSIST innodb_monitor_enable=all;
195+
# Restart server and verify log configuration.
196+
# We should also receive a full JSON log of the start-up.
197+
# restart
198+
SELECT @@global.log_error_verbosity;
199+
@@global.log_error_verbosity
200+
3
201+
SELECT @@global.log_error_services;
202+
@@global.log_error_services
203+
log_filter_internal; log_sink_internal; log_sink_json
204+
SELECT @@global.innodb_monitor_enable;
205+
@@global.innodb_monitor_enable
206+
all
207+
# Reset PERSISTs.
208+
RESET PERSIST;
209+
SET GLOBAL log_error_services=DEFAULT;
210+
UNINSTALL COMPONENT "file://component_log_sink_json";
211+
# Log file analysis:
212+
SUCCESS!
213+
# Restart server with all defaults
214+
# restart
215+
185216
###
186217
### done
187218
###

mysql-test/t/log_components_split.test

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,75 @@ EOF
159159
--remove_file $log_json_0_
160160
--remove_file $log_json_1_
161161

162+
163+
--echo
164+
--echo #
165+
--echo # Bug#31464539: SET PERSISTED LOG_ERROR_SERVICES WAS RESTORED PREMATURELY
166+
--echo #
167+
--echo
168+
169+
--echo # Set up logging via PERSISTs. Order of the PERSISTs matters!
170+
INSTALL COMPONENT "file://component_log_sink_json";
171+
RESET PERSIST;
172+
SET PERSIST log_error_verbosity=3;
173+
SET PERSIST log_error_services="log_filter_internal; log_sink_internal; log_sink_json";
174+
SET PERSIST innodb_monitor_enable=all;
175+
176+
--echo # Restart server and verify log configuration.
177+
--echo # We should also receive a full JSON log of the start-up.
178+
--source include/restart_mysqld.inc
179+
180+
SELECT @@global.log_error_verbosity;
181+
SELECT @@global.log_error_services;
182+
SELECT @@global.innodb_monitor_enable;
183+
184+
--echo # Reset PERSISTs.
185+
RESET PERSIST;
186+
SET GLOBAL log_error_services=DEFAULT;
187+
UNINSTALL COMPONENT "file://component_log_sink_json";
188+
189+
--echo # Log file analysis:
190+
let GREP_FILE=$log_json_0_;
191+
192+
perl;
193+
use strict;
194+
use File::stat;
195+
my $file= $ENV{'GREP_FILE'} or die("grep file not set");
196+
197+
my $second_run=0;
198+
my $seen_inno=0;
199+
my $post_inno=0;
200+
201+
open(FILE, "$file") or die("Unable to open $file: $!");
202+
while (<FILE>) {
203+
my $line = $_;
204+
205+
# Ignore everything pre-shutdown
206+
if ($line =~ /"ER_SERVER_SHUTDOWN_COMPLETE"/) {
207+
$second_run=1; }
208+
209+
if ($second_run > 0) {
210+
# Count un-buffered InnoDB messages.
211+
if (!($line =~ /"buffered" : /) && ($line =~ /"subsystem" : "InnoDB"/)) {
212+
$seen_inno++; }
213+
#
214+
if (($line =~ /"buffered" : /) && ($seen_inno > 0)) {
215+
$post_inno++; }}}
216+
close(FILE);
217+
218+
if ($post_inno > 0) {
219+
print "FAIL: $post_inno buffered lines seen after $seen_inno unbuffered ones.\n"; }
220+
else {
221+
print "SUCCESS!\n"; }
222+
EOF
223+
224+
# --remove_file $MYSQLD_DATADIR/mysqld-auto.cnf
225+
--remove_file $log_json_0_
226+
227+
--echo # Restart server with all defaults
228+
--source include/restart_mysqld.inc
229+
230+
162231
--echo
163232
--echo ###
164233
--echo ### done

sql/sys_vars.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,10 +2427,10 @@ static bool fix_log_error_services(sys_var *self MY_ATTRIBUTE((unused)),
24272427
static Sys_var_charptr Sys_log_error_services(
24282428
"log_error_services",
24292429
"Services that should be called when an error event is received",
2430-
GLOBAL_VAR(opt_log_error_services), CMD_LINE(REQUIRED_ARG),
2431-
IN_SYSTEM_CHARSET, DEFAULT(LOG_ERROR_SERVICES_DEFAULT), NO_MUTEX_GUARD,
2432-
NOT_IN_BINLOG, ON_CHECK(check_log_error_services),
2433-
ON_UPDATE(fix_log_error_services));
2430+
PERSIST_AS_READONLY GLOBAL_VAR(opt_log_error_services),
2431+
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
2432+
DEFAULT(LOG_ERROR_SERVICES_DEFAULT), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2433+
ON_CHECK(check_log_error_services), ON_UPDATE(fix_log_error_services));
24342434

24352435
static bool check_log_error_suppression_list(sys_var *self, THD *thd,
24362436
set_var *var) {

0 commit comments

Comments
 (0)