问题描述

现象

5.6 和 5.7 时区设置相同,select now()也显示当前时间

5.7 error log 中时间和当前时间差8小时

screenshot.png

问题分析

5.6 写 error log 函数如下

取时间的函数是localtime_r(&skr, &tm_tmp)

日志中时间和系统时区相同

  1. static void print_buffer_to_file(enum loglevel level, const char *buffer,
  2. size_t length)
  3. {
  4. time_t skr;
  5. struct tm tm_tmp;
  6. struct tm *start;
  7. DBUG_ENTER("print_buffer_to_file");
  8. DBUG_PRINT("enter",("buffer: %s", buffer));
  9. mysql_mutex_lock(&LOCK_error_log);
  10. skr= my_time(0);
  11. localtime_r(&skr, &tm_tmp);
  12. start=&tm_tmp;
  13. fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d %lu [%s] %.*s\n",
  14. start->tm_year + 1900,
  15. start->tm_mon + 1,
  16. start->tm_mday,
  17. start->tm_hour,
  18. start->tm_min,
  19. start->tm_sec,
  20. current_pid,
  21. (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
  22. "Warning" : "Note"),
  23. (int) length, buffer);
  24. fflush(stderr);
  25. mysql_mutex_unlock(&LOCK_error_log);
  26. DBUG_VOID_RETURN;
  27. }

5.7 写 error log 函数如下

取时间的函数是 make_iso8601_timestamp(my_timestamp)

  1. static void print_buffer_to_file(enum loglevel level, const char *buffer,
  2. size_t length)
  3. {
  4. DBUG_ENTER("print_buffer_to_file");
  5. DBUG_PRINT("enter",("buffer: %s", buffer));
  6. char my_timestamp[iso8601_size];
  7. my_thread_id thread_id= 0;
  8. /*
  9. If the thread system is up and running and we're in a connection,
  10. add the connection ID to the log-line, otherwise 0.
  11. */
  12. if (THR_THD_initialized && (current_thd != NULL))
  13. thread_id= current_thd->thread_id();
  14. make_iso8601_timestamp(my_timestamp);
  15. /*
  16. This must work even if the mutex has not been initialized yet.
  17. At that point we should still be single threaded so that it is
  18. safe to write without mutex.
  19. */
  20. if (error_log_initialized)
  21. mysql_mutex_lock(&LOCK_error_log);
  22. if (error_log_buffering)
  23. {
  24. // Logfile not open yet, buffer messages for now.
  25. if (buffered_messages == NULL)
  26. buffered_messages= new (std::nothrow) std::string();
  27. std::ostringstream s;
  28. s << my_timestamp << " " << thread_id;
  29. if (level == ERROR_LEVEL)
  30. s << " [ERROR] ";
  31. else if (level == WARNING_LEVEL)
  32. s << " [Warning] ";
  33. else
  34. s << " [Note] ";
  35. s << buffer << std::endl;
  36. buffered_messages->append(s.str());
  37. }
  38. else
  39. {
  40. fprintf(stderr, "%s %u [%s] %.*s\n",
  41. my_timestamp,
  42. thread_id,
  43. (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
  44. "Warning" : "Note"),
  45. (int) length, buffer);
  46. fflush(stderr);
  47. }
  48. if (error_log_initialized)
  49. mysql_mutex_unlock(&LOCK_error_log);
  50. DBUG_VOID_RETURN;
  51. }

make_iso8601_timestamp 中有代码段如下

参数 opt_log_timestamps 控制时间

  1. if (opt_log_timestamps == 0)
  2. gmtime_r(&seconds, &my_tm);
  3. else
  4. {
  5. localtime_r(&seconds, &my_tm);

opt_log_timestamps 对应 sys_vars.cc 中的 log_timestamps

取值 const char *timestamp_type_names[]= {“UTC”, “SYSTEM”, NullS};

log_timestamps = 0 时,日志中是 UTC 时区

log_timestamps = 1 时,日志中是 SYSTEM 时区

5.7 默认 log_timestamps = 0

5.7 error log 使用系统时区

set global log_timestamps = 1;