diff --git a/mysql-test/suite/binlog/r/binlog_rotate_perf.result b/mysql-test/suite/binlog/r/binlog_rotate_perf.result new file mode 100644 index 00000000000..d2ebc56e228 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_rotate_perf.result @@ -0,0 +1,945 @@ +connect conn1,localhost,root,,test; +reset master; +create database test_rotate_db; +use test_rotate_db; +#currrent engine=myisam +show binary logs; +Log_name File_size +master-bin.000001 # +CREATE TABLE t1_myisam (c1 INT) ENGINE=myisam; +insert into t1_myisam values(0),(1); +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # +flush logs; +flush logs; +flush logs; +# left times= 99 +flush logs; +flush logs; +flush logs; +# left times= 98 +flush logs; +flush logs; +flush logs; +# left times= 97 +flush logs; +flush logs; +flush logs; +# left times= 96 +flush logs; +flush logs; +flush logs; +# left times= 95 +flush logs; +flush logs; +flush logs; +# left times= 94 +flush logs; +flush logs; +flush logs; +# left times= 93 +flush logs; +flush logs; +flush logs; +# left times= 92 +flush logs; +flush logs; +flush logs; +# left times= 91 +flush logs; +flush logs; +flush logs; +# left times= 90 +flush logs; +flush logs; +flush logs; +# left times= 89 +flush logs; +flush logs; +flush logs; +# left times= 88 +flush logs; +flush logs; +flush logs; +# left times= 87 +flush logs; +flush logs; +flush logs; +# left times= 86 +flush logs; +flush logs; +flush logs; +# left times= 85 +flush logs; +flush logs; +flush logs; +# left times= 84 +flush logs; +flush logs; +flush logs; +# left times= 83 +flush logs; +flush logs; +flush logs; +# left times= 82 +flush logs; +flush logs; +flush logs; +# left times= 81 +flush logs; +flush logs; +flush logs; +# left times= 80 +flush logs; +flush logs; +flush logs; +# left times= 79 +flush logs; +flush logs; +flush logs; +# left times= 78 +flush logs; +flush logs; +flush logs; +# left times= 77 +flush logs; +flush logs; +flush logs; +# left times= 76 +flush logs; +flush logs; +flush logs; +# left times= 75 +flush logs; +flush logs; +flush logs; +# left times= 74 +flush logs; +flush logs; +flush logs; +# left times= 73 +flush logs; +flush logs; +flush logs; +# left times= 72 +flush logs; +flush logs; +flush logs; +# left times= 71 +flush logs; +flush logs; +flush logs; +# left times= 70 +flush logs; +flush logs; +flush logs; +# left times= 69 +flush logs; +flush logs; +flush logs; +# left times= 68 +flush logs; +flush logs; +flush logs; +# left times= 67 +flush logs; +flush logs; +flush logs; +# left times= 66 +flush logs; +flush logs; +flush logs; +# left times= 65 +flush logs; +flush logs; +flush logs; +# left times= 64 +flush logs; +flush logs; +flush logs; +# left times= 63 +flush logs; +flush logs; +flush logs; +# left times= 62 +flush logs; +flush logs; +flush logs; +# left times= 61 +flush logs; +flush logs; +flush logs; +# left times= 60 +flush logs; +flush logs; +flush logs; +# left times= 59 +flush logs; +flush logs; +flush logs; +# left times= 58 +flush logs; +flush logs; +flush logs; +# left times= 57 +flush logs; +flush logs; +flush logs; +# left times= 56 +flush logs; +flush logs; +flush logs; +# left times= 55 +flush logs; +flush logs; +flush logs; +# left times= 54 +flush logs; +flush logs; +flush logs; +# left times= 53 +flush logs; +flush logs; +flush logs; +# left times= 52 +flush logs; +flush logs; +flush logs; +# left times= 51 +flush logs; +flush logs; +flush logs; +# left times= 50 +flush logs; +flush logs; +flush logs; +# left times= 49 +flush logs; +flush logs; +flush logs; +# left times= 48 +flush logs; +flush logs; +flush logs; +# left times= 47 +flush logs; +flush logs; +flush logs; +# left times= 46 +flush logs; +flush logs; +flush logs; +# left times= 45 +flush logs; +flush logs; +flush logs; +# left times= 44 +flush logs; +flush logs; +flush logs; +# left times= 43 +flush logs; +flush logs; +flush logs; +# left times= 42 +flush logs; +flush logs; +flush logs; +# left times= 41 +flush logs; +flush logs; +flush logs; +# left times= 40 +flush logs; +flush logs; +flush logs; +# left times= 39 +flush logs; +flush logs; +flush logs; +# left times= 38 +flush logs; +flush logs; +flush logs; +# left times= 37 +flush logs; +flush logs; +flush logs; +# left times= 36 +flush logs; +flush logs; +flush logs; +# left times= 35 +flush logs; +flush logs; +flush logs; +# left times= 34 +flush logs; +flush logs; +flush logs; +# left times= 33 +flush logs; +flush logs; +flush logs; +# left times= 32 +flush logs; +flush logs; +flush logs; +# left times= 31 +flush logs; +flush logs; +flush logs; +# left times= 30 +flush logs; +flush logs; +flush logs; +# left times= 29 +flush logs; +flush logs; +flush logs; +# left times= 28 +flush logs; +flush logs; +flush logs; +# left times= 27 +flush logs; +flush logs; +flush logs; +# left times= 26 +flush logs; +flush logs; +flush logs; +# left times= 25 +flush logs; +flush logs; +flush logs; +# left times= 24 +flush logs; +flush logs; +flush logs; +# left times= 23 +flush logs; +flush logs; +flush logs; +# left times= 22 +flush logs; +flush logs; +flush logs; +# left times= 21 +flush logs; +flush logs; +flush logs; +# left times= 20 +flush logs; +flush logs; +flush logs; +# left times= 19 +flush logs; +flush logs; +flush logs; +# left times= 18 +flush logs; +flush logs; +flush logs; +# left times= 17 +flush logs; +flush logs; +flush logs; +# left times= 16 +flush logs; +flush logs; +flush logs; +# left times= 15 +flush logs; +flush logs; +flush logs; +# left times= 14 +flush logs; +flush logs; +flush logs; +# left times= 13 +flush logs; +flush logs; +flush logs; +# left times= 12 +flush logs; +flush logs; +flush logs; +# left times= 11 +flush logs; +flush logs; +flush logs; +# left times= 10 +flush logs; +flush logs; +flush logs; +# left times= 9 +flush logs; +flush logs; +flush logs; +# left times= 8 +flush logs; +flush logs; +flush logs; +# left times= 7 +flush logs; +flush logs; +flush logs; +# left times= 6 +flush logs; +flush logs; +flush logs; +# left times= 5 +flush logs; +flush logs; +flush logs; +# left times= 4 +flush logs; +flush logs; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000291 # +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +master-bin.000004 # +master-bin.000005 # +master-bin.000006 # +master-bin.000007 # +master-bin.000008 # +master-bin.000009 # +master-bin.000010 # +master-bin.000011 # +master-bin.000012 # +master-bin.000013 # +master-bin.000014 # +master-bin.000015 # +master-bin.000016 # +master-bin.000017 # +master-bin.000018 # +master-bin.000019 # +master-bin.000020 # +master-bin.000021 # +master-bin.000022 # +master-bin.000023 # +master-bin.000024 # +master-bin.000025 # +master-bin.000026 # +master-bin.000027 # +master-bin.000028 # +master-bin.000029 # +master-bin.000030 # +master-bin.000031 # +master-bin.000032 # +master-bin.000033 # +master-bin.000034 # +master-bin.000035 # +master-bin.000036 # +master-bin.000037 # +master-bin.000038 # +master-bin.000039 # +master-bin.000040 # +master-bin.000041 # +master-bin.000042 # +master-bin.000043 # +master-bin.000044 # +master-bin.000045 # +master-bin.000046 # +master-bin.000047 # +master-bin.000048 # +master-bin.000049 # +master-bin.000050 # +master-bin.000051 # +master-bin.000052 # +master-bin.000053 # +master-bin.000054 # +master-bin.000055 # +master-bin.000056 # +master-bin.000057 # +master-bin.000058 # +master-bin.000059 # +master-bin.000060 # +master-bin.000061 # +master-bin.000062 # +master-bin.000063 # +master-bin.000064 # +master-bin.000065 # +master-bin.000066 # +master-bin.000067 # +master-bin.000068 # +master-bin.000069 # +master-bin.000070 # +master-bin.000071 # +master-bin.000072 # +master-bin.000073 # +master-bin.000074 # +master-bin.000075 # +master-bin.000076 # +master-bin.000077 # +master-bin.000078 # +master-bin.000079 # +master-bin.000080 # +master-bin.000081 # +master-bin.000082 # +master-bin.000083 # +master-bin.000084 # +master-bin.000085 # +master-bin.000086 # +master-bin.000087 # +master-bin.000088 # +master-bin.000089 # +master-bin.000090 # +master-bin.000091 # +master-bin.000092 # +master-bin.000093 # +master-bin.000094 # +master-bin.000095 # +master-bin.000096 # +master-bin.000097 # +master-bin.000098 # +master-bin.000099 # +master-bin.000100 # +master-bin.000101 # +master-bin.000102 # +master-bin.000103 # +master-bin.000104 # +master-bin.000105 # +master-bin.000106 # +master-bin.000107 # +master-bin.000108 # +master-bin.000109 # +master-bin.000110 # +master-bin.000111 # +master-bin.000112 # +master-bin.000113 # +master-bin.000114 # +master-bin.000115 # +master-bin.000116 # +master-bin.000117 # +master-bin.000118 # +master-bin.000119 # +master-bin.000120 # +master-bin.000121 # +master-bin.000122 # +master-bin.000123 # +master-bin.000124 # +master-bin.000125 # +master-bin.000126 # +master-bin.000127 # +master-bin.000128 # +master-bin.000129 # +master-bin.000130 # +master-bin.000131 # +master-bin.000132 # +master-bin.000133 # +master-bin.000134 # +master-bin.000135 # +master-bin.000136 # +master-bin.000137 # +master-bin.000138 # +master-bin.000139 # +master-bin.000140 # +master-bin.000141 # +master-bin.000142 # +master-bin.000143 # +master-bin.000144 # +master-bin.000145 # +master-bin.000146 # +master-bin.000147 # +master-bin.000148 # +master-bin.000149 # +master-bin.000150 # +master-bin.000151 # +master-bin.000152 # +master-bin.000153 # +master-bin.000154 # +master-bin.000155 # +master-bin.000156 # +master-bin.000157 # +master-bin.000158 # +master-bin.000159 # +master-bin.000160 # +master-bin.000161 # +master-bin.000162 # +master-bin.000163 # +master-bin.000164 # +master-bin.000165 # +master-bin.000166 # +master-bin.000167 # +master-bin.000168 # +master-bin.000169 # +master-bin.000170 # +master-bin.000171 # +master-bin.000172 # +master-bin.000173 # +master-bin.000174 # +master-bin.000175 # +master-bin.000176 # +master-bin.000177 # +master-bin.000178 # +master-bin.000179 # +master-bin.000180 # +master-bin.000181 # +master-bin.000182 # +master-bin.000183 # +master-bin.000184 # +master-bin.000185 # +master-bin.000186 # +master-bin.000187 # +master-bin.000188 # +master-bin.000189 # +master-bin.000190 # +master-bin.000191 # +master-bin.000192 # +master-bin.000193 # +master-bin.000194 # +master-bin.000195 # +master-bin.000196 # +master-bin.000197 # +master-bin.000198 # +master-bin.000199 # +master-bin.000200 # +master-bin.000201 # +master-bin.000202 # +master-bin.000203 # +master-bin.000204 # +master-bin.000205 # +master-bin.000206 # +master-bin.000207 # +master-bin.000208 # +master-bin.000209 # +master-bin.000210 # +master-bin.000211 # +master-bin.000212 # +master-bin.000213 # +master-bin.000214 # +master-bin.000215 # +master-bin.000216 # +master-bin.000217 # +master-bin.000218 # +master-bin.000219 # +master-bin.000220 # +master-bin.000221 # +master-bin.000222 # +master-bin.000223 # +master-bin.000224 # +master-bin.000225 # +master-bin.000226 # +master-bin.000227 # +master-bin.000228 # +master-bin.000229 # +master-bin.000230 # +master-bin.000231 # +master-bin.000232 # +master-bin.000233 # +master-bin.000234 # +master-bin.000235 # +master-bin.000236 # +master-bin.000237 # +master-bin.000238 # +master-bin.000239 # +master-bin.000240 # +master-bin.000241 # +master-bin.000242 # +master-bin.000243 # +master-bin.000244 # +master-bin.000245 # +master-bin.000246 # +master-bin.000247 # +master-bin.000248 # +master-bin.000249 # +master-bin.000250 # +master-bin.000251 # +master-bin.000252 # +master-bin.000253 # +master-bin.000254 # +master-bin.000255 # +master-bin.000256 # +master-bin.000257 # +master-bin.000258 # +master-bin.000259 # +master-bin.000260 # +master-bin.000261 # +master-bin.000262 # +master-bin.000263 # +master-bin.000264 # +master-bin.000265 # +master-bin.000266 # +master-bin.000267 # +master-bin.000268 # +master-bin.000269 # +master-bin.000270 # +master-bin.000271 # +master-bin.000272 # +master-bin.000273 # +master-bin.000274 # +master-bin.000275 # +master-bin.000276 # +master-bin.000277 # +master-bin.000278 # +master-bin.000279 # +master-bin.000280 # +master-bin.000281 # +master-bin.000282 # +master-bin.000283 # +master-bin.000284 # +master-bin.000285 # +master-bin.000286 # +master-bin.000287 # +master-bin.000288 # +master-bin.000289 # +master-bin.000290 # +master-bin.000291 # +reset master; +# left times= 3 +flush logs; +flush logs; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000003 # +reset master; +# left times= 2 +flush logs; +flush logs; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000003 # +reset master; +# left times= 1 +flush logs; +flush logs; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000003 # +reset master; +# left times= 0 +# [engine=myisam] after first loop_times=0, show master logs results +show binary logs; +Log_name File_size +master-bin.000001 # +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # +flush logs; +flush logs; +#begin to restart mysqld current loop_times=10 +# restart +# left restart times= 9 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=9 +# restart +# left restart times= 8 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=8 +# restart +# left restart times= 7 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=7 +# restart +# left restart times= 6 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=6 +# restart +# left restart times= 5 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=5 +# restart +# left restart times= 4 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=4 +# restart +# left restart times= 3 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=3 +# restart +# left restart times= 2 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=2 +# restart +# left restart times= 1 +flush logs; +flush logs; +#begin to restart mysqld current loop_times=1 +# restart +# left restart times= 0 +# [engine=myisam] after second loop_times=0, show master logs results +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +master-bin.000004 # +master-bin.000005 # +master-bin.000006 # +master-bin.000007 # +master-bin.000008 # +master-bin.000009 # +master-bin.000010 # +master-bin.000011 # +master-bin.000012 # +master-bin.000013 # +master-bin.000014 # +master-bin.000015 # +master-bin.000016 # +master-bin.000017 # +master-bin.000018 # +master-bin.000019 # +master-bin.000020 # +master-bin.000021 # +master-bin.000022 # +master-bin.000023 # +master-bin.000024 # +master-bin.000025 # +master-bin.000026 # +master-bin.000027 # +master-bin.000028 # +master-bin.000029 # +master-bin.000030 # +master-bin.000031 # +# ======= now try to change the log-bin config for mysqld ======= +#begin to restart mysqld +# restart: --log-bin=new_log_bin +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +master-bin.000004 # +master-bin.000005 # +master-bin.000006 # +master-bin.000007 # +master-bin.000008 # +master-bin.000009 # +master-bin.000010 # +master-bin.000011 # +master-bin.000012 # +master-bin.000013 # +master-bin.000014 # +master-bin.000015 # +master-bin.000016 # +master-bin.000017 # +master-bin.000018 # +master-bin.000019 # +master-bin.000020 # +master-bin.000021 # +master-bin.000022 # +master-bin.000023 # +master-bin.000024 # +master-bin.000025 # +master-bin.000026 # +master-bin.000027 # +master-bin.000028 # +master-bin.000029 # +master-bin.000030 # +master-bin.000031 # +new_log_bin.000001 # +flush logs; +flush logs; +flush logs; +# left times= 9 +flush logs; +flush logs; +flush logs; +# left times= 8 +flush logs; +flush logs; +flush logs; +# left times= 7 +flush logs; +flush logs; +flush logs; +# left times= 6 +flush logs; +flush logs; +flush logs; +# left times= 5 +flush logs; +flush logs; +flush logs; +# left times= 4 +flush logs; +flush logs; +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +master-bin.000004 # +master-bin.000005 # +master-bin.000006 # +master-bin.000007 # +master-bin.000008 # +master-bin.000009 # +master-bin.000010 # +master-bin.000011 # +master-bin.000012 # +master-bin.000013 # +master-bin.000014 # +master-bin.000015 # +master-bin.000016 # +master-bin.000017 # +master-bin.000018 # +master-bin.000019 # +master-bin.000020 # +master-bin.000021 # +master-bin.000022 # +master-bin.000023 # +master-bin.000024 # +master-bin.000025 # +master-bin.000026 # +master-bin.000027 # +master-bin.000028 # +master-bin.000029 # +master-bin.000030 # +master-bin.000031 # +new_log_bin.000001 # +new_log_bin.000002 # +new_log_bin.000003 # +new_log_bin.000004 # +new_log_bin.000005 # +new_log_bin.000006 # +new_log_bin.000007 # +new_log_bin.000008 # +new_log_bin.000009 # +new_log_bin.000010 # +new_log_bin.000011 # +new_log_bin.000012 # +new_log_bin.000013 # +new_log_bin.000014 # +new_log_bin.000015 # +new_log_bin.000016 # +new_log_bin.000017 # +new_log_bin.000018 # +new_log_bin.000019 # +new_log_bin.000020 # +new_log_bin.000021 # +reset master; +# left times= 3 +flush logs; +flush logs; +reset master; +# left times= 2 +flush logs; +flush logs; +reset master; +# left times= 1 +flush logs; +flush logs; +reset master; +# left times= 0 +# [engine=myisam] after third loop_times=0, show master logs results +show binary logs; +Log_name File_size +new_log_bin.000001 # +drop database test_rotate_db; diff --git a/mysql-test/suite/binlog/r/show_concurrent_rotate.result b/mysql-test/suite/binlog/r/show_concurrent_rotate.result new file mode 100644 index 00000000000..cee5de33973 --- /dev/null +++ b/mysql-test/suite/binlog/r/show_concurrent_rotate.result @@ -0,0 +1,16 @@ +connect con1,localhost,root,,; +FLUSH LOGS; +FLUSH LOGS; +FLUSH LOGS; +SET DEBUG_SYNC= "at_after_lock_index WAIT_FOR con1_go"; +SHOW BINARY LOGS; +connect con2,localhost,root,,; +RESET MASTER; +FLUSH LOGS; +SET DEBUG_SYNC= "now SIGNAL con1_go"; +connection con1; +# The correct result must consists of two records +Log_name File_size +master-bin.000001 # +master-bin.000002 # +SET debug_sync = 'reset'; diff --git a/mysql-test/suite/binlog/t/binlog_rotate_perf.test b/mysql-test/suite/binlog/t/binlog_rotate_perf.test new file mode 100644 index 00000000000..74c91feca97 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_rotate_perf.test @@ -0,0 +1,102 @@ +# ==== Purpose ==== +# +# functional test for open_binlog call using when +# +# flush log reset master/slave called +# +# ==== Related ==== +# +# TXSQL feature 67 binlog rotate perf optimization + +let $engine= myisam; + +--source include/have_binlog_format_row.inc +--connect(conn1,localhost,root,,test) + +reset master; +create database test_rotate_db; +use test_rotate_db; +--echo #currrent engine=$engine +# Create a new table +--replace_column 2 # +show binary logs; +--eval CREATE TABLE t1_$engine (c1 INT) ENGINE=$engine +--eval insert into t1_$engine values(0),(1) + +# do batch flush and show +let $loop_times= 100; +--source include/show_master_status.inc +while ($loop_times) { + flush logs; + flush logs; + if ($loop_times < 5) + { + --source include/show_master_status.inc + if ($loop_times == 4) + { + --source include/show_binary_logs.inc + } + reset master; + } + if ($loop_times >= 5) + { + flush logs; + } + + # + dec $loop_times; + --echo # left times= $loop_times +} +--echo # [engine=$engine] after first loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + +# do batch flush and show with restart mysql +--source include/show_master_status.inc +let $loop_times= 10; +while ($loop_times) { + flush logs; + flush logs; + --echo #begin to restart mysqld current loop_times=$loop_times + --source include/restart_mysqld.inc + # + dec $loop_times; + --echo # left restart times= $loop_times +} +--echo # [engine=$engine] after second loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + + +# try to change the log-bin configs and restart +--echo # ======= now try to change the log-bin config for mysqld ======= +--let $restart_parameters="--log-bin=new_log_bin" +--echo #begin to restart mysqld +--source include/restart_mysqld.inc +--let $restart_parameters= "" + +--source include/show_binary_logs.inc +let $loop_times= 10; +while ($loop_times) { + flush logs; + flush logs; + if ($loop_times < 5) + { + if ($loop_times == 4) + { + --source include/show_binary_logs.inc + } + reset master; + } + if ($loop_times >= 5) + { + flush logs; + } + + # + dec $loop_times; + --echo # left times= $loop_times +} +--echo # [engine=$engine] after third loop_times=$loop_times, show master logs results +--source include/show_binary_logs.inc + +##cleanup +drop database test_rotate_db; diff --git a/mysql-test/suite/binlog/t/show_concurrent_rotate.test b/mysql-test/suite/binlog/t/show_concurrent_rotate.test new file mode 100644 index 00000000000..79d36c30a86 --- /dev/null +++ b/mysql-test/suite/binlog/t/show_concurrent_rotate.test @@ -0,0 +1,24 @@ +--source include/have_debug.inc +--source include/have_debug_sync.inc +# mere to limit it run rate +--source include/have_binlog_format_row.inc + +connect(con1,localhost,root,,); +FLUSH LOGS; +FLUSH LOGS; +FLUSH LOGS; + +SET DEBUG_SYNC= "at_after_lock_index WAIT_FOR con1_go"; +--send SHOW BINARY LOGS + +connect(con2,localhost,root,,); +RESET MASTER; +FLUSH LOGS; +SET DEBUG_SYNC= "now SIGNAL con1_go"; + +--connection con1 +--echo # The correct result must consists of two records +--replace_column 2 # +--reap + +SET debug_sync = 'reset'; diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 3794d2fe4dc..b1f67375903 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -496,10 +496,17 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, { /* If we change from WRITE_CACHE to READ_CACHE, assume that everything - after the current positions should be ignored + after the current positions should be ignored. In other cases we + update end_of_file as it may have changed since last init. */ - if (info->type == WRITE_CACHE && type == READ_CACHE) - info->end_of_file=my_b_tell(info); + if (type == READ_CACHE) + { + if (info->type == WRITE_CACHE) + info->end_of_file= my_b_tell(info); + else + info->end_of_file= mysql_file_seek(info->file, 0L, MY_SEEK_END, + MYF(0)); + } /* flush cache if we want to reuse it */ if (!clear_cache && my_b_flush_io_cache(info,1)) DBUG_RETURN(1); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 88cdefed3e9..a058c366f60 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -31,6 +31,7 @@ #include "debug_sync.h" #include "semisync_master.h" #include "semisync_slave.h" +#include "mysys_err.h" enum enum_gtid_until_state { GTID_UNTIL_NOT_DONE, @@ -866,44 +867,88 @@ static int send_heartbeat_event(binlog_send_info *info, struct binlog_file_entry { binlog_file_entry *next; - char *name; + LEX_CSTRING name; + my_off_t size; }; +/** + Read all binary logs and return as a list + + @param memroot Use this for mem_root calls + @param reverse If set filenames returned in latest first order (reverse + order than in the index file) + @param already_locked If set, index file is already locked. + + @return 0 error + # pointer to list + + @notes + index_file is always unlocked at return +*/ + static binlog_file_entry * -get_binlog_list(MEM_ROOT *memroot) +get_binlog_list(MEM_ROOT *memroot, bool reverse= true, + bool already_locked= false) { IO_CACHE *index_file; - char fname[FN_REFLEN]; - size_t length; - binlog_file_entry *current_list= NULL, *e; + char *fname, *buff, *end_pos; + binlog_file_entry *current_list= NULL, *current_link= NULL, *e; DBUG_ENTER("get_binlog_list"); if (!mysql_bin_log.is_open()) { + if (already_locked) + mysql_bin_log.unlock_index(); my_error(ER_NO_BINARY_LOGGING, MYF(0)); DBUG_RETURN(NULL); } - - mysql_bin_log.lock_index(); + if (!already_locked) + mysql_bin_log.lock_index(); index_file=mysql_bin_log.get_index_file(); reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0); - /* The file ends with EOF or empty line */ - while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1) + if (!(buff= (char*) alloc_root(memroot, + (size_t) (index_file->end_of_file+1)))) + goto err; + if (my_b_read(index_file, (uchar*) buff, (size_t) index_file->end_of_file)) { - --length; /* Remove the newline */ - if (!(e= (binlog_file_entry *)alloc_root(memroot, sizeof(*e))) || - !(e->name= strmake_root(memroot, fname, length))) - { - mysql_bin_log.unlock_index(); - DBUG_RETURN(NULL); - } - e->next= current_list; - current_list= e; + my_error(EE_READ, MYF(ME_ERROR_LOG), my_filename(index_file->file), + my_errno); + goto err; } + buff[index_file->end_of_file]= 0; // For strchr mysql_bin_log.unlock_index(); + /* The file ends with EOF or empty line */ + for (fname= buff; + (end_pos= strchr(fname, '\n')) && (end_pos - fname) > 1; + fname= end_pos+1) + { + end_pos[0]= '\0'; // remove the newline + if (!(e= (binlog_file_entry *) alloc_root(memroot, sizeof(*e)))) + DBUG_RETURN(NULL); + if (reverse) + { + e->next= current_list; + current_list= e; + } + else + { + e->next= NULL; + if (!current_link) + current_list= e; + else + current_link->next= e; + current_link= e; + } + e->name.str= fname; + e->name.length= (size_t) (end_pos - fname); + } DBUG_RETURN(current_list); + +err: + mysql_bin_log.unlock_index(); + DBUG_RETURN(0); } @@ -1228,8 +1273,7 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name, char buf[FN_REFLEN]; init_alloc_root(&memroot, "gtid_find_binlog_file", - 10*(FN_REFLEN+sizeof(binlog_file_entry)), - 0, MYF(MY_THREAD_SPECIFIC)); + 8192, 0, MYF(MY_THREAD_SPECIFIC)); if (!(list= get_binlog_list(&memroot))) { errormsg= "Out of memory while looking for GTID position in binlog"; @@ -1255,7 +1299,7 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name, Read the Gtid_list_log_event at the start of the binlog file to get the binlog state. */ - if (normalize_binlog_name(buf, list->name, false)) + if (normalize_binlog_name(buf, list->name.str, false)) { errormsg= "Failed to determine binlog file name while looking for " "GTID position in binlog"; @@ -4193,17 +4237,25 @@ void show_binlogs_get_fields(THD *thd, List *field_list) @retval FALSE success @retval TRUE failure + + @notes + We only keep the index locked while reading all file names as + if there are 1000+ binary logs, there can be a serious impact + as getting the file sizes can take some notable time (up to 20 seconds + has been reported) and we don't want to block log rotations for that long. */ + +#define BINLOG_INDEX_RETRY_COUNT 5 + bool show_binlogs(THD* thd) { - IO_CACHE *index_file; LOG_INFO cur; - File file; - char fname[FN_REFLEN]; + MEM_ROOT mem_root; + binlog_file_entry *list; List field_list; - size_t length; - size_t cur_dir_len; Protocol *protocol= thd->protocol; + uint retry_count= 0; + size_t cur_dir_len; DBUG_ENTER("show_binlogs"); if (!mysql_bin_log.is_open()) @@ -4217,55 +4269,71 @@ bool show_binlogs(THD* thd) if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - + + init_alloc_root(&mem_root, "binlog_file_list", 8192, 0, + MYF(MY_THREAD_SPECIFIC)); +retry: + /* + The current mutex handling here is to ensure we get the current log position + and all the log files from the index in sync without any index rotation + in between. + */ mysql_mutex_lock(mysql_bin_log.get_log_lock()); mysql_bin_log.lock_index(); - index_file=mysql_bin_log.get_index_file(); - - mysql_bin_log.raw_get_current_log(&cur); // dont take mutex - mysql_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK + mysql_bin_log.raw_get_current_log(&cur); + mysql_mutex_unlock(mysql_bin_log.get_log_lock()); + /* The following call unlocks lock_index */ + if ((!(list= get_binlog_list(&mem_root, false, true)))) + goto err; + + DEBUG_SYNC(thd, "at_after_lock_index"); + + // the 1st loop computes the sizes; If stat() fails, then retry cur_dir_len= dirname_length(cur.log_file_name); - - reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0); - - /* The file ends with EOF or empty line */ - while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1) + for (binlog_file_entry *cur_link= list; cur_link; cur_link= cur_link->next) { - size_t dir_len; - ulonglong file_length= 0; // Length if open fails - fname[--length] = '\0'; // remove the newline + const char *fname= cur_link->name.str; + size_t dir_len= dirname_length(fname); + size_t length= cur_link->name.length- dir_len; - protocol->prepare_for_resend(); - dir_len= dirname_length(fname); - length-= dir_len; - protocol->store(fname + dir_len, length, &my_charset_bin); + /* Skip directory name as we shouldn't include this in the result */ + cur_link->name.str+= dir_len; + cur_link->name.length-= dir_len; if (!(strncmp(fname+dir_len, cur.log_file_name+cur_dir_len, length))) - file_length= cur.pos; /* The active log, use the active position */ + cur_link->size= cur.pos; /* The active log, use the active position */ else { - /* this is an old log, open it and find the size */ - if ((file= mysql_file_open(key_file_binlog, - fname, O_RDONLY | O_SHARE | O_BINARY, - MYF(0))) >= 0) + MY_STAT stat_info; + if (mysql_file_stat(key_file_binlog, fname, &stat_info, MYF(0))) + cur_link->size= stat_info.st_size; + else { - file_length= (ulonglong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0)); - mysql_file_close(file, MYF(0)); + if (retry_count++ < BINLOG_INDEX_RETRY_COUNT) + { + free_root(&mem_root, MYF(MY_MARK_BLOCKS_FREE)); + goto retry; + } + cur_link->size= 0; } } - protocol->store(file_length); + } + + for (binlog_file_entry *cur_link= list; cur_link; cur_link= cur_link->next) + { + protocol->prepare_for_resend(); + protocol->store(cur_link->name.str, cur_link->name.length, &my_charset_bin); + protocol->store((ulonglong) cur_link->size); if (protocol->write()) goto err; } - if (unlikely(index_file->error == -1)) - goto err; - mysql_bin_log.unlock_index(); + free_root(&mem_root, MYF(0)); my_eof(thd); DBUG_RETURN(FALSE); err: - mysql_bin_log.unlock_index(); + free_root(&mem_root, MYF(0)); DBUG_RETURN(TRUE); }