measuring replication speed

Developed In: Perl — Contributed by: Giuseppe Maxia

Based on an idea of Jeremy Zawodny (High Performance MySQL, O'Reilly, 2004, chapter 7), this script measures the replication speed between masetr and slave with a precision of some microseconds. You can see a longer explanation in this article (the data charmer's blog)
Giuseppe Maxia
Perl
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;
  5. use DBI;
  6. use Time::HiRes qw/ usleep gettimeofday tv_interval/;
  7. use English qw( -no_match_vars );
  8.  
  9. my $username1 = 'user1';
  10. my $password1 = 'user2';
  11. my $username2 = 'pass1';
  12. my $password2 = 'pass2';
  13. my $host1 = 'host_IP1';
  14. my $host2 = 'host_IP2';
  15. my $port1 = '3306';
  16. my $port2 = '3306';
  17.  
  18. my $dbh1=DBI->connect("dbi:mysql:test;host=$host1;port=$port1",
  19. $username1, $password1,
  20. {RaiseError => 1})
  21. or die "Can't connect: $DBI::errstr\n";
  22.  
  23. my $dbh2=DBI->connect("dbi:mysql:test;host=$host2;port=$port2",
  24. $username2, $password2,
  25. {RaiseError => 1})
  26. or die "Can't connect: $DBI::errstr\n";
  27.  
  28. my $loops = 10; # how many times we loop (with size increase)
  29. my $num_of_inserts = 5; # how many records we insert for each loop
  30. my $initial_blob_size = 1_000; # how big is the record we start with
  31. my $replica_db = 'test'; # which database we use for testing
  32.  
  33. my $master_dbh = $dbh1;
  34. my $slave_dbh = $dbh2;
  35.  
  36. my ( $exists_db ) = $master_dbh->selectrow_array(qq{SHOW DATABASES LIKE '$replica_db'});
  37. unless ($exists_db) {
  38. eval {$master_dbh->do(qq{CREATE DATABASE $replica_db}) };
  39. if ( $EVAL_ERROR ) {
  40. die "execution error $DBI::errstr\n";
  41. }
  42. }
  43.  
  44. #
  45. # creating the measurement table
  46. #
  47. $master_dbh->do( qq{
  48. CREATE DATABASE IF NOT EXISTS $replica_db});
  49. $master_dbh->do( qq{
  50. USE $replica_db } );
  51. $master_dbh->do( qq{
  52. DROP TABLE IF EXISTS replica_speed });
  53. $master_dbh->do( qq{
  54. CREATE TABLE replica_speed (
  55. id int(11) NOT NULL auto_increment,
  56. insert_sequence int not null,
  57. seconds bigint(20) default NULL,
  58. microseconds bigint(20) default NULL,
  59. ts timestamp(14) NOT NULL,
  60. big_one longtext,
  61. PRIMARY KEY (`id`),
  62. KEY insert_sequence (insert_sequence)
  63. )
  64. } );
  65. };
  66. if ($EVAL_ERROR) {
  67. die "table creation error $DBI::errstr\n";
  68. }
  69.  
  70. #
  71. # give some time to the table creation to get replicated
  72. #
  73. usleep(200_000);
  74. my $insert_query = qq{
  75. INSERT INTO $replica_db.replica_speed
  76. (insert_sequence, seconds, microseconds, big_one)
  77. VALUES ( ?, ?, ?, ?) };
  78. my $retrieve_query = qq{
  79. SELECT seconds, microseconds, id, insert_sequence
  80. FROM $replica_db.replica_speed
  81. WHERE insert_sequence = ?
  82. };
  83. my $slave_sth = $slave_dbh->prepare($retrieve_query);
  84.  
  85. #
  86. # checking max_allowed_packet to make sure that we are not
  87. # exceeding the limits
  88. #
  89. my ( undef, $master_max_allowed_packet) = $master_dbh->selectrow_array(
  90. qq{ SHOW VARIABLES LIKE "max_allowed_packet" } );
  91.  
  92. my ( undef, $slave_max_allowed_packet) = $slave_dbh->selectrow_array(
  93. qq{ SHOW VARIABLES LIKE "max_allowed_packet" } );
  94.  
  95. my $max_allowed_packet = $master_max_allowed_packet;
  96. if ( $slave_max_allowed_packet < $master_max_allowed_packet) {
  97. $max_allowed_packet = $slave_max_allowed_packet;
  98. }
  99. my @results = ();
  100.  
  101. LOOP:
  102. for my $loopcount (0 .. $loops )
  103. {
  104. usleep(200_000);
  105.  
  106. #
  107. # let's start with an empty table
  108. #
  109. $master_dbh->do( qq{ TRUNCATE $replica_db.replica_speed } );
  110.  
  111. my $size = $initial_blob_size * ($loopcount || 1);
  112. if ($size > $max_allowed_packet) {
  113. $size = $max_allowed_packet - 1000;
  114. }
  115. my $master_insert_time = 0.0;
  116. my $big_blob = 'a' x $size;
  117.  
  118. #
  119. # inserting several records in the master
  120. #
  121. for my $sequence (1 .. $num_of_inserts ) {
  122. my ( $secs, $msecs ) = gettimeofday();
  123. $master_dbh->do($insert_query, undef, $sequence, $secs, $msecs, $big_blob);
  124. $master_insert_time = tv_interval( [$secs, $msecs], [gettimeofday()]);
  125. }
  126. my $replication_delay = 0;
  127. my $total_retrieval_time = 0;
  128. my $baredelay = undef;
  129.  
  130. #
  131. # fetching data from the slave
  132. #
  133. RETRIEVAL:
  134. while ( ! $replication_delay ) # waiting for data to arrive from master to slave
  135. {
  136. my $retrieval_start_time = [gettimeofday()];
  137. $slave_sth->execute( $num_of_inserts);
  138. my $info = $slave_sth->fetchrow_arrayref();
  139. my $retrieval_stop_time = [gettimeofday()];
  140. my $retrieval_time = 0.0;
  141. $retrieval_time = tv_interval(
  142. $retrieval_start_time,
  143. $retrieval_stop_time);
  144. next RETRIEVAL unless $info->[0];
  145.  
  146. #
  147. # retrieval time is counted only after a successful fetch
  148. #
  149. $total_retrieval_time += $retrieval_time;
  150. $replication_delay = tv_interval( [$info->[0], $info->[1]], $retrieval_stop_time);
  151. $baredelay = $replication_delay - $total_retrieval_time - $master_insert_time;
  152. printf "%4d %5d %5d %12d %12d %12d %12d\n",
  153. $loopcount, $info->[2], $info->[3] , $info->[0] , $info->[1] ,
  154. $retrieval_stop_time->[0], $retrieval_stop_time->[1];
  155. }
  156.  
  157. push @results,
  158. {
  159. data_size => $size,
  160. master_insert_time => $master_insert_time,
  161. slave_retrieval_time => $total_retrieval_time,
  162. replication_time => $replication_delay,
  163. bare_replication_time => $baredelay,
  164. }
  165. }
  166.  
  167. #
  168. # displaying results
  169. #
  170. my @header_sizes = qw(4 9 13 15 16 9);
  171. my @headers = ('loop', 'data size', 'master insert', 'slave retrieval', 'total repl. time', 'bare time');
  172. printf "%s %s %s %s %s %s\n" , @headers;
  173. printf "%s %s %s %s %s %s\n" , map { '-' x $_ } @header_sizes;
  174. my $count = 0;
  175. for my $res (@results)
  176. {
  177. printf "%4d %9d %13.6f %15.6f %16.6f %9.6f\n" , ++$count,
  178. map { $res->{$_} }
  179. qw/data_size master_insert_time slave_retrieval_time replication_time bare_replication_time/;
  180. }
  181.  

Current Tags

You must be logged in to tag this tool

No Comments yet

Votes

  • Rated 4.75 out of 5
Rated 4.75 out of 5 with 4 votes cast.
You must be logged in to vote.

Watches

1 members are watching this tool
You must be logged in to track this tool.

Provide Feedback

Please note:
HTML will be purified, but we allow for a number of HTML tags so that you have the flexibility to decorate your comment text to some extent. The comments allow the following HTML tags:

strong, b, em, blockquote, a, code, pre

To put code into your comment, simply encapsulate your code with
[code language="XXX"][/code], where XXX is any common language, for instance "PHP", "SQL", "C", etc.



You must be logged in to comment