Fixed bug in ALTER TABLE
Removed _mi_rkey() function New fork_big.pl multi-thread test BitKeeper/deleted/.del-fork3_test.pl~c4a7bffb4f8e813c: Delete: tests/fork3_test.pl BitKeeper/deleted/.del-fork_test.pl~3d3535329ed8cd5e: Delete: tests/fork_test.pl Docs/manual.texi: Changelog. Updated support information client/mysqladmin.c: Removed not used --timeout option configure.in: Update version myisam/mi_extra.c: Fixed bug in ALTER TABLE myisam/mi_rkey.c: Removed _mi_rkey() function myisam/myisamdef.h: Removed _mi_rkey() function myisammrg/myrg_rkey.c: Removed _mi_rkey() function myisammrg/myrg_rnext.c: Removed _mi_rkey() function mysql-test/t/alter_table.test: Added test case for ALTER TABLE bug sql/derror.cc: Moved shutdown message to clean_up sql/mysql_priv.h: Moved shutdown message to clean_up sql/sql_class.cc: Fixed bug in MySQL compiled with transactions but using --skip-"table-handler" sql/sql_show.cc: Use time_after_lock for time of query when debugging sql/sql_test.cc: Check memory overruns when using 'mysqladmin debug' strings/ctype-tis620.c: F
This commit is contained in:
parent
05f08c18ac
commit
1776fbac85
161
Docs/manual.texi
161
Docs/manual.texi
@ -528,10 +528,10 @@ GEMINI Tables
|
||||
|
||||
INNOBASE Tables
|
||||
|
||||
* INNOBASE overview::
|
||||
* INNOBASE overview:: INNOBASE overview
|
||||
* INNOBASE start:: INNOBASE startup options
|
||||
* Using INNOBASE tables:: Using INNOBASE tables
|
||||
* INNOBASE restrictions:: Some restrictions on @code{INNOBASE} tables:
|
||||
* INNOBASE restrictions:: Some restrictions on @code{INNOBASE} tables
|
||||
|
||||
MySQL Tutorial
|
||||
|
||||
@ -899,7 +899,7 @@ Changes in release 4.0.x (Development; Alpha)
|
||||
|
||||
Changes in release 3.23.x (Stable)
|
||||
|
||||
* News-3.23.37::
|
||||
* News-3.23.37:: Changes in release 3.23.37
|
||||
* News-3.23.36:: Changes in release 3.23.36
|
||||
* News-3.23.35:: Changes in release 3.23.35
|
||||
* News-3.23.34a:: Changes in release 3.23.34a
|
||||
@ -3873,6 +3873,29 @@ please send e-mail to @email{webmaster@@mysql.com}.
|
||||
* Table handler support:: Support for other table handlers
|
||||
@end menu
|
||||
|
||||
The following holds for all support options.
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
The support is per year.
|
||||
@item
|
||||
Fixing or provide reasonable workarounds for any repeatable bug.
|
||||
@item
|
||||
A reasonable effort to find and fix any other MySQL related bug.
|
||||
@item
|
||||
The following doesn't hold for Basic email support (As this only includes
|
||||
basic installation support):
|
||||
|
||||
For not bug related things, like helping you optimize your queries or
|
||||
your system, extending MySQL with new functionality... we charge 200
|
||||
EURO/hour, which is deducted from your support contract. In other words,
|
||||
if you have login support (2000 EURO), you can expect us to work up to
|
||||
10 hours to help you with things like this.
|
||||
@item
|
||||
The higher level of support contract the more effort we will put into finding
|
||||
a solution to your problems..
|
||||
@end itemize
|
||||
|
||||
@cindex email, technical support
|
||||
@cindex technical support, by email
|
||||
@node Basic email support, Extended email support, Support, Support
|
||||
@ -4635,12 +4658,6 @@ Please report bad or out-of-date mirrors to @email{webmaster@@mysql.com}.
|
||||
@c @image{Flags/usa} USA [Savages/Oregon] @
|
||||
@c @uref{http://mysql.savages.com, WWW}
|
||||
|
||||
@c @item
|
||||
@c No mirror! 010323 Matt
|
||||
@c EMAIL: tcobb@staff.circle.net (Troy Cobb)
|
||||
@c @image{Flags/usa} USA [Circle Net/North Carolina] @
|
||||
@c @uref{http://www.mysql.net, WWW}
|
||||
|
||||
@c @item
|
||||
@c Not ok 20000919; Non-existent (Matt)
|
||||
@c EMAIL: paul@gina.net (Paul Vining)
|
||||
@ -7172,13 +7189,10 @@ Linux version that doesn't have @code{glibc2}, you must install
|
||||
LinuxThreads before trying to compile
|
||||
@strong{MySQL}. @uref{http://www.mysql.com/Downloads/Linux}
|
||||
|
||||
Note that @code{glibc} versions before and including Version 2.1.1 have a fatal
|
||||
bug in @code{pthread_mutex_timedwait} handling, which is used when you
|
||||
do @code{INSERT DELAYED}. If you are using @code{INSERT DELAYED}, you
|
||||
@strong{MUST} add the following patch to your glibc library:
|
||||
@uref{http://www.mysql.com/Downloads/Patches/glibc-pthread_cond_timedwait.patch}.
|
||||
@strong{MySQL} Versions 3.23.7 and 3.22.32 contain a temporary
|
||||
workaround for this bug.
|
||||
Note that @code{glibc} versions before and including Version 2.1.1 have
|
||||
a fatal bug in @code{pthread_mutex_timedwait} handling, which is used
|
||||
when you do @code{INSERT DELAYED}. We recommend you to not use
|
||||
@code{INSERT DELAYED} before upgrading glibc.
|
||||
|
||||
If you plan to have 1000+ concurrent connections, you will need to make
|
||||
some changes to LinuxThreads, recompile it, and relink MySQL against
|
||||
@ -7216,7 +7230,6 @@ tables with lots of data. The more you reduce @code{STACK_SIZE} in
|
||||
LinuxThreads the more threads you can safely create. We recommend the values
|
||||
between 128K and 256 K.
|
||||
|
||||
|
||||
If you use a lot of concurrent connections, you may suffer from a 2.2
|
||||
kernel "feature" in 2.2 kernel that penalizes a process for
|
||||
forking or cloning a child
|
||||
@ -7250,31 +7263,33 @@ systems. If you have access such a system and have done some benchmarks,
|
||||
please send a mail to @email{docs@@mysql.com} with the results - we will
|
||||
include them in the manual.
|
||||
|
||||
The following paragraph is only relevant if you are using a glibc
|
||||
version older than 2.2.2 (Note that if you are going to use MANY
|
||||
connections to MySQL, you still need to change the STACK_SIZE and
|
||||
PTHREAD_THREADS_MAX variables in glibc 2.2.2).
|
||||
|
||||
There is another issue that greatly hurts @strong{MySQL} performance,
|
||||
especially on SMP systems. The current implementation of mutex in Linuxthreads is also very bad for
|
||||
programs with many threads that only hold the mutex for a short time. On an
|
||||
SMP system, ironic as it is, if you link @strong{MySQL} against unmodified
|
||||
@strong{LinuxThreads}, removing processors from the machine improves
|
||||
@strong{MySQL} performance in many cases.
|
||||
We have made a patch available for glibc 2.1,
|
||||
especially on SMP systems. The old implementation of mutex in
|
||||
LinuxThreads was also very bad for programs with many threads that only
|
||||
hold the mutex for a short time. On an SMP system, ironic as it is, if
|
||||
you link @strong{MySQL} against unmodified @strong{LinuxThreads},
|
||||
removing processors from the machine improves @strong{MySQL} performance
|
||||
in many cases. We have made a patch available for glibc 2.1,
|
||||
@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch,linuxthreads-2.1-patch}
|
||||
and for glibc 2.2,
|
||||
@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2-patch,linuxthreads-2.2-patch} to correct this behaviour. Please note that since there are so
|
||||
many versions of glibc floating around, the patch may not apply cleanly to
|
||||
@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2-patch,linuxthreads-2.2-patch}
|
||||
to correct this behaveour. Please note that since there are so many
|
||||
versions of glibc floating around, the patch may not apply cleanly to
|
||||
yours, so some manual work may be required.
|
||||
|
||||
We recommend that you use the above patched to build a special static version
|
||||
of @code{libpthread.a} and use it only for statically linking
|
||||
against @code{MySQL}. We
|
||||
know that the patch is safe for @code{MySQL} and significantly improves its
|
||||
performance, but we cannot say anything about other applications. If you
|
||||
link other applications against the patched version of the library, or
|
||||
build a patched shared version and install it on your system, you are doing
|
||||
it at your own risk with regard to other applicatioins that depend on
|
||||
@code{LinuxThreads}.
|
||||
|
||||
@c Monty, is the stuff below any longer relevant? I know it needs to be
|
||||
@c at least corrected as RPM and binary are now the same
|
||||
We recommend that you use the above patches to build a special static
|
||||
version of @code{libpthread.a} and use it only for statically linking
|
||||
against @code{MySQL}. We know that the patch is safe for @code{MySQL}
|
||||
and significantly improves its performance, but we cannot say anything
|
||||
about other applications. If you link other applications against the
|
||||
patched version of the library, or build a patched shared version and
|
||||
install it on your system, you are doing it at your own risk with regard
|
||||
to other applications that depend on @code{LinuxThreads}.
|
||||
|
||||
If you can't start @code{mysqld} or if @code{mysql_install_db} doesn't work,
|
||||
please continue reading! This only happens on Linux system with problems in
|
||||
@ -9792,6 +9807,11 @@ Set the default character set. @xref{Character sets}.
|
||||
@item --default-table-type=type
|
||||
Set the default table type for tables. @xref{Table types}.
|
||||
|
||||
@item --debug[...]=
|
||||
If @strong{MySQL} is configured with @code{--with-debug}, you can use
|
||||
this option to get a trace file of what @code{mysqld} is
|
||||
doing. @xref{The DBUG package}.
|
||||
|
||||
@item --delay-key-write-for-all-tables
|
||||
Don't flush key buffers between writes for any @code{MyISAM} table.
|
||||
@xref{Server parameters}.
|
||||
@ -9946,14 +9966,23 @@ All interaction with @code{mysqld} must be made via Unix sockets.
|
||||
This option is highly recommended for systems where only local requests
|
||||
are allowed. @xref{DNS}.
|
||||
|
||||
@item --skip-host-cache
|
||||
Never use host name cache for faster name-ip resolution, but query
|
||||
DNS server on every connect instead. @xref{DNS}.
|
||||
|
||||
@item --skip-new
|
||||
Don't use new, possible wrong routines.
|
||||
Implies @code{--skip-delay-key-write}.
|
||||
This will also set default table type to @code{ISAM}. @xref{ISAM}.
|
||||
|
||||
@item --skip-host-cache
|
||||
Never use host name cache for faster name-ip resolution, but query
|
||||
DNS server on every connect instead. @xref{DNS}.
|
||||
@item --skip-safemalloc
|
||||
If @strong{MySQL} is configured with @code{--with-debug=full}, all
|
||||
programs will check the memory for overruns for every memory allocation /
|
||||
memory freeing. As this checking is very slow, you can avoid this,
|
||||
when you don't need memory checking, by using this option.
|
||||
|
||||
this option to get a trace file of what @code{mysqld} is
|
||||
doing. @xref{The DBUG package}.
|
||||
|
||||
@item --skip-show-database
|
||||
Don't allow 'SHOW DATABASE' commands, unless the user has
|
||||
@ -10291,6 +10320,9 @@ Version 3.23:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
All tables that uses the @code{tis620} character set must be fixed
|
||||
with @code{myisamchk -r} or @code{REPAIR TABLE}.
|
||||
@item
|
||||
If you do a @code{DROP DATABASE} on a symbolic linked database, both the
|
||||
link and the original database is deleted. (This didn't happen in 3.22
|
||||
because configure didn't detect the @code{readlink} system call).
|
||||
@ -12377,9 +12409,12 @@ You can use the wild-card characters @samp{%} and @samp{_} in the @code{Host}
|
||||
field.
|
||||
|
||||
@item
|
||||
A @code{Host} value of @code{'%'} matches any hostname. A blank @code{Host}
|
||||
value is equivalent to @code{'%'}. Note that these values match @emph{any
|
||||
host that can create a connection to your server!}
|
||||
A @code{Host} value of @code{'%'} matches any hostname.
|
||||
|
||||
@item
|
||||
A blank @code{Host} value means that the privilege should be anded
|
||||
with the entry in the @code{host} table that matches the given host name.
|
||||
You can find more information about this in the next chapter.
|
||||
|
||||
@cindex netmask notation, in @code{mysql.user} table
|
||||
@item
|
||||
@ -18304,7 +18339,7 @@ or MIN_ROWS = #
|
||||
or PACK_KEYS = @{0 | 1@}
|
||||
or PASSWORD = "string"
|
||||
or DELAY_KEY_WRITE = @{0 | 1@}
|
||||
or ROW_FORMAT= @{ default | dynamic | static | compressed @}
|
||||
or ROW_FORMAT= @{ default | dynamic | fixed | compressed @}
|
||||
or RAID_TYPE= @{1 | STRIPED | RAID0 @} RAID_CHUNKS=# RAID_CHUNKSIZE=#
|
||||
or UNION = (table_name,[table_name...])
|
||||
|
||||
@ -21489,6 +21524,20 @@ The buffer that is allocated when sorting the index when doing a
|
||||
@code{REPAIR} or when creating indexes with @code{CREATE INDEX} or
|
||||
@code{ALTER TABLE}.
|
||||
|
||||
@item @code{myisam_max_extra_sort_file_size}.
|
||||
If the creating of the temporary file for fast index creation would be
|
||||
this much bigger than using the key cache, then prefer the key cache
|
||||
method. This is mainly used to force long character keys in large
|
||||
tables to use the slower key cache method to create the index.
|
||||
@strong{NOTE} that this parameter is given in megabytes!
|
||||
|
||||
@item @code{myisam_max_sort_file_size}
|
||||
The maximum size of the temporary file @strong{MySQL} is allowed to create
|
||||
to while recreating the index (during @code{REPAIR}, @code{ALTER TABLE}
|
||||
or @code{LOAD DATA INFILE}. If the file size would be bigger than this,
|
||||
the index will be created through the key cache (which is slower).
|
||||
@strong{NOTE} that this parameter is given in megabytes!
|
||||
|
||||
@item @code{net_buffer_length}
|
||||
The communication buffer is reset to this size between queries. This
|
||||
should not normally be changed, but if you have very little memory, you
|
||||
@ -23083,13 +23132,16 @@ system resources than @code{ISAM}, but will need more CPU when inserting
|
||||
data into a compressed index.
|
||||
|
||||
The following options to @code{mysqld} can be used to change the behavior of
|
||||
@code{MyISAM} tables:
|
||||
@code{MyISAM} tables. @xref{SHOW VARIABLES}.
|
||||
|
||||
@multitable @columnfractions .40 .60
|
||||
@item @strong{Option} @tab @strong{Meaning}
|
||||
@item @code{--myisam-recover=#} @tab Automatic recover of crashed tables.
|
||||
@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables.
|
||||
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
|
||||
@item @code{-O myisam_max_extra_sort_file_size=#} @tab Used to help @strong{MySQL} to decide when to use the slow but safe key cache index create method. @strong{NOTE} that this parameter is given in megabytes!
|
||||
@item @code{-O myisam_max_sort_file_size=#} @tab Don't use the fast sort index method to created index if the temporary file would get bigger than this.
|
||||
@strong{NOTE} that this paramter is given in megabytes!
|
||||
@end multitable
|
||||
|
||||
The automatic recovery is activated if you start mysqld with
|
||||
@ -34084,7 +34136,7 @@ this problem.
|
||||
@itemize @bullet
|
||||
@item
|
||||
You can use the static @strong{MySQL} libraries for Borland C++ that you
|
||||
can find on @uref{http://www.mysql.net/downloads/os-win32.html}.
|
||||
can find on @uref{http://www.mysql.com/downloads/os-win32.html}.
|
||||
@item
|
||||
Only call @code{mysql_init()} with @code{NULL} as an argument, not a
|
||||
pre-allocated MYSQL struct.
|
||||
@ -42427,7 +42479,19 @@ not yet 100 % confident in this code.
|
||||
Fixed bug in @code{ALTER TABLE} and @code{LOAD DATA INFILE} that disabled
|
||||
key-sorting. These command should now be faster in most cases.
|
||||
@item
|
||||
Fixed problem with @code{ALTER TABLE} to Innobase tables on Freebsd.
|
||||
@item
|
||||
Added @code{mysqld} variables @code{myisam_max_sort_file_size} and
|
||||
@code{myisam_max_extra_sort_file_size}.
|
||||
@item
|
||||
Initialize signals early to avoid problem with signals in Innobase..
|
||||
@item
|
||||
Applied patch for the @code{tis620} character set to make comparisons
|
||||
case-independent and to fix a bug in @code{LIKE} for this character set.
|
||||
@strong{NOTE}: All tables that uses the @code{tis620} character set must be
|
||||
fixed with @code{myisamchk -r} or @code{REPAIR TABLE} !
|
||||
@item
|
||||
Added @code{--skip-safemalloc} option to @code{mysqld}.
|
||||
@end itemize
|
||||
|
||||
@node News-3.23.36, News-3.23.35, News-3.23.37, News-3.23.x
|
||||
@ -48417,6 +48481,11 @@ file of what the program is debugging.
|
||||
One uses the debug package by invoking the program with the
|
||||
@code{--debug="..."} or the @code{-#...} option.
|
||||
|
||||
Most @strong{MySQL} programs has a default debug string that will be
|
||||
used if you don't specify an option to @code{--debug}. The default
|
||||
trace file is usually @code{/tmp/programname.trace} on Unix and
|
||||
@code{\programname.trace} on windows.
|
||||
|
||||
The debug control string is a sequence of colon separated fields
|
||||
as follows:
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <my_pthread.h> /* because of signal() */
|
||||
#endif
|
||||
|
||||
#define ADMIN_VERSION "8.18"
|
||||
#define ADMIN_VERSION "8.19"
|
||||
#define MAX_MYSQL_VAR 64
|
||||
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
|
||||
#define MAX_TRUNC_LENGTH 3
|
||||
@ -817,8 +817,6 @@ static void usage(void)
|
||||
-s, --silent Silently exit if one can't connect to server\n\
|
||||
-S, --socket=... Socket file to use for connection\n");
|
||||
#include "sslopt-usage.h"
|
||||
printf("\
|
||||
-t, --timeout=... Timeout for connection to the mysqld server\n");
|
||||
#ifndef DONT_ALLOW_USER_CHANGE
|
||||
printf("\
|
||||
-u, --user=# User for login if not current user\n");
|
||||
|
@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(sql/mysqld.cc)
|
||||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
AM_INIT_AUTOMAKE(mysql, 3.23.36)
|
||||
AM_INIT_AUTOMAKE(mysql, 3.23.37)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
@ -660,6 +660,7 @@ int main()
|
||||
#
|
||||
|
||||
MAX_C_OPTIMIZE="-O6"
|
||||
|
||||
case $SYSTEM_TYPE in
|
||||
*solaris2.7*)
|
||||
# Solaris 2.7 has a broken /usr/include/widec.h
|
||||
|
@ -319,6 +319,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
|
||||
{
|
||||
my_free(info->rec_alloc,MYF(MY_ALLOW_ZERO_PTR));
|
||||
info->rec_alloc=info->rec_buff=0;
|
||||
mi_fix_rec_buff_for_blob(info,info->s->base.pack_reclength);
|
||||
}
|
||||
break;
|
||||
case HA_EXTRA_NORMAL: /* Theese isn't in use */
|
||||
|
@ -22,8 +22,8 @@
|
||||
/* Read a record using key */
|
||||
/* Ordinary search_flag is 0 ; Give error if no record with key */
|
||||
|
||||
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
enum ha_rkey_function search_flag, bool raw_key)
|
||||
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
enum ha_rkey_function search_flag)
|
||||
{
|
||||
uchar *key_buff;
|
||||
MYISAM_SHARE *share=info->s;
|
||||
@ -37,7 +37,7 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
|
||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||
|
||||
if (raw_key)
|
||||
if (!info->use_packed_key)
|
||||
{
|
||||
if (key_len == 0)
|
||||
key_len=USE_WHOLE_KEY;
|
||||
@ -101,11 +101,3 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
err:
|
||||
DBUG_RETURN(my_errno);
|
||||
} /* _mi_rkey */
|
||||
|
||||
/* shouldn't forget to do it inline sometime */
|
||||
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
enum ha_rkey_function search_flag)
|
||||
{
|
||||
return _mi_rkey(info,buf,inx,key,key_len,search_flag,TRUE);
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,7 @@ struct st_myisam_info {
|
||||
my_bool quick_mode;
|
||||
my_bool page_changed; /* If info->buff can't be used for rnext */
|
||||
my_bool buff_used; /* If info->buff has to be reread for rnext */
|
||||
my_bool use_packed_key; /* For MYISAMMRG */
|
||||
myf lock_wait; /* is 0 or MY_DONT_WAIT */
|
||||
int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
|
||||
LIST open_list;
|
||||
@ -630,8 +631,6 @@ void mi_update_status(void* param);
|
||||
void mi_copy_status(void* to,void *from);
|
||||
my_bool mi_check_status(void* param);
|
||||
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
|
||||
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
enum ha_rkey_function search_flag, bool raw_key);
|
||||
|
||||
my_bool check_table_is_closed(const char *name, const char *where);
|
||||
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share);
|
||||
|
@ -63,7 +63,9 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
|
||||
}
|
||||
else
|
||||
{
|
||||
err=_mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag,FALSE);
|
||||
mi->use_packed_key=1;
|
||||
err=mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag);
|
||||
mi->use_packed_key=0;
|
||||
}
|
||||
info->last_used_table=table+1;
|
||||
|
||||
|
@ -68,8 +68,10 @@ int _myrg_finish_scan(MYRG_INFO *info, int inx, enum ha_rkey_function type)
|
||||
for (; table < info->end_table ; table++)
|
||||
{
|
||||
mi=table->table;
|
||||
if ((err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,
|
||||
type,FALSE)))
|
||||
mi->use_packed_key=1;
|
||||
err=mi_rkey(mi,NULL,inx,key_buff,pack_key_length,type);
|
||||
mi->use_packed_key=0;
|
||||
if (err)
|
||||
{
|
||||
if (err == HA_ERR_KEY_NOT_FOUND) /* If end of file */
|
||||
continue;
|
||||
|
@ -57,13 +57,17 @@ CREATE TABLE t1 (
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
ALTER TABLE
|
||||
t1
|
||||
ORDER BY
|
||||
t1.id,
|
||||
t1.status,
|
||||
t1.type_id,
|
||||
t1.user_id,
|
||||
t1.body;
|
||||
ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body;
|
||||
DROP TABLE t1;
|
||||
|
||||
drop table t1;
|
||||
#
|
||||
# The following combination found a hang-bug in MyISAM
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (AnamneseId int(10) unsigned NOT NULL auto_increment,B BLOB,PRIMARY KEY (AnamneseId)) type=myisam;
|
||||
insert into t1 values (null,"hello");
|
||||
LOCK TABLES t1 WRITE;
|
||||
ALTER TABLE t1 ADD Column new_col int not null;
|
||||
UNLOCK TABLES;
|
||||
OPTIMIZE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
@ -72,7 +72,7 @@ static void read_texts(const char *file_name,const char ***point,
|
||||
Check that the above file is the right version for this program!\n\n",
|
||||
my_progname,name,ant,error_messages);
|
||||
VOID(my_close(file,MYF(MY_WME)));
|
||||
clean_up(); /* Clean_up frees everything */
|
||||
clean_up(0); /* Clean_up frees everything */
|
||||
exit(1); /* We can't continue */
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ err:
|
||||
if (file != FERR)
|
||||
VOID(my_close(file,MYF(MY_WME)));
|
||||
fprintf(stderr,buff,my_progname,name);
|
||||
clean_up(); /* Clean_up frees everything */
|
||||
clean_up(0); /* Clean_up frees everything */
|
||||
exit(1); /* We can't continue */
|
||||
} /* read_texts */
|
||||
|
||||
|
@ -611,7 +611,7 @@ uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
|
||||
void find_date(char *pos,uint *vek,uint flag);
|
||||
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
||||
TYPELIB *typelib(List<String> &strings);
|
||||
void clean_up(void);
|
||||
void clean_up(bool print_message=1);
|
||||
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
|
||||
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
|
||||
const char *newname);
|
||||
|
@ -136,9 +136,9 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
|
||||
(hash_get_key) get_var_key,
|
||||
(void (*)(void*)) free_var,0);
|
||||
#ifdef USING_TRANSACTIONS
|
||||
bzero((char*) &transaction,sizeof(transaction));
|
||||
if (opt_using_transactions)
|
||||
{
|
||||
bzero((char*) &transaction,sizeof(transaction));
|
||||
if (open_cached_file(&transaction.trans_log,
|
||||
mysql_tmpdir, LOG_PREFIX, binlog_cache_size,
|
||||
MYF(MY_WME)))
|
||||
|
@ -1006,7 +1006,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
|
||||
if (pthread_kill(tmp->real_id,0))
|
||||
tmp->proc_info="*** DEAD ***"; // This shouldn't happen
|
||||
#endif
|
||||
#ifdef EXTRA_DEBUG
|
||||
thd_info->start_time= tmp->time_after_lock;
|
||||
#else
|
||||
thd_info->start_time= tmp->start_time;
|
||||
#endif
|
||||
thd_info->query=0;
|
||||
if (tmp->query)
|
||||
{
|
||||
|
@ -240,6 +240,7 @@ Open streams: %10lu\n",
|
||||
fflush(stdout);
|
||||
if (thd)
|
||||
thd->proc_info="malloc";
|
||||
my_checkmalloc();
|
||||
TERMINATE(stdout); // Write malloc information
|
||||
if (thd)
|
||||
thd->proc_info=0;
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2001 by Korakot Chaovavanich <korakot@iname.com> and
|
||||
Apisilp Trunganont <apisilp@pantip.inet.co.th>
|
||||
Copyright (C) 1998, 1999 by Pruet Boonma <pruet@eng.cmu.ac.th>
|
||||
Copyright (C) 1998 by Theppitak Karoonboonyanan <thep@links.nectec.or.th>
|
||||
Copyright (C) 1989, 1991 by Samphan Raruenrom <samphan@thai.com>
|
||||
@ -6,9 +8,10 @@
|
||||
Permission to use, copy, modify, distribute and sell this software
|
||||
and its documentation for any purpose is hereby granted without fee,
|
||||
provided that the above copyright notice appear in all copies.
|
||||
Smaphan Raruenrom , Theppitak Karoonboonyanan and Pruet Boonma makes
|
||||
no representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied warranty.
|
||||
Samphan Raruenrom , Theppitak Karoonboonyanan , Pruet Boonma ,
|
||||
Korakot Chaovavanich and Apisilp Trunganont makes no representations
|
||||
about the suitability of this software for any purpose. It is provided
|
||||
"as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
@ -297,7 +300,8 @@ int t_ctype[][TOT_LEVELS] = {
|
||||
/*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
|
||||
/*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
|
||||
/*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
|
||||
/*0xFF*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
|
||||
/* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
|
||||
/*0xFF*/ { 255 /*IGNORE*/, IGNORE, IGNORE, IGNORE, X },
|
||||
};
|
||||
|
||||
uchar NEAR ctype_tis620[257] =
|
||||
@ -436,10 +440,14 @@ uchar NEAR sort_order_tis620[]=
|
||||
|
||||
static uchar* thai2sortable(const uchar * tstr,uint len)
|
||||
{
|
||||
/* We use only 3 levels (neglect capitalization). */
|
||||
|
||||
const uchar* p = tstr;
|
||||
uchar *outBuf;
|
||||
uchar *pRight1, *pRight2, *pRight3, *pRight4;
|
||||
uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4;
|
||||
// uchar *pRight1, *pRight2, *pRight3, *pRight4;
|
||||
// uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4;
|
||||
uchar *pRight1, *pRight2, *pRight3;
|
||||
uchar *pLeft1, *pLeft2, *pLeft3;
|
||||
uint bufSize;
|
||||
|
||||
len = (uint) strnlen((char*) tstr,len);
|
||||
@ -460,23 +468,23 @@ static uchar* thai2sortable(const uchar * tstr,uint len)
|
||||
return((uchar*) tstr);
|
||||
}
|
||||
pLeft3 = pRight3;
|
||||
if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
|
||||
/* if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
|
||||
free(pRight1);
|
||||
free(pRight2);
|
||||
free(pRight3);
|
||||
return((uchar*) tstr);
|
||||
}
|
||||
pLeft4 = pRight4;
|
||||
pLeft4 = pRight4;*/
|
||||
while(len--) {
|
||||
if(isldvowel(*p) && isconsnt(p[1])) {
|
||||
*pRight1++ = t_ctype[p[1]][0];
|
||||
*pRight2++ = t_ctype[p[1]][1];
|
||||
*pRight3++ = t_ctype[p[1]][2];
|
||||
*pRight4++ = t_ctype[p[1]][3];
|
||||
// *pRight4++ = t_ctype[p[1]][3];
|
||||
*pRight1++ = t_ctype[*p][0];
|
||||
*pRight2++ = t_ctype[*p][1];
|
||||
*pRight3++ = t_ctype[*p][2];
|
||||
*pRight4++ = t_ctype[*p][3];
|
||||
// *pRight4++ = t_ctype[*p][3];
|
||||
len--;
|
||||
p += 2;
|
||||
} else {
|
||||
@ -486,23 +494,24 @@ static uchar* thai2sortable(const uchar * tstr,uint len)
|
||||
if(*pRight2 != IGNORE) pRight2++;
|
||||
*pRight3 = t_ctype[*p][2];
|
||||
if(*pRight3 != IGNORE) pRight3++;
|
||||
*pRight4 = t_ctype[*p][3];
|
||||
if(*pRight4 != IGNORE) pRight4++;
|
||||
/* *pRight4 = t_ctype[*p][3];
|
||||
if(*pRight4 != IGNORE) pRight4++;*/
|
||||
p++;
|
||||
}
|
||||
}
|
||||
*pRight1++ = L2_BLANK;
|
||||
*pRight2++ = L3_BLANK;
|
||||
*pRight3++ = L4_BLANK;
|
||||
*pRight4++ = '\0';
|
||||
// *pRight3++ = L4_BLANK;
|
||||
*pRight3++ = '\0';
|
||||
// *pRight4++ = '\0';
|
||||
memcpy(pRight1, pLeft2, pRight2 - pLeft2);
|
||||
pRight1 += pRight2 - pLeft2;
|
||||
memcpy(pRight1, pLeft3, pRight3 - pLeft3);
|
||||
pRight1 += pRight3 - pLeft3;
|
||||
memcpy(pRight1, pLeft4, pRight4 - pLeft4);
|
||||
// pRight1 += pRight3 - pLeft3;
|
||||
// memcpy(pRight1, pLeft4, pRight4 - pLeft4);
|
||||
free(pLeft2);
|
||||
free(pLeft3);
|
||||
free(pLeft4);
|
||||
// free(pLeft4);
|
||||
return(outBuf);
|
||||
}
|
||||
|
||||
@ -574,55 +583,58 @@ int my_strxfrm_tis620(uchar * dest, uchar * src, int len)
|
||||
Arg: String, its length, escape character, resource length, minimal string and maximum string
|
||||
Ret: Alway 0
|
||||
*/
|
||||
|
||||
/* We just copy this function from opt_range.cc. No need to convert to
|
||||
thai2sortable string. min_str and max_str will be use for comparison and
|
||||
converted there. */
|
||||
#define max_sort_chr ((char) 255)
|
||||
#define wild_one '_'
|
||||
#define wild_many '%'
|
||||
|
||||
my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
|
||||
uint res_length, char *min_str, char *max_str,
|
||||
uint *min_length,uint *max_length)
|
||||
uint *min_length, uint *max_length)
|
||||
{
|
||||
char *end;
|
||||
char *min_org= min_str;
|
||||
char *min_end = min_str + res_length;
|
||||
char *tbuff;
|
||||
uchar *tc;
|
||||
uint tbuff_length;
|
||||
const char *end=ptr+ptr_length;
|
||||
char *min_org=min_str;
|
||||
char *min_end=min_str+res_length;
|
||||
char *tmp;
|
||||
|
||||
tbuff = (char*) (tc=thai2sortable((uchar*) ptr, ptr_length));
|
||||
tbuff_length = (uint) buffsize(ptr);
|
||||
end = tbuff + tbuff_length;
|
||||
for(;tbuff != end && min_str != min_end; tbuff++)
|
||||
for (; ptr != end && min_str != min_end ; ptr++)
|
||||
{
|
||||
if(*tbuff == escape && tbuff + 1 != end)
|
||||
if (*ptr == escape && ptr+1 != end)
|
||||
{
|
||||
tbuff++;
|
||||
*min_str++ = *max_str++ = *tbuff;
|
||||
ptr++; // Skipp escape
|
||||
*min_str++= *max_str++ = *ptr;
|
||||
continue;
|
||||
}
|
||||
if(*tbuff == '_')
|
||||
if (*ptr == wild_one) // '_' in SQL
|
||||
{
|
||||
*min_str++ = '\0';
|
||||
*max_str++ = '\255';
|
||||
*min_str++='\0'; // This should be min char
|
||||
*max_str++=max_sort_chr;
|
||||
continue;
|
||||
}
|
||||
if(*tbuff == '%')
|
||||
if (*ptr == wild_many) // '%' in SQL
|
||||
{
|
||||
*min_length= (uint) (min_str - min_org);
|
||||
*max_length= res_length;
|
||||
do
|
||||
{
|
||||
*min_str++ = ' ';
|
||||
*max_str++ = '\255';
|
||||
} while(min_str != min_end);
|
||||
free(tc);
|
||||
return(0);
|
||||
*max_length=res_length;
|
||||
do {
|
||||
*min_str++ = ' '; // Because if key compression
|
||||
*max_str++ = max_sort_chr;
|
||||
} while (min_str != min_end);
|
||||
return 0;
|
||||
}
|
||||
*min_str++ = *max_str++ = *tbuff;
|
||||
*min_str++= *max_str++ = *ptr;
|
||||
}
|
||||
*min_length= *max_length = (uint) (min_str - min_org);
|
||||
while(min_str != min_end)
|
||||
{
|
||||
*min_str++ = *max_str++ = ' ';
|
||||
}
|
||||
free(tc);
|
||||
return(0);
|
||||
|
||||
/* Temporary fix for handling wild_one at end of string (key compression) */
|
||||
// for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
|
||||
// *--tmp=' ';
|
||||
|
||||
while (min_str != min_end)
|
||||
*min_str++ = *max_str++ = ' '; // Because if key compression
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Thai normalization for input sub system
|
||||
|
@ -1,188 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# This is a test with uses 4 processes to insert, delete , check and select
|
||||
#
|
||||
|
||||
$opt_loop_count=200000; # Change this to make test harder/easier
|
||||
|
||||
##################### Standard benchmark inits ##############################
|
||||
|
||||
use DBI;
|
||||
use Getopt::Long;
|
||||
use Benchmark;
|
||||
|
||||
package main;
|
||||
|
||||
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
|
||||
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
|
||||
$opt_host=""; $opt_db="test";
|
||||
|
||||
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in","skip-delete",
|
||||
"verbose","fast-insert","lock-tables","debug","fast","force") || die "Aborted";
|
||||
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
|
||||
|
||||
print "Testing 4 multiple connections to a server with 1 insert, 1 delete\n";
|
||||
print "1 select and one repair/check connection.\n";
|
||||
|
||||
$firsttable = "bench_f1";
|
||||
|
||||
####
|
||||
#### Start timeing and start test
|
||||
####
|
||||
|
||||
$start_time=new Benchmark;
|
||||
if (!$opt_skip_create)
|
||||
{
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
$dbh->do("drop table if exists $firsttable");
|
||||
|
||||
print "Creating table $firsttable in database $opt_db\n";
|
||||
$dbh->do("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
|
||||
$dbh->disconnect; $dbh=0; # Close handler
|
||||
}
|
||||
$|= 1; # Autoflush
|
||||
|
||||
####
|
||||
#### Start the tests
|
||||
####
|
||||
|
||||
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
|
||||
test_select() if (($pid=fork()) == 0); $work{$pid}="select1";
|
||||
repair_and_check() if (($pid=fork()) == 0); $work{$pid}="repair/check";
|
||||
|
||||
$errors=0;
|
||||
while (($pid=wait()) != -1)
|
||||
{
|
||||
$ret=$?/256;
|
||||
print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
|
||||
$errors++ if ($ret != 0);
|
||||
}
|
||||
|
||||
if (!$opt_skip_delete && !$errors)
|
||||
{
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
$dbh->do("drop table $firsttable");
|
||||
$dbh->disconnect; $dbh=0; # Close handler
|
||||
}
|
||||
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||
|
||||
$end_time=new Benchmark;
|
||||
print "Total time: " .
|
||||
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||
|
||||
exit(0);
|
||||
|
||||
#
|
||||
# Insert records in the table
|
||||
#
|
||||
|
||||
sub test_insert
|
||||
{
|
||||
my ($dbh,$i,$sth);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
for ($i=0 ; $i < $opt_loop_count; $i++)
|
||||
{
|
||||
$sth=$dbh->do("insert into $firsttable values ($i,'This is entry $i','')") || die "Got error on insert: $Mysql::db_errstr\n";
|
||||
$sth=0;
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_insert: Inserted $i rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub test_delete
|
||||
{
|
||||
my ($dbh,$i,$sth,@row);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||
{
|
||||
sleep(5);
|
||||
if ($opt_lock_tables)
|
||||
{
|
||||
$sth=$dbh->do("lock tables $firsttable WRITE") || die "Got error on lock tables $firsttable: $Mysql::db_errstr\n";
|
||||
}
|
||||
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on select from $firsttable: $dbh->errstr\n";
|
||||
$sth->execute || die $dbh->errstr;
|
||||
if ((@row = $sth->fetchrow_array()))
|
||||
{
|
||||
last if (!$row[0]); # Insert thread is probably ready
|
||||
}
|
||||
$sth=$dbh->do("delete from $firsttable") || die "Got error on delete from $firsttable: $dbh->errstr;\n";
|
||||
}
|
||||
$sth=0;
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_delete: Deleted all rows $i times\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# select records
|
||||
#
|
||||
|
||||
sub test_select
|
||||
{
|
||||
my ($dbh,$i,$sth,@row);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||
{
|
||||
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on select from $firsttable: $dbh->errstr;\n";
|
||||
$sth->execute || die $dbh->errstr;
|
||||
@row = $sth->fetchrow_array();
|
||||
$sth=0;
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_select: ok\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub repair_and_check
|
||||
{
|
||||
my ($dbh,$row,$found1,$last_found1,$i,$type, $table);
|
||||
$found1=0; $last_found1= -1;
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
for ($i=0; $found1 != $last_found1 ; $i++)
|
||||
{
|
||||
$type=($i & 2) ? "repair" : "check";
|
||||
$table=$firsttable;
|
||||
$last_found1=$found1;
|
||||
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $dbh->errstr\n";
|
||||
$sth->execute || die $dbh->errstr;
|
||||
|
||||
while (($row=$sth->fetchrow_arrayref))
|
||||
{
|
||||
if ($row->[3] ne "OK")
|
||||
{
|
||||
print "Got error " . $row->[3] . " when doing $type on $table\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
$sth=$dbh->prepare("select count(*) from $table") || die "Got error on prepare: $dbh->errstr\n";
|
||||
$sth->execute || die $dbh->errstr;
|
||||
@row = $sth->fetchrow_array();
|
||||
$found1= $row[0];
|
||||
$sth->finish;
|
||||
sleep(3);
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "check/repair: Did $i repair/checks\n";
|
||||
exit(0);
|
||||
}
|
449
tests/fork_big.pl
Executable file
449
tests/fork_big.pl
Executable file
@ -0,0 +1,449 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# This is a test with uses many processes to test a MySQL server.
|
||||
#
|
||||
# Tested a lot with: --threads=30
|
||||
|
||||
$opt_loop_count=200000; # Change this to make test harder/easier
|
||||
|
||||
##################### Standard benchmark inits ##############################
|
||||
|
||||
use DBI;
|
||||
use Getopt::Long;
|
||||
use Benchmark;
|
||||
|
||||
package main;
|
||||
|
||||
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
|
||||
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
|
||||
$opt_threads=5;
|
||||
$opt_host=""; $opt_db="test";
|
||||
|
||||
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","threads=i") || die "Aborted";
|
||||
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
|
||||
|
||||
print "Test of multiple connections that test the following things:\n";
|
||||
print "insert, select, delete, update, check, repair and flush\n";
|
||||
|
||||
@testtables = ( ["bench_f31", ""],
|
||||
["bench_f32", "row_format=fixed"],
|
||||
["bench_f33", "delay_key_write=1"],
|
||||
["bench_f34", "checksum=1"],
|
||||
["bench_f35", "delay_key_write=1"]);
|
||||
$abort_table="bench_f39";
|
||||
|
||||
$numtables = $#testtables+1;
|
||||
srand 100; # Make random numbers repeatable
|
||||
####
|
||||
#### Start timeing and start test
|
||||
####
|
||||
|
||||
$start_time=new Benchmark;
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
if (!$opt_skip_create)
|
||||
{
|
||||
my $table_def;
|
||||
foreach $table_def (@testtables)
|
||||
{
|
||||
my ($table,$extra)= ($table_def->[0], $table_def->[1]);
|
||||
print "Creating table $table in database $opt_db\n";
|
||||
$dbh->do("drop table if exists $table");
|
||||
$dbh->do("create table $table".
|
||||
" (id int(6) not null auto_increment,".
|
||||
" info varchar(32)," .
|
||||
" marker timestamp," .
|
||||
" flag int not null," .
|
||||
" primary key(id)) $extra")
|
||||
|
||||
or die $DBI::errstr;
|
||||
# One row in the table will make future tests easier
|
||||
$dbh->do("insert into $table (id) values (null)")
|
||||
or die $DBI::errstr;
|
||||
}
|
||||
# Create the table we use to signal that we should end the test
|
||||
$dbh->do("drop table if exists $abort_table");
|
||||
$dbh->do("create table $abort_table (id int(6) not null) type=heap") ||
|
||||
die $DBI::errstr;
|
||||
}
|
||||
|
||||
$dbh->do("delete from $abort_table");
|
||||
$dbh->disconnect; $dbh=0; # Close handler
|
||||
$|= 1; # Autoflush
|
||||
|
||||
####
|
||||
#### Start the tests
|
||||
####
|
||||
|
||||
for ($i=0 ; $i < $opt_threads ; $i ++)
|
||||
{
|
||||
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||
}
|
||||
for ($i=0 ; $i < $numtables ; $i ++)
|
||||
{
|
||||
test_insert($i,$i) if (($pid=fork()) == 0); $work{$pid}="insert_one";
|
||||
}
|
||||
for ($i=0 ; $i < $opt_threads ; $i ++)
|
||||
{
|
||||
test_select() if (($pid=fork()) == 0); $work{$pid}="select_key";
|
||||
}
|
||||
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
|
||||
test_update() if (($pid=fork()) == 0); $work{$pid}="update";
|
||||
test_flush() if (($pid=fork()) == 0); $work{$pid}= "flush";
|
||||
test_check() if (($pid=fork()) == 0); $work{$pid}="check";
|
||||
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
|
||||
|
||||
print "Started " . ($opt_threads*2+4) . " threads\n";
|
||||
|
||||
$errors=0;
|
||||
$running_insert_threads=$opt_threads+$numtables;
|
||||
while (($pid=wait()) != -1)
|
||||
{
|
||||
$ret=$?/256;
|
||||
print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
|
||||
if ($work{$pid} =~ /^insert/)
|
||||
{
|
||||
if (!--$running_insert_threads)
|
||||
{
|
||||
# Time to stop other threads
|
||||
signal_abort();
|
||||
}
|
||||
}
|
||||
$errors++ if ($ret != 0);
|
||||
}
|
||||
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
|
||||
if (!$opt_skip_delete && !$errors)
|
||||
{
|
||||
my $table_def;
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$dbh->do("drop table $abort_table");
|
||||
foreach $table_def (@testtables)
|
||||
{
|
||||
$dbh->do("drop table " . $table_def->[0]);
|
||||
}
|
||||
$dbh->disconnect; $dbh=0; # Close handler
|
||||
}
|
||||
|
||||
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||
$end_time=new Benchmark;
|
||||
print "Total time: " .
|
||||
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||
|
||||
exit(0);
|
||||
|
||||
|
||||
#
|
||||
# Insert records in the table
|
||||
#
|
||||
|
||||
sub test_insert
|
||||
{
|
||||
my ($from_table,$to_table)= @_;
|
||||
my ($dbh,$i,$j,$count,$table_def,$table);
|
||||
|
||||
if (!defined($from_table))
|
||||
{
|
||||
$from_table=0; $to_table=$numtables-1;
|
||||
}
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
for ($i=$count=0 ; $i < $opt_loop_count; $i++)
|
||||
{
|
||||
for ($j= $from_table ; $j <= $to_table ; $j++)
|
||||
{
|
||||
my ($table)= ($testtables[$j]->[0]);
|
||||
$dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_insert: Inserted $count rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# select records
|
||||
# Do continously select over all tables as long as there is changed
|
||||
# rows in the table
|
||||
#
|
||||
|
||||
sub test_select
|
||||
{
|
||||
my ($dbh, $i, $j, $count, $loop);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$count_query=make_count_query($numtables);
|
||||
$count=0;
|
||||
$loop=9999;
|
||||
|
||||
$i=0;
|
||||
while (($i++ % 100) || !test_if_abort($dbh))
|
||||
{
|
||||
if ($loop++ >= 100)
|
||||
{
|
||||
$loop=0;
|
||||
$row_counts=simple_query($dbh, $count_query);
|
||||
}
|
||||
for ($j=0 ; $j < $numtables ; $j++)
|
||||
{
|
||||
my ($id)= int rand $row_counts->[$j];
|
||||
my ($table)= $testtables[$j]->[0];
|
||||
simple_query($dbh, "select id,info from $table where id=$id");
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_select: Executed $count selects\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Delete 1-5 rows from the first 2 tables.
|
||||
# Test ends when the number of rows for table 3 didn't change during
|
||||
# one loop
|
||||
#
|
||||
|
||||
sub test_delete
|
||||
{
|
||||
my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
|
||||
|
||||
$table_count=2;
|
||||
$count=0;
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$count_query=make_count_query($table_count+1);
|
||||
|
||||
sleep(5); # Give time to insert some rows
|
||||
$i=0;
|
||||
while (($i++ % 10) || !test_if_abort($dbh))
|
||||
{
|
||||
sleep(1);
|
||||
$row_counts=simple_query($dbh, $count_query);
|
||||
|
||||
for ($j=0 ; $j < $table_count ; $j++)
|
||||
{
|
||||
my ($id)= int rand $row_counts->[$j];
|
||||
my ($table)= $testtables[$j]->[0];
|
||||
$dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_delete: Executed $count deletes\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Update the flag for table 2 and 3
|
||||
# Will abort after a while when table1 doesn't change max value
|
||||
#
|
||||
|
||||
sub test_update
|
||||
{
|
||||
my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$count_query=make_count_query(3);
|
||||
$loop=9999;
|
||||
$count=0;
|
||||
|
||||
sleep(5); # Give time to insert some rows
|
||||
$i=0;
|
||||
while (($i++ % 100) || !test_if_abort($dbh))
|
||||
{
|
||||
if ($loop++ >= 100)
|
||||
{
|
||||
$loop=0;
|
||||
$row_counts=simple_query($dbh, $count_query);
|
||||
}
|
||||
|
||||
for ($j=1 ; $j <= 2 ; $j++)
|
||||
{
|
||||
my ($id)= int rand $row_counts->[$j];
|
||||
my ($table)= $testtables[$j]->[0];
|
||||
# Fix to not change the same rows as the above delete
|
||||
$id= ($id + $count) % $row_counts->[$j];
|
||||
|
||||
$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";
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "Test_update: Executed $count updates\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Run a check on all tables except the last one
|
||||
# (The last one is not checked to put pressure on the key cache)
|
||||
#
|
||||
|
||||
sub test_check
|
||||
{
|
||||
my ($dbh, $row, $i, $j, $type, $table);
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$type= "check";
|
||||
for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
|
||||
{
|
||||
sleep(60);
|
||||
$table=$testtables[$j]->[0];
|
||||
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
|
||||
$sth->execute || die $DBI::errstr;
|
||||
|
||||
while (($row=$sth->fetchrow_arrayref))
|
||||
{
|
||||
if ($row->[3] ne "OK")
|
||||
{
|
||||
print "Got error " . $row->[3] . " when doing $type on $table\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (++$j == $numtables-1)
|
||||
{
|
||||
$j=0;
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "test_check: Executed $i checks\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Do a repair on the first table once in a while
|
||||
#
|
||||
|
||||
sub test_repair
|
||||
{
|
||||
my ($dbh, $row, $i, $type, $table);
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$type= "repair";
|
||||
for ($i=0 ; !test_if_abort($dbh) ; $i++)
|
||||
{
|
||||
sleep(95);
|
||||
$table=$testtables[0]->[0];
|
||||
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
|
||||
$sth->execute || die $DBI::errstr;
|
||||
|
||||
while (($row=$sth->fetchrow_arrayref))
|
||||
{
|
||||
if ($row->[3] ne "OK")
|
||||
{
|
||||
print "Got error " . $row->[3] . " when doing $type on $table\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "test_repair: Executed $i repairs\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Do a flush tables on table 3 and 4 once in a while
|
||||
#
|
||||
|
||||
sub test_flush
|
||||
{
|
||||
my ($dbh,$count,$tables);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
|
||||
|
||||
$count=0;
|
||||
while (!test_if_abort($dbh))
|
||||
{
|
||||
sleep(60);
|
||||
$dbh->do("flush tables $tables") ||
|
||||
die "Got error on flush $DBI::errstr\n";
|
||||
$count++;
|
||||
}
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "flush: Executed $count flushs\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Help functions
|
||||
#
|
||||
|
||||
sub signal_abort
|
||||
{
|
||||
my ($dbh);
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
$dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
|
||||
$dbh->disconnect; $dbh=0;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
sub test_if_abort()
|
||||
{
|
||||
my ($dbh)=@_;
|
||||
$row=simple_query($dbh,"select * from $abort_table");
|
||||
return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
sub make_count_query
|
||||
{
|
||||
my ($table_count)= @_;
|
||||
my ($tables, $count_query, $i, $tables_def);
|
||||
$tables="";
|
||||
$count_query="select high_priority ";
|
||||
$table_count--;
|
||||
for ($i=0 ; $i < $table_count ; $i++)
|
||||
{
|
||||
my ($table_def)= $testtables[$i];
|
||||
$tables.=$table_def->[0] . ",";
|
||||
$count_query.= "max(" . $table_def->[0] . ".id),";
|
||||
}
|
||||
$table_def=$testtables[$table_count];
|
||||
$tables.=$table_def->[0];
|
||||
$count_query.= "max(" . $table_def->[0] . ".id) from $tables";
|
||||
return $count_query;
|
||||
}
|
||||
|
||||
sub simple_query()
|
||||
{
|
||||
my ($dbh, $query)= @_;
|
||||
my ($sth,$row);
|
||||
|
||||
$sth=$dbh->prepare($query) || die "Got error on '$query': $DBI::errstr\n";
|
||||
$sth->execute || die "Got error on '$query': $dbh->errstr\n";
|
||||
$row= $sth->fetchrow_arrayref();
|
||||
$sth=0;
|
||||
return $row;
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# This is a test with uses 5 processes to insert, update and select from
|
||||
# two tables.
|
||||
# One inserts records in the tables, one updates some record in it and
|
||||
# the last 3 does different selects on the tables.
|
||||
#
|
||||
|
||||
$opt_loop_count=10000; # Change this to make test harder/easier
|
||||
|
||||
##################### Standard benchmark inits ##############################
|
||||
|
||||
use Mysql;
|
||||
use Getopt::Long;
|
||||
use Benchmark;
|
||||
|
||||
package main;
|
||||
|
||||
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
|
||||
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
|
||||
$opt_host=""; $opt_db="test";
|
||||
|
||||
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in",
|
||||
"skip-delete","verbose","fast-insert","lock-tables","debug","fast",
|
||||
"force") || die "Aborted";
|
||||
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$Mysql::db_errstr=$opt_force=undef; # Ignore warnings from these
|
||||
|
||||
print "Testing 5 multiple connections to a server with 1 insert, 1 update\n";
|
||||
print "and 3 select connections.\n";
|
||||
|
||||
|
||||
$firsttable = "bench_f1";
|
||||
$secondtable = "bench_f2";
|
||||
|
||||
####
|
||||
#### Start timeing and start test
|
||||
####
|
||||
|
||||
$start_time=new Benchmark;
|
||||
if (!$opt_skip_create)
|
||||
{
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$Mysql::QUIET = 1;
|
||||
$dbh->Query("drop table $firsttable");
|
||||
$dbh->Query("drop table $secondtable");
|
||||
$Mysql::QUIET = 0;
|
||||
|
||||
print "Creating tables $firsttable and $secondtable in database $opt_db\n";
|
||||
$dbh->Query("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") or die $Mysql::db_errstr;
|
||||
$dbh->Query("create table $secondtable (id int(6) not null, row int(3) not null,value double, primary key(id,row))") or die $Mysql::db_errstr;
|
||||
|
||||
$dbh=0; # Close handler
|
||||
}
|
||||
$|= 1; # Autoflush
|
||||
|
||||
####
|
||||
#### Start the tests
|
||||
####
|
||||
|
||||
test_1() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||
test_2() if (($pid=fork()) == 0); $work{$pid}="update";
|
||||
test_3() if (($pid=fork()) == 0); $work{$pid}="select1";
|
||||
test_4() if (($pid=fork()) == 0); $work{$pid}="select2";
|
||||
test_5() if (($pid=fork()) == 0); $work{$pid}="select3";
|
||||
|
||||
$errors=0;
|
||||
while (($pid=wait()) != -1)
|
||||
{
|
||||
$ret=$?/256;
|
||||
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
|
||||
$errors++ if ($ret != 0);
|
||||
}
|
||||
|
||||
if (!$opt_skip_delete && !$errors)
|
||||
{
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$dbh->Query("drop table $firsttable");
|
||||
$dbh->Query("drop table $secondtable");
|
||||
}
|
||||
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||
|
||||
$end_time=new Benchmark;
|
||||
print "Total time: " .
|
||||
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||
|
||||
exit(0);
|
||||
|
||||
#
|
||||
# Insert records in the two tables
|
||||
#
|
||||
|
||||
sub test_1
|
||||
{
|
||||
my ($dbh,$tmpvar,$rows,$found,$i);
|
||||
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$tmpvar=1;
|
||||
$rows=$found=0;
|
||||
for ($i=0 ; $i < $opt_loop_count; $i++)
|
||||
{
|
||||
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
|
||||
$sth=$dbh->Query("insert into $firsttable values ($i,'This is entry $i','')") || die "Got error on insert: $Mysql::db_errstr\n";
|
||||
$row_count=($i % 7)+1;
|
||||
$rows+=1+$row_count;
|
||||
for ($j=0 ; $j < $row_count; $j++)
|
||||
{
|
||||
$sth=$dbh->Query("insert into $secondtable values ($i,$j,0)") || die "Got error on insert: $Mysql::db_errstr\n";
|
||||
}
|
||||
if (($tmpvar % 10) == 0)
|
||||
{
|
||||
$sth=$dbh->Query("select max(info) from $firsttable") || die "Got error on select max(info): $Mysql::db_errstr\n";
|
||||
$sth=$dbh->Query("select max(value) from $secondtable") || die "Got error on select max(info): $Mysql::db_errstr\n";
|
||||
$found+=2;
|
||||
}
|
||||
}
|
||||
$dbh=0;
|
||||
print "Test_1: Inserted $rows rows, found $found rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Update records in both tables
|
||||
#
|
||||
|
||||
sub test_2
|
||||
{
|
||||
my ($dbh,$id,$tmpvar,$rows,$found,$i,$max_id,$tmp);
|
||||
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$tmpvar=111111;
|
||||
$rows=$found=$max_id=$id=0;
|
||||
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||
{
|
||||
$tmp=(($tmpvar + 63) + $i)*3;
|
||||
$tmp=$tmp-int($tmp/100000)*100000;
|
||||
$tmpvar^= $tmp;
|
||||
$tmp=$tmpvar - int($tmpvar/10)*10;
|
||||
if ($max_id < 2 || $tmp == 0)
|
||||
{
|
||||
$max_id=0;
|
||||
$sth=$dbh->Query("select max(id) from $firsttable where marker=''") || die "Got error select max: $Mysql::db_errstr\n";
|
||||
if ((@row = $sth->FetchRow()) && defined($row[0]))
|
||||
{
|
||||
$found++;
|
||||
$max_id=$id=$row[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$id= $tmpvar % ($max_id-1)+1;
|
||||
}
|
||||
if ($id)
|
||||
{
|
||||
$sth=$dbh->Query("update $firsttable set marker='x' where id=$id") || die "Got error update $firsttable: $Mysql::db_errstr\n";
|
||||
$rows+=$sth->affected_rows;
|
||||
if ($sth->affected_rows)
|
||||
{
|
||||
$sth=$dbh->Query("update $secondtable set value=$i where id=$id") || die "Got error update $firsttable: $Mysql::db_errstr\n";
|
||||
$rows+=$sth->affected_rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
$dbh=0;
|
||||
print "Test_2: Found $found rows, Updated $rows rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# select records
|
||||
#
|
||||
|
||||
sub test_3
|
||||
{
|
||||
my ($dbh,$id,$tmpvar,$rows,$i);
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$tmpvar=222222;
|
||||
$rows=0;
|
||||
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||
{
|
||||
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
|
||||
$id=$tmpvar % $opt_loop_count;
|
||||
$sth=$dbh->Query("select id from $firsttable where id=$id") || die "Got error on select from $firsttable: $Mysql::db_errstr\n";
|
||||
$rows+=$sth->numrows;
|
||||
}
|
||||
$dbh=0;
|
||||
print "Test_3: Found $rows rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Note that this uses row=1 and in some cases won't find any matching
|
||||
# records
|
||||
#
|
||||
|
||||
sub test_4
|
||||
{
|
||||
my ($dbh,$id,$tmpvar,$rows,$i);
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$tmpvar=333333;
|
||||
$rows=0;
|
||||
for ($i=0 ; $i < $opt_loop_count; $i++)
|
||||
{
|
||||
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
|
||||
$id=$tmpvar % $opt_loop_count;
|
||||
$sth=$dbh->Query("select id from $secondtable where id=$id") || die "Got error on select form $secondtable: $Mysql::db_errstr\n";
|
||||
$rows+=$sth->numrows;
|
||||
}
|
||||
$dbh=0;
|
||||
print "Test_4: Found $rows rows\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
sub test_5
|
||||
{
|
||||
my ($dbh,$id,$tmpvar,$rows,$i,$max_id);
|
||||
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
|
||||
$tmpvar=444444;
|
||||
$rows=$max_id=0;
|
||||
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||
{
|
||||
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
|
||||
if ($max_id == 0 || ($tmpvar % 10 == 0))
|
||||
{
|
||||
$sth=$dbh->Query("select max(id) from $firsttable") || die "Got error select max: $Mysql::db_errstr\n";
|
||||
if ((@row = $sth->FetchRow()) && defined($row[0]))
|
||||
{
|
||||
$max_id=$id=$row[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$id=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$id= $tmpvar % $max_id;
|
||||
}
|
||||
$sth=$dbh->Query("select value from $firsttable,$secondtable where $firsttable.id=$id and $secondtable.id=$firsttable.id") || die "Got error on select form $secondtable: $Mysql::db_errstr\n";
|
||||
$rows+=$sth->numrows;
|
||||
}
|
||||
$dbh=0;
|
||||
print "Test_5: Found $rows rows\n";
|
||||
exit(0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user