~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/fork_big.pl

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl -w
 
2
#
 
3
# This is a test with uses many processes to test a MySQL server.
 
4
#
 
5
# Tested a lot with:  --threads=30
 
6
 
 
7
$opt_loop_count=500000; # Change this to make test harder/easier
 
8
 
 
9
##################### Standard benchmark inits ##############################
 
10
 
 
11
use DBI;
 
12
use Getopt::Long;
 
13
use Benchmark;
 
14
 
 
15
package main;
 
16
 
 
17
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
 
18
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
 
19
$opt_threads=5;
 
20
$opt_host=$opt_user=$opt_password=""; $opt_db="test";
 
21
 
 
22
GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","skip-in","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","threads=i") || die "Aborted";
 
23
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef;  # Ignore warnings from these
 
24
 
 
25
print "Test of multiple connections that test the following things:\n";
 
26
print "insert, select, delete, update, alter, check, repair and flush\n";
 
27
 
 
28
@testtables = ( ["bench_f31", ""],
 
29
                ["bench_f32", "row_format=fixed"],
 
30
                ["bench_f33", "delay_key_write=1"],
 
31
                ["bench_f34", "checksum=1"],
 
32
                ["bench_f35", "delay_key_write=1"]);
 
33
$abort_table="bench_f39";
 
34
 
 
35
$numtables = $#testtables+1;
 
36
srand 100;                      # Make random numbers repeatable
 
37
 
 
38
####
 
39
####  Start timeing and start test
 
40
####
 
41
 
 
42
$start_time=new Benchmark;
 
43
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
44
                    $opt_user, $opt_password,
 
45
                  { PrintError => 0}) || die $DBI::errstr;
 
46
if (!$opt_skip_create)
 
47
{
 
48
  my $table_def;
 
49
  foreach $table_def (@testtables)
 
50
  {
 
51
    my ($table,$extra)= ($table_def->[0], $table_def->[1]);
 
52
    print "Creating table $table in database $opt_db\n";
 
53
    $dbh->do("drop table if exists $table");
 
54
    $dbh->do("create table $table".
 
55
             " (id int(6) not null auto_increment,".
 
56
             " info varchar(32)," .
 
57
             " marker timestamp," .
 
58
             " flag int not null," .
 
59
             " primary key(id)) $extra")
 
60
 
 
61
      or die $DBI::errstr;
 
62
    # One row in the table will make future tests easier
 
63
    $dbh->do("insert into $table (id) values (null)")
 
64
      or die $DBI::errstr;
 
65
  }
 
66
  # Create the table we use to signal that we should end the test
 
67
  $dbh->do("drop table if exists $abort_table");
 
68
  $dbh->do("create table $abort_table (id int(6) not null) ENGINE=heap") ||
 
69
    die $DBI::errstr;
 
70
}
 
71
 
 
72
$dbh->do("delete from $abort_table");
 
73
$dbh->disconnect; $dbh=0;       # Close handler
 
74
$|= 1;                          # Autoflush
 
75
 
 
76
####
 
77
#### Start the tests
 
78
####
 
79
 
 
80
for ($i=0 ; $i < $opt_threads ; $i ++)
 
81
{
 
82
  test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
 
83
}
 
84
for ($i=0 ; $i < $numtables ; $i ++)
 
85
{
 
86
  test_insert($i,$i) if (($pid=fork()) == 0); $work{$pid}="insert_one";
 
87
}
 
88
for ($i=0 ; $i < $opt_threads ; $i ++)
 
89
{
 
90
  test_select() if (($pid=fork()) == 0); $work{$pid}="select_key";
 
91
}
 
92
test_join() if (($pid=fork()) == 0); $work{$pid}="test_join";
 
93
test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
 
94
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
 
95
test_update() if (($pid=fork()) == 0); $work{$pid}="update";
 
96
test_flush() if (($pid=fork()) == 0); $work{$pid}= "flush";
 
97
test_check() if (($pid=fork()) == 0); $work{$pid}="check";
 
98
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
 
99
test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
 
100
#test_database("test2") if (($pid=fork()) == 0); $work{$pid}="check_database";
 
101
 
 
102
print "Started " . ($opt_threads*2+4) . " threads\n";
 
103
 
 
104
$errors=0;
 
105
$running_insert_threads=$opt_threads+$numtables;
 
106
while (($pid=wait()) != -1)
 
107
{
 
108
  $ret=$?/256;
 
109
  print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
 
110
  if ($work{$pid} =~ /^insert/)
 
111
  {
 
112
    if (!--$running_insert_threads)
 
113
    {
 
114
      # Time to stop other threads
 
115
      signal_abort();
 
116
    }
 
117
  }
 
118
  $errors++ if ($ret != 0);
 
119
}
 
120
 
 
121
#
 
122
# Cleanup
 
123
#
 
124
 
 
125
if (!$opt_skip_delete && !$errors)
 
126
{
 
127
  my $table_def;
 
128
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
129
                      $opt_user, $opt_password,
 
130
                    { PrintError => 0}) || die $DBI::errstr;
 
131
 
 
132
  $dbh->do("drop table $abort_table");
 
133
  foreach $table_def (@testtables)
 
134
  {
 
135
    $dbh->do("drop table " . $table_def->[0]);
 
136
  }
 
137
  $dbh->disconnect; $dbh=0;     # Close handler
 
138
}
 
139
 
 
140
print ($errors ? "Test failed\n" :"Test ok\n");
 
141
$end_time=new Benchmark;
 
142
print "Total time: " .
 
143
  timestr(timediff($end_time, $start_time),"noc") . "\n";
 
144
 
 
145
exit(0);
 
146
 
 
147
 
 
148
#
 
149
# Insert records in the table
 
150
#
 
151
 
 
152
sub test_insert
 
153
{
 
154
  my ($from_table,$to_table)= @_;
 
155
  my ($dbh,$i,$j,$count,$table_def,$table);
 
156
 
 
157
  if (!defined($from_table))
 
158
  {
 
159
    $from_table=0; $to_table=$numtables-1;
 
160
  }
 
161
 
 
162
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
163
                      $opt_user, $opt_password,
 
164
                    { PrintError => 0}) || die $DBI::errstr;
 
165
 
 
166
  for ($i=$count=0 ; $i < $opt_loop_count; $i++)
 
167
  {
 
168
    for ($j= $from_table ; $j <= $to_table ; $j++)
 
169
    {
 
170
      my ($table)= ($testtables[$j]->[0]);
 
171
      $dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
 
172
      $count++;
 
173
    }
 
174
  }
 
175
  $dbh->disconnect; $dbh=0;
 
176
  print "Test_insert: Inserted $count rows\n";
 
177
  exit(0);
 
178
}
 
179
 
 
180
 
 
181
#
 
182
# select records
 
183
# Do continously select over all tables as long as there is changed
 
184
# rows in the table
 
185
#
 
186
 
 
187
sub test_select
 
188
{
 
189
  my ($dbh, $i, $j, $count, $loop);
 
190
 
 
191
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
192
                      $opt_user, $opt_password,
 
193
                    { PrintError => 0}) || die $DBI::errstr;
 
194
 
 
195
  $count_query=make_count_query($numtables);
 
196
  $count=0;
 
197
  $loop=9999;
 
198
 
 
199
  $i=0;
 
200
  while (($i++ % 100) || !test_if_abort($dbh))
 
201
  {
 
202
    if ($loop++ >= 100)
 
203
    {
 
204
      $loop=0;
 
205
      $row_counts=simple_query($dbh, $count_query);
 
206
    }
 
207
    for ($j=0 ; $j < $numtables ; $j++)
 
208
    {
 
209
      my ($id)= int rand $row_counts->[$j];
 
210
      my ($table)= $testtables[$j]->[0];
 
211
      simple_query($dbh, "select id,info from $table where id=$id");
 
212
      $count++;
 
213
    }
 
214
  }
 
215
  $dbh->disconnect; $dbh=0;
 
216
  print "Test_select: Executed $count selects\n";
 
217
  exit(0);
 
218
}
 
219
 
 
220
#
 
221
# Do big select count(distinct..) over the table
 
222
 
223
 
 
224
sub test_select_count
 
225
{
 
226
  my ($dbh, $i, $j, $count, $loop);
 
227
 
 
228
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
229
                      $opt_user, $opt_password,
 
230
                    { PrintError => 0}) || die $DBI::errstr;
 
231
 
 
232
  $count=0;
 
233
  $i=0;
 
234
  while (!test_if_abort($dbh))
 
235
  {
 
236
    for ($j=0 ; $j < $numtables ; $j++)
 
237
    {
 
238
      my ($table)= $testtables[$j]->[0];
 
239
      simple_query($dbh, "select count(distinct marker),count(distinct id),count(distinct info) from $table");
 
240
      $count++;
 
241
    }
 
242
    sleep(20);          # This query is quite slow
 
243
  }
 
244
  $dbh->disconnect; $dbh=0;
 
245
  print "Test_select: Executed $count select count(distinct) queries\n";
 
246
  exit(0);
 
247
}
 
248
 
 
249
#
 
250
# select records
 
251
# Do continously joins between the first and second table
 
252
#
 
253
 
 
254
sub test_join
 
255
{
 
256
  my ($dbh, $i, $j, $count, $loop);
 
257
 
 
258
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
259
                      $opt_user, $opt_password,
 
260
                    { PrintError => 0}) || die $DBI::errstr;
 
261
 
 
262
  $count_query=make_count_query($numtables);
 
263
  $count=0;
 
264
  $loop=9999;
 
265
 
 
266
  $i=0;
 
267
  while (($i++ % 100) || !test_if_abort($dbh))
 
268
  {
 
269
    if ($loop++ >= 100)
 
270
    {
 
271
      $loop=0;
 
272
      $row_counts=simple_query($dbh, $count_query);
 
273
    }
 
274
    for ($j=0 ; $j < $numtables-1 ; $j++)
 
275
    {
 
276
      my ($id)= int rand $row_counts->[$j];
 
277
      my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
 
278
      simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
 
279
      $count++;
 
280
    }
 
281
  }
 
282
  $dbh->disconnect; $dbh=0;
 
283
  print "Test_join: Executed $count joins\n";
 
284
  exit(0);
 
285
}
 
286
 
 
287
#
 
288
# Delete 1-5 rows from the first 2 tables.
 
289
# Test ends when the number of rows for table 3 didn't change during
 
290
# one loop
 
291
#
 
292
 
 
293
sub test_delete
 
294
{
 
295
  my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
 
296
 
 
297
  $table_count=2;
 
298
  $count=0;
 
299
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
300
                      $opt_user, $opt_password,
 
301
                    { PrintError => 0}) || die $DBI::errstr;
 
302
 
 
303
  $count_query=make_count_query($table_count+1);
 
304
 
 
305
  sleep(5);                     # Give time to insert some rows
 
306
  $i=0;
 
307
  while (($i++ % 10) || !test_if_abort($dbh))
 
308
  {
 
309
    sleep(1);
 
310
    $row_counts=simple_query($dbh, $count_query);
 
311
 
 
312
    for ($j=0 ; $j < $table_count ; $j++)
 
313
    {
 
314
      my ($id)= int rand $row_counts->[$j];
 
315
      my ($table)= $testtables[$j]->[0];
 
316
      $dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
 
317
      $count++;
 
318
    }
 
319
  }
 
320
  $dbh->disconnect; $dbh=0;
 
321
  print "Test_delete: Executed $count deletes\n";
 
322
  exit(0);
 
323
}
 
324
 
 
325
#
 
326
# Update the flag for table 2 and 3
 
327
# Will abort after a while when table1 doesn't change max value
 
328
#
 
329
 
 
330
sub test_update
 
331
{
 
332
  my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
 
333
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
334
                      $opt_user, $opt_password,
 
335
                    { PrintError => 0}) || die $DBI::errstr;
 
336
 
 
337
  $count_query=make_count_query(3);
 
338
  $loop=9999;
 
339
  $count=0;
 
340
 
 
341
  sleep(5);                     # Give time to insert some rows
 
342
  $i=0;
 
343
  while (($i++ % 100) || !test_if_abort($dbh))
 
344
  {
 
345
    if ($loop++ >= 100)
 
346
    {
 
347
      $loop=0;
 
348
      $row_counts=simple_query($dbh, $count_query);
 
349
    }
 
350
 
 
351
    for ($j=1 ; $j <= 2 ; $j++)
 
352
    {
 
353
      my ($id)= int rand $row_counts->[$j];
 
354
      my ($table)= $testtables[$j]->[0];
 
355
      # Fix to not change the same rows as the above delete
 
356
      $id= ($id + $count) % $row_counts->[$j];
 
357
 
 
358
      $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";
 
359
      $count++;
 
360
    }
 
361
  }
 
362
  $dbh->disconnect; $dbh=0;
 
363
  print "Test_update: Executed $count updates\n";
 
364
  exit(0);
 
365
}
 
366
 
 
367
 
 
368
#
 
369
# Run a check on all tables except the last one
 
370
# (The last one is not checked to put pressure on the key cache)
 
371
#
 
372
 
 
373
sub test_check
 
374
{
 
375
  my ($dbh, $row, $i, $j, $type, $table);
 
376
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
377
                      $opt_user, $opt_password,
 
378
                    { PrintError => 0}) || die $DBI::errstr;
 
379
 
 
380
  $type= "check";
 
381
  for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
 
382
  {
 
383
    sleep(1000);
 
384
    $table=$testtables[$j]->[0];
 
385
    $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
 
386
    $sth->execute || die $DBI::errstr;
 
387
 
 
388
    while (($row=$sth->fetchrow_arrayref))
 
389
    {
 
390
      if ($row->[3] ne "OK")
 
391
      {
 
392
        print "Got error " . $row->[3] . " when doing $type on $table\n";
 
393
        exit(1);
 
394
      }
 
395
    }
 
396
    if (++$j == $numtables-1)
 
397
    {
 
398
      $j=0;
 
399
    }
 
400
  }
 
401
  $dbh->disconnect; $dbh=0;
 
402
  print "test_check: Executed $i checks\n";
 
403
  exit(0);
 
404
}
 
405
 
 
406
#
 
407
# Do a repair on the first table once in a while
 
408
#
 
409
 
 
410
sub test_repair
 
411
{
 
412
  my ($dbh, $row, $i, $type, $table);
 
413
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
414
                      $opt_user, $opt_password,
 
415
                    { PrintError => 0}) || die $DBI::errstr;
 
416
 
 
417
  $type= "repair";
 
418
  for ($i=0 ; !test_if_abort($dbh) ; $i++)
 
419
  {
 
420
    sleep(2000);
 
421
    $table=$testtables[0]->[0];
 
422
    $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
 
423
    $sth->execute || die $DBI::errstr;
 
424
 
 
425
    while (($row=$sth->fetchrow_arrayref))
 
426
    {
 
427
      if ($row->[3] ne "OK")
 
428
      {
 
429
        print "Got error " . $row->[3] . " when doing $type on $table\n";
 
430
        exit(1);
 
431
      }
 
432
    }
 
433
  }
 
434
  $dbh->disconnect; $dbh=0;
 
435
  print "test_repair: Executed $i repairs\n";
 
436
  exit(0);
 
437
}
 
438
 
 
439
#
 
440
# Do a flush tables on table 3 and 4 once in a while
 
441
#
 
442
 
 
443
sub test_flush
 
444
{
 
445
  my ($dbh,$count,$tables);
 
446
 
 
447
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
448
                      $opt_user, $opt_password,
 
449
                    { PrintError => 0}) || die $DBI::errstr;
 
450
 
 
451
  $tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
 
452
 
 
453
  $count=0;
 
454
  while (!test_if_abort($dbh))
 
455
  {
 
456
    sleep(3000);
 
457
    $dbh->do("flush tables $tables") ||
 
458
      die "Got error on flush $DBI::errstr\n";
 
459
    $count++;
 
460
  }
 
461
  $dbh->disconnect; $dbh=0;
 
462
  print "flush: Executed $count flushs\n";
 
463
  exit(0);
 
464
}
 
465
 
 
466
 
 
467
#
 
468
# Test all tables in a database
 
469
#
 
470
 
 
471
sub test_database
 
472
{
 
473
  my ($database) = @_;
 
474
  my ($dbh, $row, $i, $type, $tables);
 
475
  $dbh = DBI->connect("DBI:mysql:$database:$opt_host",
 
476
                      $opt_user, $opt_password,
 
477
                    { PrintError => 0}) || die $DBI::errstr;
 
478
 
 
479
  $tables= join(',',$dbh->func('_ListTables'));
 
480
  $type= "check";
 
481
  for ($i=0 ; !test_if_abort($dbh) ; $i++)
 
482
  {
 
483
    sleep(120);
 
484
    $sth=$dbh->prepare("$type table $tables") || die "Got error on prepare: $DBI::errstr\n";
 
485
    $sth->execute || die $DBI::errstr;
 
486
 
 
487
    while (($row=$sth->fetchrow_arrayref))
 
488
    {
 
489
      if ($row->[3] ne "OK")
 
490
      {
 
491
        print "Got error " . $row->[2] . " " . $row->[3] . " when doing $type on " . $row->[0] . "\n";
 
492
        exit(1);
 
493
      }
 
494
    }
 
495
  }
 
496
  $dbh->disconnect; $dbh=0;
 
497
  print "test_check: Executed $i checks\n";
 
498
  exit(0);
 
499
}
 
500
 
 
501
#
 
502
# Test ALTER TABLE on the second table
 
503
#
 
504
 
 
505
sub test_alter
 
506
{
 
507
  my ($dbh, $row, $i, $type, $table);
 
508
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
509
                      $opt_user, $opt_password,
 
510
                    { PrintError => 0}) || die $DBI::errstr;
 
511
 
 
512
  for ($i=0 ; !test_if_abort($dbh) ; $i++)
 
513
  {
 
514
    sleep(100);
 
515
    $table=$testtables[1]->[0];
 
516
    $sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
 
517
    $sth->execute || die $DBI::errstr;
 
518
  }
 
519
  $dbh->disconnect; $dbh=0;
 
520
  print "test_alter: Executed $i ALTER TABLE\n";
 
521
  exit(0);
 
522
}
 
523
 
 
524
 
 
525
#
 
526
# Help functions
 
527
#
 
528
 
 
529
sub signal_abort
 
530
{
 
531
  my ($dbh);
 
532
  $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
 
533
                      $opt_user, $opt_password,
 
534
                    { PrintError => 0}) || die $DBI::errstr;
 
535
 
 
536
  $dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
 
537
  $dbh->disconnect; $dbh=0;
 
538
  exit(0);
 
539
}
 
540
 
 
541
 
 
542
sub test_if_abort()
 
543
{
 
544
  my ($dbh)=@_;
 
545
  $row=simple_query($dbh,"select * from $opt_db.$abort_table");
 
546
  return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
 
547
}
 
548
 
 
549
 
 
550
sub make_count_query
 
551
{
 
552
  my ($table_count)= @_;
 
553
  my ($tables, $count_query, $i, $tables_def);
 
554
  $tables="";
 
555
  $count_query="select high_priority ";
 
556
  $table_count--;
 
557
  for ($i=0 ; $i < $table_count ; $i++)
 
558
  {
 
559
    my ($table_def)= $testtables[$i];
 
560
    $tables.=$table_def->[0] . ",";
 
561
    $count_query.= "max(" . $table_def->[0] . ".id),";
 
562
  }
 
563
  $table_def=$testtables[$table_count];
 
564
  $tables.=$table_def->[0];
 
565
  $count_query.= "max(" . $table_def->[0] . ".id) from $tables";
 
566
  return $count_query;
 
567
}
 
568
 
 
569
sub simple_query()
 
570
{
 
571
  my ($dbh, $query)= @_;
 
572
  my ($sth,$row);
 
573
 
 
574
  $sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
 
575
  $sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
 
576
  $row= $sth->fetchrow_arrayref();
 
577
  $sth=0;
 
578
  return $row;
 
579
}