3
# This is a test with uses many processes to test a MySQL server.
5
# Tested a lot with: --threads=30
7
$opt_loop_count=500000; # Change this to make test harder/easier
9
##################### Standard benchmark inits ##############################
17
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
18
$opt_lock_tables=$opt_debug=$opt_skip_drop=$opt_fast=$opt_force=0;
21
$opt_select=6;$opt_join=4;
22
$opt_select_count=$opt_join_count=0;
23
$opt_update=1;$opt_delete=0;
24
$opt_flush=$opt_check=$opt_repair=$opt_alter=0;
26
$opt_resize_interval=0;
28
$opt_host=$opt_user=$opt_password=""; $opt_db="test";
29
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
31
GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","skip-in","skip-drop",
32
"verbose","fast-insert","lock-tables","debug","fast","force","thread-factor=i",
33
"insert=i", "select=i", "join=i", "select-count=i", "join-count=i", "update=i", "delete=i",
34
"flush=i", "check=i", "repair=i", "alter=i", "resize-interval=i", "max-join_range=i", "time=i") || die "Aborted";
36
print "Test of multiple connections that test the following things:\n";
37
print "insert, select, delete, update, alter, check, repair and flush\n";
39
@testtables = ( ["bench_f31", ""],
40
["bench_f32", "row_format=fixed"],
41
["bench_f33", "delay_key_write=1"],
42
["bench_f34", "checksum=1"],
43
["bench_f35", "delay_key_write=1"]);
44
$abort_table="bench_f39";
46
$numtables = $#testtables+1;
47
srand 100; # Make random numbers repeatable
50
#### Start timeing and start test
53
$opt_insert*=$opt_thread_factor;
54
$opt_select*=$opt_thread_factor;
55
$opt_join*=$opt_thread_factor;
56
$opt_select_count*=$opt_thread_factor;
57
$opt_join_count*=$opt_thread_factor;
58
$opt_update*=$opt_thread_factor;
59
$opt_delete*=$opt_thread_factor;
61
if ($opt_time == 0 && $opt_insert == 0)
66
$start_time=new Benchmark;
67
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
68
$opt_user, $opt_password,
69
{ PrintError => 0}) || die $DBI::errstr;
70
if (!$opt_skip_create)
73
foreach $table_def (@testtables)
75
my ($table,$extra)= ($table_def->[0], $table_def->[1]);
76
print "Creating table $table in database $opt_db\n";
77
$dbh->do("drop table if exists $table");
78
$dbh->do("create table $table".
79
" (id int(6) not null auto_increment,".
80
" info varchar(32)," .
81
" marker timestamp," .
82
" flag int not null," .
83
" primary key(id)) $extra")
86
# One row in the table will make future tests easier
87
$dbh->do("insert into $table (id) values (null)")
90
# Create the table we use to signal that we should end the test
91
$dbh->do("drop table if exists $abort_table");
92
$dbh->do("create table $abort_table (id int(6) not null) ENGINE=heap") ||
96
$dbh->do("delete from $abort_table");
97
$dbh->disconnect; $dbh=0; # Close handler
105
test_abort() if (($pid=fork()) == 0); $work{$pid}="abort";
107
for ($i=0 ; $i < $opt_insert ; $i ++)
109
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
112
for ($i=0 ; $i < $opt_select ; $i ++)
114
test_select() if (($pid=fork()) == 0); $work{$pid}="select";
117
for ($i=0 ; $i < $opt_join ; $i ++)
119
test_join() if (($pid=fork()) == 0); $work{$pid}="join";
122
for ($i=0 ; $i < $opt_select_count ; $i ++)
124
test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
127
for ($i=0 ; $i < $opt_join_count ; $i ++)
129
test_join_count() if (($pid=fork()) == 0); $work{$pid}="join_count";
132
for ($i=0 ; $i < $opt_update ; $i ++)
134
test_update() if (($pid=fork()) == 0); $work{$pid}="update";
137
for ($i=0 ; $i < $opt_delete ; $i ++)
139
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
142
for ($i=0 ; $i < $opt_flush ; $i ++)
144
test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
147
for ($i=0 ; $i < $opt_check ; $i ++)
149
test_check() if (($pid=fork()) == 0); $work{$pid}="check";
152
for ($i=0 ; $i < $opt_repair ; $i ++)
154
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
157
for ($i=0 ; $i < $opt_alter ; $i ++)
159
test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
162
if ($opt_resize_interval != 0)
164
test_resize() if (($pid=fork()) == 0); $work{$pid}="resize";
168
print "Started $threads threads\n";
171
$running_insert_threads=$opt_insert;
172
while (($pid=wait()) != -1)
175
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
178
if ($work{$pid} =~ /^insert/)
180
if (!--$running_insert_threads)
183
# Time to stop other threads
188
$errors++ if ($ret != 0);
195
if (!$opt_skip_drop && !$errors)
198
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
199
$opt_user, $opt_password,
200
{ PrintError => 0}) || die $DBI::errstr;
202
$dbh->do("drop table $abort_table");
203
foreach $table_def (@testtables)
205
$dbh->do("drop table " . $table_def->[0]);
207
$dbh->disconnect; $dbh=0; # Close handler
210
print ($errors ? "Test failed\n" :"Test ok\n");
211
$end_time=new Benchmark;
212
print "Total time: " .
213
timestr(timediff($end_time, $start_time),"noc") . "\n";
218
# Sleep and then abort other threads
230
# Insert records in the table
235
my ($from_table,$to_table)= @_;
236
my ($dbh,$i,$j,$count,$table_def,$table);
238
if (!defined($from_table))
240
$from_table=0; $to_table=$numtables-1;
243
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
244
$opt_user, $opt_password,
245
{ PrintError => 0}) || die $DBI::errstr;
247
for ($i=$count=0 ; $i < $opt_loop_count; $i++)
249
for ($j= $from_table ; $j <= $to_table ; $j++)
251
my ($table)= ($testtables[$j]->[0]);
252
$dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
256
$dbh->disconnect; $dbh=0;
257
print "Test_insert: Inserted $count rows\n";
264
# Do continously select over all tables as long as there is changed
270
my ($dbh, $i, $j, $count, $loop);
272
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
273
$opt_user, $opt_password,
274
{ PrintError => 0}) || die $DBI::errstr;
276
$count_query=make_count_query($numtables);
281
while (($i++ % 100) || !test_if_abort($dbh))
286
$row_counts=simple_query($dbh, $count_query);
288
for ($j=0 ; $j < $numtables ; $j++)
290
my ($id)= int rand $row_counts->[$j];
291
my ($table)= $testtables[$j]->[0];
292
simple_query($dbh, "select id,info from $table where id=$id");
296
$dbh->disconnect; $dbh=0;
297
print "Test_select: Executed $count selects\n";
302
# Do big select count(distinct..) over the table
305
sub test_select_count
307
my ($dbh, $i, $j, $count, $loop);
309
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
310
$opt_user, $opt_password,
311
{ PrintError => 0}) || die $DBI::errstr;
315
while (!test_if_abort($dbh))
317
for ($j=0 ; $j < $numtables ; $j++)
319
my ($table)= $testtables[$j]->[0];
320
simple_query($dbh, "select count(distinct marker),count(distinct id),count(distinct info) from $table");
323
sleep(20); # This query is quite slow
325
$dbh->disconnect; $dbh=0;
326
print "Test_select: Executed $count select count(distinct) queries\n";
332
# Do continously joins between the first and second table
337
my ($dbh, $i, $j, $count, $loop);
339
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
340
$opt_user, $opt_password,
341
{ PrintError => 0}) || die $DBI::errstr;
343
$count_query=make_count_query($numtables);
348
while (($i++ % 100) || !test_if_abort($dbh))
353
$row_counts=simple_query($dbh, $count_query);
355
for ($j=0 ; $j < $numtables-1 ; $j++)
357
my ($id)= int rand $row_counts->[$j];
358
my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
359
simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
363
$dbh->disconnect; $dbh=0;
364
print "Test_join: Executed $count joins\n";
370
# Do continously joins between the first and second for range and count selected rows
375
my ($dbh, $i, $j, $count, $loop);
377
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
378
$opt_user, $opt_password,
379
{ PrintError => 0}) || die $DBI::errstr;
381
$count_query=make_count_query($numtables);
389
while (($i++ % 10) || !test_if_abort($dbh))
394
$row_counts=simple_query($dbh, $count_query);
396
for ($j=0 ; $j < $numtables-1 ; $j++)
398
my ($id1)= int rand $row_counts->[$j];
399
my ($id2)= int rand $row_counts->[$j];
402
my $id0=$id1; $id1=$id2; $id2=$id0;
403
if ($id2-$id1 > $opt_join_range)
405
$id2=$id1+$opt_join_range;
408
my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
409
$row=simple_query($dbh, "select count(*) from $t1, $t2 where $t1.id=$t2.id and $t1.id between $id1 and $id2");
414
$dbh->disconnect; $dbh=0;
415
print "Test_join_count: Executed $count joins: total $sum rows\n";
421
# Delete 1-5 rows from the first 2 tables.
422
# Test ends when the number of rows for table 3 didn't change during
428
my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
432
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
433
$opt_user, $opt_password,
434
{ PrintError => 0}) || die $DBI::errstr;
436
$count_query=make_count_query($table_count+1);
438
sleep(5); # Give time to insert some rows
440
while (($i++ % 10) || !test_if_abort($dbh))
443
$row_counts=simple_query($dbh, $count_query);
445
for ($j=0 ; $j < $table_count ; $j++)
447
my ($id)= int rand $row_counts->[$j];
448
my ($table)= $testtables[$j]->[0];
449
$dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
453
$dbh->disconnect; $dbh=0;
454
print "Test_delete: Executed $count deletes\n";
459
# Update the flag for table 2 and 3
460
# Will abort after a while when table1 doesn't change max value
465
my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
466
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
467
$opt_user, $opt_password,
468
{ PrintError => 0}) || die $DBI::errstr;
470
$count_query=make_count_query(3);
474
sleep(5); # Give time to insert some rows
476
while (($i++ % 100) || !test_if_abort($dbh))
481
$row_counts=simple_query($dbh, $count_query);
484
for ($j=1 ; $j <= 2 ; $j++)
486
my ($id)= int rand $row_counts->[$j];
487
my ($table)= $testtables[$j]->[0];
488
# Fix to not change the same rows as the above delete
489
$id= ($id + $count) % $row_counts->[$j];
491
$dbh->do("update $table set flag=flag+1 where id >= $id-2 and id <= $id +2") || die "Got error on update of $table: $DBI::errstr\n";
495
$dbh->disconnect; $dbh=0;
496
print "Test_update: Executed $count updates\n";
502
# Run a check on all tables except the last one
503
# (The last one is not checked to put pressure on the key cache)
508
my ($dbh, $row, $i, $j, $type, $table);
509
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
510
$opt_user, $opt_password,
511
{ PrintError => 0}) || die $DBI::errstr;
514
for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
517
$table=$testtables[$j]->[0];
518
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
519
$sth->execute || die $DBI::errstr;
521
while (($row=$sth->fetchrow_arrayref))
523
if ($row->[3] ne "OK")
525
print "Got error " . $row->[3] . " when doing $type on $table\n";
529
if (++$j == $numtables-1)
534
$dbh->disconnect; $dbh=0;
535
print "test_check: Executed $i checks\n";
540
# Do a repair on the first table once in a while
545
my ($dbh, $row, $i, $type, $table);
546
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
547
$opt_user, $opt_password,
548
{ PrintError => 0}) || die $DBI::errstr;
551
for ($i=0 ; !test_if_abort($dbh) ; $i++)
554
$table=$testtables[0]->[0];
555
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
556
$sth->execute || die $DBI::errstr;
558
while (($row=$sth->fetchrow_arrayref))
560
if ($row->[3] ne "OK")
562
print "Got error " . $row->[3] . " when doing $type on $table\n";
567
$dbh->disconnect; $dbh=0;
568
print "test_repair: Executed $i repairs\n";
573
# Do a flush tables on table 3 and 4 once in a while
578
my ($dbh,$count,$tables);
580
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
581
$opt_user, $opt_password,
582
{ PrintError => 0}) || die $DBI::errstr;
584
$tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
587
while (!test_if_abort($dbh))
590
$dbh->do("flush tables $tables") ||
591
die "Got error on flush $DBI::errstr\n";
594
$dbh->disconnect; $dbh=0;
595
print "flush: Executed $count flushs\n";
600
# Do a resize key cache every periodically
605
my ($dbh, $key_buffer_size);
607
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
608
$opt_user, $opt_password,
609
{ PrintError => 0}) || die $DBI::errstr;
612
$key_buffer_size=1024*64;
613
while (!test_if_abort($dbh))
615
sleep($opt_resize_interval);
616
$dbh->do("set global key_buffer_size=$key_buffer_size") ||
617
die "Got error on resize key cache $DBI::errstr\n";
618
$key_buffer_size+=1024*16;
621
$dbh->disconnect; $dbh=0;
622
print "Test_resize: Executed $count times resize key cache\n";
627
# Test all tables in a database
633
my ($dbh, $row, $i, $type, $tables);
634
$dbh = DBI->connect("DBI:mysql:$database:$opt_host",
635
$opt_user, $opt_password,
636
{ PrintError => 0}) || die $DBI::errstr;
638
$tables= join(',',$dbh->func('_ListTables'));
640
for ($i=0 ; !test_if_abort($dbh) ; $i++)
643
$sth=$dbh->prepare("$type table $tables") || die "Got error on prepare: $DBI::errstr\n";
644
$sth->execute || die $DBI::errstr;
646
while (($row=$sth->fetchrow_arrayref))
648
if ($row->[3] ne "OK")
650
print "Got error " . $row->[2] . " " . $row->[3] . " when doing $type on " . $row->[0] . "\n";
655
$dbh->disconnect; $dbh=0;
656
print "test_check: Executed $i checks\n";
661
# Test ALTER TABLE on the second table
666
my ($dbh, $row, $i, $type, $table);
667
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
668
$opt_user, $opt_password,
669
{ PrintError => 0}) || die $DBI::errstr;
671
for ($i=0 ; !test_if_abort($dbh) ; $i++)
674
$table=$testtables[1]->[0];
675
$sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
676
$sth->execute || die $DBI::errstr;
678
$dbh->disconnect; $dbh=0;
679
print "test_alter: Executed $i ALTER TABLE\n";
691
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
692
$opt_user, $opt_password,
693
{ PrintError => 0}) || die $DBI::errstr;
695
$dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
696
$dbh->disconnect; $dbh=0;
703
$row=simple_query($dbh,"select * from $opt_db.$abort_table");
704
return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
710
my ($table_count)= @_;
711
my ($tables, $count_query, $i, $tables_def);
713
$count_query="select high_priority ";
715
for ($i=0 ; $i < $table_count ; $i++)
717
my ($table_def)= $testtables[$i];
718
$tables.=$table_def->[0] . ",";
719
$count_query.= "max(" . $table_def->[0] . ".id),";
721
$table_def=$testtables[$table_count];
722
$tables.=$table_def->[0];
723
$count_query.= "max(" . $table_def->[0] . ".id) from $tables";
729
my ($dbh, $query)= @_;
732
$sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
733
$sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
734
$row= $sth->fetchrow_arrayref();