mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
semi-manual merge, some more needs to be fixed in mysqltest.c in fully
manual mode mysql-test/mysql-test-run.sh: Auto merged sql/lex.h: Auto merged Docs/manual.texi: merged client/mysqltest.c: merged
This commit is contained in:
@ -188,3 +188,4 @@ Docs/my_sys.doc
|
|||||||
tmp/*
|
tmp/*
|
||||||
extra/resolve_stack_dump
|
extra/resolve_stack_dump
|
||||||
sql/share/*.sys
|
sql/share/*.sys
|
||||||
|
BitKeeper/tmp/bkr3sAHD
|
||||||
|
211
Docs/manual.texi
211
Docs/manual.texi
@ -17401,6 +17401,17 @@ Addresses may be 4 or 8 byte addresses:
|
|||||||
mysql> select INET_ATON("209.207.224.40");
|
mysql> select INET_ATON("209.207.224.40");
|
||||||
-> 3520061480
|
-> 3520061480
|
||||||
@end example
|
@end example
|
||||||
|
@findex MASTER_POS_WAIT()
|
||||||
|
@item MASTER_POS_WAIT(log_name, log_pos)
|
||||||
|
Blocks until the slave reaches the specified position in the master log during
|
||||||
|
replication. If master information is not initialized, returns NULL. If the
|
||||||
|
slave is not running, will block and wait until it is started and goes to or
|
||||||
|
past
|
||||||
|
the specified postion. If the slave is already past the specified postion,
|
||||||
|
returns immediately. The return value is the number of log events it had to
|
||||||
|
wait to get to the specified position, or NULL in case of error. Useful for
|
||||||
|
control of master-slave synchronization, but was originally written to
|
||||||
|
facilate replication testing.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@findex GROUP BY functions
|
@findex GROUP BY functions
|
||||||
@ -25618,6 +25629,7 @@ tables}.
|
|||||||
* Replication Options:: Replication Options in my.cnf
|
* Replication Options:: Replication Options in my.cnf
|
||||||
* Replication SQL:: SQL Commands related to replication
|
* Replication SQL:: SQL Commands related to replication
|
||||||
* Replication FAQ:: Frequently Asked Questions about replication
|
* Replication FAQ:: Frequently Asked Questions about replication
|
||||||
|
* Troubleshooting Replication:: Troubleshooting Replication
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Replication Intro, Replication Implementation, Replication, Replication
|
@node Replication Intro, Replication Implementation, Replication, Replication
|
||||||
@ -25634,7 +25646,7 @@ Starting in Version 3.23.15, @strong{MySQL} supports one-way replication
|
|||||||
internally. One server acts as the master, while the other acts as the
|
internally. One server acts as the master, while the other acts as the
|
||||||
slave. Note that one server could play the roles of master in one pair
|
slave. Note that one server could play the roles of master in one pair
|
||||||
and slave in the other. The master server keeps a binary log of updates
|
and slave in the other. The master server keeps a binary log of updates
|
||||||
(@xref{Binary log}.) and an index file of binary logs to keep track of
|
(@xref{Binary log}.) and an index file to binary logs to keep track of
|
||||||
log rotation. The slave, upon connecting, informs the master where it
|
log rotation. The slave, upon connecting, informs the master where it
|
||||||
left off since the last successfully propagated update, catches up on
|
left off since the last successfully propagated update, catches up on
|
||||||
the updates, and then blocks and waits for the master to notify it of
|
the updates, and then blocks and waits for the master to notify it of
|
||||||
@ -25656,7 +25668,7 @@ master. @xref{Backup}.
|
|||||||
|
|
||||||
@strong{MySQL} replication is based on the server keeping track of all
|
@strong{MySQL} replication is based on the server keeping track of all
|
||||||
changes to your database (updates, deletes, etc) in the binary
|
changes to your database (updates, deletes, etc) in the binary
|
||||||
log (@xref{Binary log}.), and the slave server(s) reading the saved
|
log. (@xref{Binary log}.) and the slave server(s) reading the saved
|
||||||
queries from the master server's binary log so that the slave can
|
queries from the master server's binary log so that the slave can
|
||||||
execute the same queries on its copy of the data.
|
execute the same queries on its copy of the data.
|
||||||
|
|
||||||
@ -25668,9 +25680,11 @@ logging on the master. If you start your slaves with data that doesn't
|
|||||||
agree with what was on the master @strong{when the binary log was
|
agree with what was on the master @strong{when the binary log was
|
||||||
started}, your slaves may fail.
|
started}, your slaves may fail.
|
||||||
|
|
||||||
A future Version of @strong{MySQL} is planned remove the need to keep a
|
A future version (4.0) of @strong{MySQL} will remove the need to keep a
|
||||||
(possibly large) snapshot of data for new slaves that you might wish to
|
(possibly large) snapshot of data for new slaves that you might wish to
|
||||||
set up.
|
set up through the live backup functionality with no locking required.
|
||||||
|
However, at this time, it is necessary to block all writes either with a
|
||||||
|
global read lock or by shutting down the master while taking a snapshot.
|
||||||
|
|
||||||
Once a slave is properly configured and running, it will simply connect
|
Once a slave is properly configured and running, it will simply connect
|
||||||
to the master and wait for updates to process. If the master goes away
|
to the master and wait for updates to process. If the master goes away
|
||||||
@ -25690,20 +25704,20 @@ The next section explains the master/slave setup process in more detail.
|
|||||||
Below is a quick description of how to set up complete replication on
|
Below is a quick description of how to set up complete replication on
|
||||||
your current @strong{MySQL} server. It assumes you want to replicate all
|
your current @strong{MySQL} server. It assumes you want to replicate all
|
||||||
your databases and have not configured replication before. You will need
|
your databases and have not configured replication before. You will need
|
||||||
to shutdown your master server briefly to complete the steps outlined
|
to shutdown your master server briefly to complete the steops outlined
|
||||||
below.
|
below.
|
||||||
|
|
||||||
@enumerate
|
@enumerate
|
||||||
@item
|
@item
|
||||||
Make sure you have a recent version of @strong{MySQL} installed on the
|
Make you have a recent version of @strong{MySQL} installed on the master
|
||||||
master and slave(s).
|
and slave(s).
|
||||||
|
|
||||||
Use Version 3.23.29 or higher. Previous releases used a different binary
|
Use Version 3.23.29 or higher. Previous releases used a different binary
|
||||||
log format and had bugs which have been fixed in newer releases. Please
|
log format and had bugs which have been fixed in newer releases. Please,
|
||||||
do not report bugs until you have verified that the problem is present
|
do not report bugs until you have verified that the problem is present
|
||||||
in the latest release.
|
in the latest release.
|
||||||
@item
|
@item
|
||||||
Set up a special replication user on the master with the @code{FILE}
|
Set up special a replication user on the master with the @code{FILE}
|
||||||
privilege and permission to connect from all the slaves. If the user is
|
privilege and permission to connect from all the slaves. If the user is
|
||||||
only doing replication (which is recommended), you don't need to grant any
|
only doing replication (which is recommended), you don't need to grant any
|
||||||
additional privileges.
|
additional privileges.
|
||||||
@ -25726,7 +25740,7 @@ mysqladmin -u root -p<password> shutdown
|
|||||||
Snapshot all the data on your master server.
|
Snapshot all the data on your master server.
|
||||||
|
|
||||||
The easiest way to do this (on Unix) is to simply use @strong{tar} to
|
The easiest way to do this (on Unix) is to simply use @strong{tar} to
|
||||||
produce an archive of your entrie data directory. The exact data
|
produce an archvie of your entrie data directory. The exact data
|
||||||
directory location depends on your installation.
|
directory location depends on your installation.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@ -25738,8 +25752,11 @@ the data directory.
|
|||||||
|
|
||||||
@item
|
@item
|
||||||
In @code{my.cnf} on the master add @code{log-bin} and
|
In @code{my.cnf} on the master add @code{log-bin} and
|
||||||
@code{server-id=<some unique number>} to the @code{[mysqld]} section.
|
@code{server-id=unique number} to the @code{[mysqld]} section and
|
||||||
|
restart it. It is very important that the id of the slave is different from
|
||||||
|
the id of the master. Think of @code{server-id} as something similar
|
||||||
|
to the IP address - it uniquely identifies the server instance in the
|
||||||
|
comminity of replication partners.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
[mysqld]
|
[mysqld]
|
||||||
@ -25764,7 +25781,12 @@ replacing the values in <> with what is relevant to your system.
|
|||||||
|
|
||||||
@code{server-id} must be different for each server participating in
|
@code{server-id} must be different for each server participating in
|
||||||
replication. If you don't specify a server-id, it will be set to 1 if
|
replication. If you don't specify a server-id, it will be set to 1 if
|
||||||
you have not defined @code{master-host}, else it will be set to 2.
|
you have not defined @code{master-host}, else it will be set to 2. Note
|
||||||
|
that in the case of @code{server-id} omission the master will refuse
|
||||||
|
connections from all slaves, and the slave will refuse to connect to a
|
||||||
|
master. Thus, omitting @code{server-id} is only good for backup with a
|
||||||
|
binary log.
|
||||||
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Copy the snapshot data into your data directory on your slave(s). Make
|
Copy the snapshot data into your data directory on your slave(s). Make
|
||||||
@ -25794,10 +25816,11 @@ If a slave is not able to replicate for any reason, you will find error
|
|||||||
messages in the error log on the slave.
|
messages in the error log on the slave.
|
||||||
|
|
||||||
Once a slave is replicating, you will find a file called
|
Once a slave is replicating, you will find a file called
|
||||||
@code{master.info} in the same directory as your error log. The
|
@code{master.info} in the same directory as your error log. The
|
||||||
@code{master.info} file is used by the slave to keep track of how much
|
@code{master.info} file is used by the slave to keep track of how much
|
||||||
of the master's binary log it has processed. @strong{Do not} remove or
|
of the master's binary log is has processed. @strong{Do not} remove or
|
||||||
edit this file.
|
edit the file, unless you really know what you are doing. Even in that case,
|
||||||
|
it is preferred that you use @code{CHANGE MASTER TO} command.
|
||||||
|
|
||||||
@cindex options, replication
|
@cindex options, replication
|
||||||
@cindex @code{my.cnf} file
|
@cindex @code{my.cnf} file
|
||||||
@ -25812,20 +25835,16 @@ Below is an explanation of what is supported and what is not:
|
|||||||
Replication will be done correctly with @code{AUTO_INCREMENT},
|
Replication will be done correctly with @code{AUTO_INCREMENT},
|
||||||
@code{LAST_INSERT_ID}, and @code{TIMESTAMP} values.
|
@code{LAST_INSERT_ID}, and @code{TIMESTAMP} values.
|
||||||
@item
|
@item
|
||||||
|
@code{RAND()} in updates does not replicate properly. Use
|
||||||
|
@code{RAND(some_non_rand_expr)} if you are replcating updates with
|
||||||
|
@code{RAND()}. You can, for example, use @code{UNIX_TIMESTAMP()} for the
|
||||||
|
argument to @code{RAND()}.
|
||||||
|
@item
|
||||||
@code{LOAD DATA INFILE} will be handled properly as long as the file
|
@code{LOAD DATA INFILE} will be handled properly as long as the file
|
||||||
still resides on the master server at the time of update
|
still resides on the master server at the time of update
|
||||||
propagation. @code{LOAD LOCAL DATA INFILE} will be skipped.
|
propagation. @code{LOAD LOCAL DATA INFILE} will be skipped.
|
||||||
@item
|
@item
|
||||||
The master and slave is not synchronizing @code{RAND()}. This means
|
Update queries that use user variables are not replication-safe (yet).
|
||||||
that you should not use @code{RAND()} with any statement that updates a
|
|
||||||
table. As fixing this will require a change in the protocol, we will
|
|
||||||
delay fixing this until 4.0. A workaround is using @code{RAND(#)}, where
|
|
||||||
# is a random integer genearated by your application or by first
|
|
||||||
executing @code{LAST_INSERT_ID(RAND())} and then using
|
|
||||||
@code{LAST_INSERT_ID()} in the next statement.
|
|
||||||
@item
|
|
||||||
Update queries that use user variables (@code{@@variable}) are not yet
|
|
||||||
replication-safe.
|
|
||||||
@item
|
@item
|
||||||
Temporary tables starting in 3.23.29 are replicated properly with the
|
Temporary tables starting in 3.23.29 are replicated properly with the
|
||||||
exception of the case when you shut down slave server ( not just slave thread),
|
exception of the case when you shut down slave server ( not just slave thread),
|
||||||
@ -25892,15 +25911,17 @@ Starting in Version 3.23.19, you can clean up stale replication leftovers when
|
|||||||
something goes wrong and you want a clean start with @code{FLUSH MASTER}
|
something goes wrong and you want a clean start with @code{FLUSH MASTER}
|
||||||
and @code{FLUSH SLAVE} commands. In Version 3.23.26 we have renamed them to
|
and @code{FLUSH SLAVE} commands. In Version 3.23.26 we have renamed them to
|
||||||
@code{RESET MASTER} and @code{RESET SLAVE} respectively to clarify
|
@code{RESET MASTER} and @code{RESET SLAVE} respectively to clarify
|
||||||
what they do. The old @code{FLUSH} variants still work, though for
|
what they do. The old @code{FLUSH} variants still work, though, for
|
||||||
compatibility.
|
compatibility.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Starting in Version 3.23.21, you can use @code{LOAD TABLE FROM MASTER} for
|
Starting in Version 3.23.21, you can use @code{LOAD TABLE FROM MASTER} for
|
||||||
network backup and to set up replication initially.
|
network backup and to set up replication initially. We have recently
|
||||||
|
received a number of bug reports concerning it that we are investigating, so
|
||||||
|
we recommend that you use it only in testing until we make it more stable.
|
||||||
@item
|
@item
|
||||||
Starting in Version 3.23.23, you can change masters with @code{CHANGE MASTER
|
Starting in Version 3.23.23, you can change masters and adjust log position
|
||||||
TO}.
|
with @code{CHANGE MASTER TO}.
|
||||||
@item
|
@item
|
||||||
Starting in Version 3.23.23, you tell the master that updates in certain
|
Starting in Version 3.23.23, you tell the master that updates in certain
|
||||||
databases should not be logged to the binary log with @code{binlog-ignore-db}.
|
databases should not be logged to the binary log with @code{binlog-ignore-db}.
|
||||||
@ -25916,7 +25937,7 @@ to get rid of old logs while the slave is running.
|
|||||||
@node Replication Options, Replication SQL, Replication Features, Replication
|
@node Replication Options, Replication SQL, Replication Features, Replication
|
||||||
@section Replication Options in my.cnf
|
@section Replication Options in my.cnf
|
||||||
|
|
||||||
If you are using replication, we recommend you to use MySQL Version 3.23.28 or
|
If you are using replication, we recommend you to use MySQL Version 3.23.30 or
|
||||||
later. Older versions work, but they do have some bugs and are missing some
|
later. Older versions work, but they do have some bugs and are missing some
|
||||||
features.
|
features.
|
||||||
|
|
||||||
@ -26169,8 +26190,8 @@ last log on the list), backup all the logs you are about to delete
|
|||||||
|
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
@node Replication FAQ, , Replication SQL, Replication
|
@node Replication FAQ,Troubleshooting Replication, Replication SQL, Replication
|
||||||
@section Frequently Asked Questions about replication
|
@section Replication FAQ
|
||||||
|
|
||||||
@cindex @code{Binlog_Dump}
|
@cindex @code{Binlog_Dump}
|
||||||
@strong{Q}: Why do I sometimes see more than one @code{Binlog_Dump} thread on
|
@strong{Q}: Why do I sometimes see more than one @code{Binlog_Dump} thread on
|
||||||
@ -26227,11 +26248,10 @@ the slave can stay down for some time - since the master is logging
|
|||||||
all the updates, the slave will be able to catch up once it is up and
|
all the updates, the slave will be able to catch up once it is up and
|
||||||
can connect.
|
can connect.
|
||||||
|
|
||||||
We plan to make post 3.23.26 versions to be backwards compatible
|
After 3.23.26, we have locked the replication protocol for modifications, so
|
||||||
for replication down to Version 3.23.26, so upgrade should be just a matter
|
you can upgrade masters and slave on the fly to a newer 3.23 version and you
|
||||||
of plug and play. Of course, as one joke goes, plug and play works
|
can have different versions of @code{MySQL} running on the slave and the
|
||||||
usually only 50% of the time - just the plug part. We hope to do much
|
master, as long as they are both newer than 3.23.26.
|
||||||
better than that, though.
|
|
||||||
|
|
||||||
@cindex replication, two-way
|
@cindex replication, two-way
|
||||||
@strong{Q}: What issues should I be aware of when setting up two-way
|
@strong{Q}: What issues should I be aware of when setting up two-way
|
||||||
@ -26251,10 +26271,6 @@ two-way replication relationship, unless you are sure that you updates
|
|||||||
can safely happen in any order, or unless you take care of mis-ordered
|
can safely happen in any order, or unless you take care of mis-ordered
|
||||||
updates somehow in the client code.
|
updates somehow in the client code.
|
||||||
|
|
||||||
Until we implement @code{server_id} variable, you cannot have more than
|
|
||||||
two servers in a co-master replication relationship, and you must
|
|
||||||
run @code{mysqld} without @code{log-slave-updates} (default) to avoid
|
|
||||||
infinite update loops.
|
|
||||||
|
|
||||||
You must also realize that two-way replication actually does not improve
|
You must also realize that two-way replication actually does not improve
|
||||||
performance very much, if at all, as far as updates are concerned. Both
|
performance very much, if at all, as far as updates are concerned. Both
|
||||||
@ -26365,7 +26381,7 @@ to all servers)
|
|||||||
|
|
||||||
So if N = 0, which means we have no replication, our system can handle
|
So if N = 0, which means we have no replication, our system can handle
|
||||||
1200/11, about 109 writes per second (which means we will have 9 times
|
1200/11, about 109 writes per second (which means we will have 9 times
|
||||||
as many reads to the nature of our application).
|
as many reads due to the nature of our application).
|
||||||
|
|
||||||
If N = 1, we can get up to 184 writes per second.
|
If N = 1, we can get up to 184 writes per second.
|
||||||
|
|
||||||
@ -26428,6 +26444,105 @@ We are currently working on intergrating an automatic master election
|
|||||||
system into @strong{MySQL}, but until it is ready, you will have to
|
system into @strong{MySQL}, but until it is ready, you will have to
|
||||||
create your own monitoring tools.
|
create your own monitoring tools.
|
||||||
|
|
||||||
|
@node Troubleshooting Replication, ,Replication FAQ, Replication
|
||||||
|
@section Troubleshooting Replication
|
||||||
|
|
||||||
|
If you have followed the instructions, and your replication setup is not
|
||||||
|
working, first elliminate the user error factor by checking the following:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Is the master logging to the binary log? Check with @code{SHOW MASTER STATUS}.
|
||||||
|
If it is, @code{Position} will be non-zero. If not, verify that you have
|
||||||
|
given the master @code{log-bin} option and have set @code{server-id}.
|
||||||
|
@item
|
||||||
|
Is the slave running? Check with @code{SHOW SLAVE STATUS}. The answer is found
|
||||||
|
in @code{Slave_running} column. If not, verify slave options and check the
|
||||||
|
error log for messages.
|
||||||
|
@item
|
||||||
|
If the slave is running, did it establish connection with the master? Do
|
||||||
|
@code{SHOW PROCESSLIST}, find the thread with @code{system user} value in
|
||||||
|
@code{User} column and @code{none} in the @code{Host} column, and check the
|
||||||
|
@code{State} column. If it says @code{connecting to master}, verify the
|
||||||
|
privileges for the replication user on the master, master host name, your
|
||||||
|
DNS setup, whether the master is actually running, whether it is reachable
|
||||||
|
from the slave, and if all that seems ok, read the error logs.
|
||||||
|
@item
|
||||||
|
If the slave was running, but then stopped, check the error logs. It usually
|
||||||
|
happens when some query that succeeded on the master fails on the slave. This
|
||||||
|
should never happen if you have taken a proper snapshot of the master, and
|
||||||
|
never modify the data on the slave outside of the slave thread. If it does,
|
||||||
|
it is a bug, read below on how to report it.
|
||||||
|
@item
|
||||||
|
Make sure you are not running into an old bug by upgrading to the most recent
|
||||||
|
version.
|
||||||
|
@item
|
||||||
|
If all else fails, read the error logs. If they are big,
|
||||||
|
@code{grep -i slave /path/to/your-log.err} on the slave. There is no
|
||||||
|
generic pattern to search for on the master, as the only errors it logs
|
||||||
|
are general system errors - if it can, it will send the error to the slave
|
||||||
|
when things go wrong.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
When you have determined that there is no user error involved, and replication
|
||||||
|
still either does not work at all or is unstable, it is time to start working
|
||||||
|
on a bug report. We need to get as much info as possible from you to be able
|
||||||
|
to track down the bug. Please do spend some time and effort preparing a good
|
||||||
|
bug report. Ideally, we would like to have a test case in the format found in
|
||||||
|
@code{mysql-test/t/rpl*} directory of the source tree. If you submit a test
|
||||||
|
case like that, you can expect a patch within a day or two in most cases,
|
||||||
|
although, of course, you mileage may vary depending on a number of factors.
|
||||||
|
|
||||||
|
Second best option is a just program with easily configurable connection
|
||||||
|
arguments for the master and the slave that will demonstrate the problem on our
|
||||||
|
systems. You can write one in Perl or in C, depending on which language you
|
||||||
|
know better.
|
||||||
|
|
||||||
|
If you have one of the above ways to demonstrate the bug, use
|
||||||
|
@code{mysqlbug} to prepare a bug report and send it to
|
||||||
|
@email{bugs@@lists.mysql.com}. If you have a phantom - a problem that
|
||||||
|
does occur but you cannot duplicate "at will":
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Verify that there is no user error involved. For example, if you update the
|
||||||
|
slave outside of the slave thread, the data will be out of sync, and you can
|
||||||
|
have unique key violations on updates, in which case the slave thread will
|
||||||
|
stop and wait for you to clean up the tables manually to bring them in sync.
|
||||||
|
@item
|
||||||
|
Run slave with @code{log-slave-updates} and @code{log-bin} - this will keep
|
||||||
|
a log of all updates on the slave.
|
||||||
|
@item
|
||||||
|
Save all evidence before reseting the replication. If we have no or only
|
||||||
|
sketchy information, it would take us a while to track down the problem. The
|
||||||
|
evidence you should collect is:
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
all binary logs on the master
|
||||||
|
@item
|
||||||
|
all binary log on the slave
|
||||||
|
@item
|
||||||
|
the output of @code{SHOW MASTER STATUS} on the master at the time
|
||||||
|
you have discovered the problem
|
||||||
|
@item
|
||||||
|
the output of @code{SHOW SLAVE STATUS} on the master at the time
|
||||||
|
you have discovered the problem
|
||||||
|
@item
|
||||||
|
Error logs on the master and on the slave
|
||||||
|
@end itemize
|
||||||
|
@item
|
||||||
|
Use @code{mysqlbinlog} to examine the binary logs. The following should
|
||||||
|
be helpful
|
||||||
|
to find the trouble query, for example:
|
||||||
|
@example
|
||||||
|
mysqlbinlog -j pos_from_slave_status /path/to/log_from_slave_status | head
|
||||||
|
@end example
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Once you have collected the evidence on the phantom problem, try hard to
|
||||||
|
isolate it into a separate test case first. Then report the problem to
|
||||||
|
@email{bugs@@lists.mysql.com} with as much info as possible.
|
||||||
|
|
||||||
|
|
||||||
@cindex performance, maximizing
|
@cindex performance, maximizing
|
||||||
@cindex optimization
|
@cindex optimization
|
||||||
@ -40439,6 +40554,7 @@ version. The replication and BerkeleyDB code is still under development,
|
|||||||
though, so Version 3.23 is not released as a stable version yet.
|
though, so Version 3.23 is not released as a stable version yet.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
|
* News-3.23.32:: Changes in release 3.23.32
|
||||||
* News-3.23.31:: Changes in release 3.23.31
|
* News-3.23.31:: Changes in release 3.23.31
|
||||||
* News-3.23.30:: Changes in release 3.23.30
|
* News-3.23.30:: Changes in release 3.23.30
|
||||||
* News-3.23.29:: Changes in release 3.23.29
|
* News-3.23.29:: Changes in release 3.23.29
|
||||||
@ -40473,7 +40589,14 @@ though, so Version 3.23 is not released as a stable version yet.
|
|||||||
* News-3.23.0:: Changes in release 3.23.0
|
* News-3.23.0:: Changes in release 3.23.0
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node News-3.23.31, News-3.23.30, News-3.23.x, News-3.23.x
|
@node News-3.23.32, News-3.23.31, News-3.23.x, News-3.23.x
|
||||||
|
@appendixsubsec Changes in release 3.23.32
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Added MASTER_POS_WAIT()
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@node News-3.23.31, News-3.23.30, News-3.23.32, News-3.23.x
|
||||||
@appendixsubsec Changes in release 3.23.31
|
@appendixsubsec Changes in release 3.23.31
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
@ -125,6 +125,7 @@ static char *current_host,*current_db,*current_user=0,*opt_password=0,
|
|||||||
*default_charset;
|
*default_charset;
|
||||||
static char *histfile;
|
static char *histfile;
|
||||||
static String glob_buffer,old_buffer;
|
static String glob_buffer,old_buffer;
|
||||||
|
static int wait_time = 5;
|
||||||
static STATUS status;
|
static STATUS status;
|
||||||
static ulong select_limit,max_join_size,opt_connect_timeout=0;
|
static ulong select_limit,max_join_size,opt_connect_timeout=0;
|
||||||
static char default_pager[FN_REFLEN];
|
static char default_pager[FN_REFLEN];
|
||||||
@ -427,7 +428,7 @@ static struct option long_options[] =
|
|||||||
{"verbose", no_argument, 0, 'v'},
|
{"verbose", no_argument, 0, 'v'},
|
||||||
{"version", no_argument, 0, 'V'},
|
{"version", no_argument, 0, 'V'},
|
||||||
{"vertical", no_argument, 0, 'E'},
|
{"vertical", no_argument, 0, 'E'},
|
||||||
{"wait", no_argument, 0, 'w'},
|
{"wait", optional_argument, 0, 'w'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -560,7 +561,7 @@ static int get_options(int argc, char **argv)
|
|||||||
|
|
||||||
set_all_changeable_vars(changeable_vars);
|
set_all_changeable_vars(changeable_vars);
|
||||||
while ((c=getopt_long(argc,argv,
|
while ((c=getopt_long(argc,argv,
|
||||||
"?ABCD:LfgGHinNoqrstTU::vVwWEe:h:O:P:S:u:#::p::",
|
"?ABCD:LfgGHinNoqrstTU::vVw::WEe:h:O:P:S:u:#::p::",
|
||||||
long_options, &option_index)) != EOF)
|
long_options, &option_index)) != EOF)
|
||||||
{
|
{
|
||||||
switch(c) {
|
switch(c) {
|
||||||
@ -664,7 +665,10 @@ static int get_options(int argc, char **argv)
|
|||||||
case 'n': unbuffered=1; break;
|
case 'n': unbuffered=1; break;
|
||||||
case 'v': verbose++; break;
|
case 'v': verbose++; break;
|
||||||
case 'E': vertical=1; break;
|
case 'E': vertical=1; break;
|
||||||
case 'w': wait_flag=1; break;
|
case 'w':
|
||||||
|
wait_flag=1;
|
||||||
|
if(optarg) wait_time = atoi(optarg) ;
|
||||||
|
break;
|
||||||
case 'A': no_rehash=1; break;
|
case 'A': no_rehash=1; break;
|
||||||
case 'G': no_named_cmds=0; break;
|
case 'G': no_named_cmds=0; break;
|
||||||
case 'g': no_named_cmds=1; break;
|
case 'g': no_named_cmds=1; break;
|
||||||
@ -2114,7 +2118,7 @@ sql_connect(char *host,char *database,char *user,char *password,uint silent)
|
|||||||
message=1;
|
message=1;
|
||||||
tee_fputs("Waiting",stderr); (void) fflush(stderr);
|
tee_fputs("Waiting",stderr); (void) fflush(stderr);
|
||||||
}
|
}
|
||||||
(void) sleep(5);
|
(void) sleep(wait_time);
|
||||||
if (!silent)
|
if (!silent)
|
||||||
{
|
{
|
||||||
putc('.',stderr); (void) fflush(stderr);
|
putc('.',stderr); (void) fflush(stderr);
|
||||||
|
@ -93,6 +93,12 @@ static uint global_expected_errno[MAX_EXPECTED_ERRORS];
|
|||||||
|
|
||||||
DYNAMIC_ARRAY q_lines;
|
DYNAMIC_ARRAY q_lines;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char file[FN_REFLEN];
|
||||||
|
ulong pos;
|
||||||
|
} MASTER_POS ;
|
||||||
|
|
||||||
struct connection
|
struct connection
|
||||||
{
|
{
|
||||||
MYSQL mysql;
|
MYSQL mysql;
|
||||||
@ -106,6 +112,7 @@ typedef
|
|||||||
} PARSER;
|
} PARSER;
|
||||||
|
|
||||||
PARSER parser;
|
PARSER parser;
|
||||||
|
MASTER_POS master_pos;
|
||||||
int block_ok = 1; /* set to 0 if the current block should not be executed */
|
int block_ok = 1; /* set to 0 if the current block should not be executed */
|
||||||
int false_block_depth = 0;
|
int false_block_depth = 0;
|
||||||
const char* result_file = 0; /* if set, all results are concated and
|
const char* result_file = 0; /* if set, all results are concated and
|
||||||
@ -139,13 +146,15 @@ struct st_query
|
|||||||
enum { Q_CONNECTION=1, Q_QUERY, Q_CONNECT,
|
enum { Q_CONNECTION=1, Q_QUERY, Q_CONNECT,
|
||||||
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
|
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
|
||||||
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
|
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
|
||||||
Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_ERROR,
|
Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_SAVE_MASTER_POS,
|
||||||
|
Q_SYNC_WITH_MASTER,
|
||||||
Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type;
|
Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *command_names[] = {
|
const char *command_names[] = {
|
||||||
"connection", "query","connect","sleep","inc","dec","source","disconnect",
|
"connection", "query","connect","sleep","inc","dec","source","disconnect",
|
||||||
"let","echo","while","end","system","result", "require","error",0
|
"let","echo","while","end","system","result", "require", "save_master_pos",
|
||||||
|
"sync_with_master", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
TYPELIB command_typelib= {array_elements(command_names),"",
|
TYPELIB command_typelib= {array_elements(command_names),"",
|
||||||
@ -473,6 +482,50 @@ int do_echo(struct st_query* q)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int do_sync_with_master()
|
||||||
|
{
|
||||||
|
MYSQL_RES* res;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
MYSQL* mysql = &cur_con->mysql;
|
||||||
|
char query_buf[FN_REFLEN+128];
|
||||||
|
sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
|
||||||
|
master_pos.pos);
|
||||||
|
if(mysql_query(mysql, query_buf))
|
||||||
|
die("At line %u: failed in %s: %d: %s", start_lineno, query_buf,
|
||||||
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
|
||||||
|
if(!(res = mysql_store_result(mysql)))
|
||||||
|
die("line %u: mysql_store_result() retuned NULL", start_lineno);
|
||||||
|
if(!(row = mysql_fetch_row(res)))
|
||||||
|
die("line %u: empty result in %s", start_lineno, query_buf);
|
||||||
|
if(!row[0])
|
||||||
|
die("Error on slave while syncing with master");
|
||||||
|
mysql_free_result(res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_save_master_pos()
|
||||||
|
{
|
||||||
|
MYSQL_RES* res;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
MYSQL* mysql = &cur_con->mysql;
|
||||||
|
if(mysql_query(mysql, "show master status"))
|
||||||
|
die("At line %u: failed in show master status: %d: %s", start_lineno,
|
||||||
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
|
||||||
|
if(!(res = mysql_store_result(mysql)))
|
||||||
|
die("line %u: mysql_store_result() retuned NULL", start_lineno);
|
||||||
|
if(!(row = mysql_fetch_row(res)))
|
||||||
|
die("line %u: empty result in show master status", start_lineno);
|
||||||
|
strncpy(master_pos.file, row[0], sizeof(master_pos.file));
|
||||||
|
master_pos.pos = strtoul(row[1], (char**) 0, 10);
|
||||||
|
mysql_free_result(res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int do_let(struct st_query* q)
|
int do_let(struct st_query* q)
|
||||||
{
|
{
|
||||||
char* p=q->first_argument;
|
char* p=q->first_argument;
|
||||||
@ -1326,6 +1379,7 @@ int main(int argc, char** argv)
|
|||||||
cur_con = cons;
|
cur_con = cons;
|
||||||
|
|
||||||
memset(file_stack, 0, sizeof(file_stack));
|
memset(file_stack, 0, sizeof(file_stack));
|
||||||
|
memset(&master_pos, 0, sizeof(master_pos));
|
||||||
file_stack_end = file_stack + MAX_INCLUDE_DEPTH;
|
file_stack_end = file_stack + MAX_INCLUDE_DEPTH;
|
||||||
cur_file = file_stack;
|
cur_file = file_stack;
|
||||||
lineno = lineno_stack;
|
lineno = lineno_stack;
|
||||||
@ -1391,6 +1445,8 @@ int main(int argc, char** argv)
|
|||||||
get_file_name(save_file,q);
|
get_file_name(save_file,q);
|
||||||
require_file=1;
|
require_file=1;
|
||||||
break;
|
break;
|
||||||
|
case Q_SAVE_MASTER_POS: do_save_master_pos(q); break;
|
||||||
|
case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
|
||||||
case Q_COMMENT: /* Ignore row */
|
case Q_COMMENT: /* Ignore row */
|
||||||
case Q_COMMENT_WITH_COMMAND:
|
case Q_COMMENT_WITH_COMMAND:
|
||||||
default: processed = 0; break;
|
default: processed = 0; break;
|
||||||
|
@ -194,11 +194,13 @@ if [ x$SOURCE_DIST = x1 ] ; then
|
|||||||
MYSQLD="$BASEDIR/sql/mysqld"
|
MYSQLD="$BASEDIR/sql/mysqld"
|
||||||
MYSQL_TEST="$BASEDIR/client/mysqltest"
|
MYSQL_TEST="$BASEDIR/client/mysqltest"
|
||||||
MYSQLADMIN="$BASEDIR/client/mysqladmin"
|
MYSQLADMIN="$BASEDIR/client/mysqladmin"
|
||||||
|
MYSQL="$BASEDIR/client/mysql"
|
||||||
INSTALL_DB="./install_test_db"
|
INSTALL_DB="./install_test_db"
|
||||||
else
|
else
|
||||||
MYSQLD="$BASEDIR/bin/mysqld"
|
MYSQLD="$BASEDIR/bin/mysqld"
|
||||||
MYSQL_TEST="$BASEDIR/bin/mysqltest"
|
MYSQL_TEST="$BASEDIR/bin/mysqltest"
|
||||||
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
|
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
|
||||||
|
MYSQL="$BASEDIR/bin/mysql"
|
||||||
INSTALL_DB="./install_test_db -bin"
|
INSTALL_DB="./install_test_db -bin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -235,6 +237,11 @@ SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov
|
|||||||
#++
|
#++
|
||||||
# Function Definitions
|
# Function Definitions
|
||||||
#--
|
#--
|
||||||
|
wait_for_server_start ()
|
||||||
|
{
|
||||||
|
$MYSQL -e "select 1" --silent -w1 --host=127.0.0.1 --port=$1 \
|
||||||
|
>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
prompt_user ()
|
prompt_user ()
|
||||||
{
|
{
|
||||||
@ -325,6 +332,7 @@ gcov_collect () {
|
|||||||
$ECHO "gcov info in $GCOV_MSG, errors in $GCOV_ERR"
|
$ECHO "gcov info in $GCOV_MSG, errors in $GCOV_ERR"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
start_master()
|
start_master()
|
||||||
{
|
{
|
||||||
[ x$MASTER_RUNNING = 1 ] && return
|
[ x$MASTER_RUNNING = 1 ] && return
|
||||||
@ -359,6 +367,7 @@ start_master()
|
|||||||
else
|
else
|
||||||
$MYSQLD $master_args >> $MASTER_MYERR 2>&1 &
|
$MYSQLD $master_args >> $MASTER_MYERR 2>&1 &
|
||||||
fi
|
fi
|
||||||
|
wait_for_server_start $MASTER_MYPORT
|
||||||
MASTER_RUNNING=1
|
MASTER_RUNNING=1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,6 +413,7 @@ start_slave()
|
|||||||
else
|
else
|
||||||
$SLAVE_MYSQLD $slave_args >> $SLAVE_MYERR 2>&1 &
|
$SLAVE_MYSQLD $slave_args >> $SLAVE_MYERR 2>&1 &
|
||||||
fi
|
fi
|
||||||
|
wait_for_server_start $SLAVE_MYPORT
|
||||||
SLAVE_RUNNING=1
|
SLAVE_RUNNING=1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +422,6 @@ mysql_start () {
|
|||||||
start_master
|
start_master
|
||||||
start_slave
|
start_slave
|
||||||
cd $MYSQL_TEST_DIR
|
cd $MYSQL_TEST_DIR
|
||||||
sleep $SLEEP_TIME # Give mysqld time to start properly
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +444,6 @@ stop_slave ()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
SLAVE_RUNNING=0
|
SLAVE_RUNNING=0
|
||||||
sleep $SLEEP_TIME # Give mysqld time to go down properly
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +466,6 @@ stop_master ()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
MASTER_RUNNING=0
|
MASTER_RUNNING=0
|
||||||
sleep $SLEEP_TIME # Give mysqld time to go down properly
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,7 +475,10 @@ mysql_stop ()
|
|||||||
$ECHO "Shutting-down MySQL daemon"
|
$ECHO "Shutting-down MySQL daemon"
|
||||||
$ECHO ""
|
$ECHO ""
|
||||||
stop_master
|
stop_master
|
||||||
|
$ECHO "Master shutdown finished"
|
||||||
stop_slave
|
stop_slave
|
||||||
|
$ECHO "Slave shutdown finished"
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
mysql-test/r/rpl000001.result
Normal file
5
mysql-test/r/rpl000001.result
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
n
|
||||||
|
1
|
||||||
|
2
|
||||||
|
sum(length(word))
|
||||||
|
71
|
@ -1,13 +1,13 @@
|
|||||||
File Position Binlog_do_db Binlog_ignore_db
|
File Position Binlog_do_db Binlog_ignore_db
|
||||||
master-bin.001 73
|
master-bin.001 73
|
||||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
||||||
127.0.0.1 root 9306 1 73 Yes
|
127.0.0.1 root 9306 1 master-bin.001 73 Yes
|
||||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
||||||
127.0.0.1 root 9306 1 73 No
|
127.0.0.1 root 9306 1 master-bin.001 73 No
|
||||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
||||||
127.0.0.1 root 9306 1 73 Yes
|
127.0.0.1 root 9306 1 master-bin.001 73 Yes
|
||||||
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
|
||||||
127.0.0.1 root 9306 1 173 Yes
|
127.0.0.1 root 9306 1 master-bin.001 173 Yes
|
||||||
File Position Binlog_do_db Binlog_ignore_db
|
File Position Binlog_do_db Binlog_ignore_db
|
||||||
master-bin.001 73
|
master-bin.001 73
|
||||||
n
|
n
|
||||||
|
@ -7,12 +7,15 @@ load data infile '../../std_data/words.dat' into table t1;
|
|||||||
drop table if exists foo;
|
drop table if exists foo;
|
||||||
create table foo(n int);
|
create table foo(n int);
|
||||||
insert into foo values(1),(2);
|
insert into foo values(1),(2);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
use test;
|
use test;
|
||||||
@r/rpl000001.a.result select * from foo;
|
select * from foo;
|
||||||
@r/rpl000001.b.result select sum(length(word)) from t1;
|
select sum(length(word)) from t1;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
@ -5,8 +5,13 @@ drop table if exists t1;
|
|||||||
create table t1 (n int auto_increment primary key);
|
create table t1 (n int auto_increment primary key);
|
||||||
set insert_id = 2000;
|
set insert_id = 2000;
|
||||||
insert into t1 values (NULL),(NULL),(NULL);
|
insert into t1 values (NULL),(NULL),(NULL);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
use test;
|
use test;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000002.result select * from t1;
|
@r/rpl000002.result select * from t1;
|
||||||
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -4,7 +4,12 @@ drop table if exists t1;
|
|||||||
create table t1(n int primary key);
|
create table t1(n int primary key);
|
||||||
!insert into t1 values (1),(2),(2);
|
!insert into t1 values (1),(2),(2);
|
||||||
insert into t1 values (3);
|
insert into t1 values (3);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000003.result select * from t1;
|
@r/rpl000003.result select * from t1;
|
||||||
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -16,4 +16,11 @@ drop table if exists t2;
|
|||||||
load table t2 from master;
|
load table t2 from master;
|
||||||
@r/rpl000004.a.result check table t1;
|
@r/rpl000004.a.result check table t1;
|
||||||
@r/rpl000004.b.result select count(*) from t2;
|
@r/rpl000004.b.result select count(*) from t2;
|
||||||
|
connection master;
|
||||||
|
set SQL_LOG_BIN=1;
|
||||||
drop table if exists t1,t2;
|
drop table if exists t1,t2;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
create table t1(n int);
|
||||||
|
drop table t1;
|
||||||
|
@ -7,8 +7,12 @@ INSERT t1 SET name='Jacob', age=2;
|
|||||||
INSERT into t1 SET name='Caleb', age=1;
|
INSERT into t1 SET name='Caleb', age=1;
|
||||||
ALTER TABLE t1 ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
|
ALTER TABLE t1 ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
|
||||||
@r/rpl000005.result select * from t1;
|
@r/rpl000005.result select * from t1;
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000005.result select * from t1;
|
@r/rpl000005.result select * from t1;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -12,3 +12,6 @@ load table foo from master;
|
|||||||
@r/rpl000006.result select unix_timestamp(t) from foo;
|
@r/rpl000006.result select unix_timestamp(t) from foo;
|
||||||
connection master;
|
connection master;
|
||||||
drop table foo;
|
drop table foo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -15,8 +15,12 @@ insert into foo values('five');
|
|||||||
drop table if exists bar;
|
drop table if exists bar;
|
||||||
create table bar (m int);
|
create table bar (m int);
|
||||||
insert into bar values(15);
|
insert into bar values(15);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000007.result select foo.n,bar.m from foo,bar;
|
@r/rpl000007.result select foo.n,bar.m from foo,bar;
|
||||||
connection master;
|
connection master;
|
||||||
drop table if exists bar,foo;
|
drop table if exists bar,foo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -17,8 +17,13 @@ insert into bar values(15);
|
|||||||
drop table if exists choo;
|
drop table if exists choo;
|
||||||
create table choo (k int);
|
create table choo (k int);
|
||||||
insert into choo values(55);
|
insert into choo values(55);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 3;
|
sync_with_master;
|
||||||
@r/rpl000008.result select foo.n,bar.m,choo.k from foo,bar,choo;
|
@r/rpl000008.result select foo.n,bar.m,choo.k from foo,bar,choo;
|
||||||
connection master;
|
connection master;
|
||||||
drop table if exists foo,bar,choo;
|
drop table if exists foo,bar,choo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
drop table if exists foo,bar,choo;
|
||||||
|
@ -6,8 +6,9 @@ drop database if exists foo;
|
|||||||
create database foo;
|
create database foo;
|
||||||
drop database if exists bar;
|
drop database if exists bar;
|
||||||
create database bar;
|
create database bar;
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
drop table if exists foo.foo;
|
drop table if exists foo.foo;
|
||||||
create table foo.foo (n int);
|
create table foo.foo (n int);
|
||||||
insert into foo.foo values(4);
|
insert into foo.foo values(4);
|
||||||
@ -18,9 +19,15 @@ insert into foo.foo values(5);
|
|||||||
drop table if exists bar.bar;
|
drop table if exists bar.bar;
|
||||||
create table bar.bar (m int);
|
create table bar.bar (m int);
|
||||||
insert into bar.bar values(15);
|
insert into bar.bar values(15);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000009.result select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
|
@r/rpl000009.result select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
|
||||||
connection master;
|
connection master;
|
||||||
drop database if exists bar;
|
drop database if exists bar;
|
||||||
drop database if exists foo;
|
drop database if exists foo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
drop database if exists bar;
|
||||||
|
drop database if exists foo;
|
||||||
|
@ -8,8 +8,12 @@ drop table if exists t1;
|
|||||||
create table t1 (n int not null auto_increment primary key);
|
create table t1 (n int not null auto_increment primary key);
|
||||||
insert into t1 values(NULL);
|
insert into t1 values(NULL);
|
||||||
insert into t1 values(2);
|
insert into t1 values(2);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 5;
|
sync_with_master;
|
||||||
@r/rpl000010.result select n from t1;
|
@r/rpl000010.result select n from t1;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -4,16 +4,21 @@ use test;
|
|||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
create table t1 (n int);
|
create table t1 (n int);
|
||||||
insert into t1 values(1);
|
insert into t1 values(1);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
#give slave some breathing room to get started
|
#give slave some breathing room to get started
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
slave stop;
|
slave stop;
|
||||||
slave start;
|
slave start;
|
||||||
connection master;
|
connection master;
|
||||||
insert into t1 values(2);
|
insert into t1 values(2);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
#let slave catch up
|
#let slave catch up
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
@r/rpl000011.result select * from t1;
|
@r/rpl000011.result select * from t1;
|
||||||
connection master;
|
connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -14,13 +14,18 @@ disconnect master;
|
|||||||
connection master1;
|
connection master1;
|
||||||
insert into t2 values(6);
|
insert into t2 values(6);
|
||||||
disconnect master1;
|
disconnect master1;
|
||||||
|
connect (master2,localhost,root,,test,0,mysql-master.sock);
|
||||||
|
connection master2;
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 1;
|
sync_with_master;
|
||||||
@r/rpl000012.result select * from t2;
|
@r/rpl000012.result select * from t2;
|
||||||
@r/rpl000012.status.result show status like 'Slave_open_temp_tables';
|
@r/rpl000012.status.result show status like 'Slave_open_temp_tables';
|
||||||
#
|
#
|
||||||
# Clean up
|
# Clean up
|
||||||
#
|
#
|
||||||
connect (master2,localhost,root,,test,0,mysql-master.sock);
|
|
||||||
connection master2;
|
connection master2;
|
||||||
drop table if exists t1,t2;
|
drop table if exists t1,t2;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
source include/master-slave.inc;
|
source include/master-slave.inc;
|
||||||
connection master;
|
connection master;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
connection master;
|
||||||
drop table if exists t2;
|
drop table if exists t2;
|
||||||
create table t2(n int);
|
create table t2(n int);
|
||||||
create temporary table t1 (n int);
|
create temporary table t1 (n int);
|
||||||
@ -12,21 +16,19 @@ insert into t2 select * from t1;
|
|||||||
disconnect master;
|
disconnect master;
|
||||||
connection master1;
|
connection master1;
|
||||||
insert into t2 values(6);
|
insert into t2 values(6);
|
||||||
sleep 2;
|
|
||||||
disconnect master1;
|
disconnect master1;
|
||||||
|
connect (master2,localhost,root,,test,0,mysql-master.sock);
|
||||||
|
connection master2;
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
let $1=12;
|
sync_with_master;
|
||||||
while ($1)
|
|
||||||
{
|
|
||||||
!slave start;
|
|
||||||
sleep 0.2;
|
|
||||||
dec $1;
|
|
||||||
}
|
|
||||||
@r/rpl000013.result select * from t2;
|
@r/rpl000013.result select * from t2;
|
||||||
@r/rpl000013.status.result show status like 'Slave_open_temp_tables';
|
@r/rpl000013.status.result show status like 'Slave_open_temp_tables';
|
||||||
#
|
#
|
||||||
# Clean up
|
# Clean up
|
||||||
#
|
#
|
||||||
connect (master2,localhost,root,,test,0,mysql-master.sock);
|
|
||||||
connection master2;
|
connection master2;
|
||||||
drop table if exists t1,t2;
|
drop table if exists t1,t2;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -2,11 +2,11 @@ source include/master-slave.inc;
|
|||||||
source include/have_default_master.inc;
|
source include/have_default_master.inc;
|
||||||
connection master;
|
connection master;
|
||||||
show master status;
|
show master status;
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 0.2;
|
sync_with_master;
|
||||||
show slave status;
|
show slave status;
|
||||||
change master to master_log_pos=73;
|
change master to master_log_pos=73;
|
||||||
sleep 0.2;
|
|
||||||
slave stop;
|
slave stop;
|
||||||
change master to master_log_pos=73;
|
change master to master_log_pos=73;
|
||||||
show slave status;
|
show slave status;
|
||||||
@ -20,9 +20,13 @@ create table if not exists foo(n int);
|
|||||||
drop table if exists foo;
|
drop table if exists foo;
|
||||||
create table foo (n int);
|
create table foo (n int);
|
||||||
insert into foo values (1),(2),(3);
|
insert into foo values (1),(2),(3);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
change master to master_log_pos=73;
|
change master to master_log_pos=73;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
select * from foo;
|
select * from foo;
|
||||||
connection master;
|
connection master;
|
||||||
drop table foo;
|
drop table foo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
@ -18,8 +18,13 @@ connection master;
|
|||||||
drop table if exists foo;
|
drop table if exists foo;
|
||||||
create table foo (n int);
|
create table foo (n int);
|
||||||
insert into foo values (10),(45),(90);
|
insert into foo values (10),(45),(90);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
select * from foo;
|
select * from foo;
|
||||||
connection master;
|
connection master;
|
||||||
drop table foo;
|
drop table foo;
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
sync_with_master;
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@ connection master;
|
|||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
create table t1 (s text);
|
create table t1 (s text);
|
||||||
insert into t1 values('Could not break slave'),('Tried hard');
|
insert into t1 values('Could not break slave'),('Tried hard');
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
connection master;
|
connection master;
|
||||||
flush logs;
|
flush logs;
|
||||||
@ -24,12 +25,14 @@ drop table if exists t2;
|
|||||||
create table t2(m int);
|
create table t2(m int);
|
||||||
insert into t2 values (34),(67),(123);
|
insert into t2 values (34),(67),(123);
|
||||||
flush logs;
|
flush logs;
|
||||||
sleep 0.3;
|
|
||||||
show master logs;
|
show master logs;
|
||||||
purge master logs to 'master-bin.003';
|
purge master logs to 'master-bin.003';
|
||||||
show master logs;
|
show master logs;
|
||||||
insert into t2 values (65);
|
insert into t2 values (65);
|
||||||
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sleep 2;
|
sync_with_master;
|
||||||
select * from t2;
|
select * from t2;
|
||||||
drop table if exists t1,t2;
|
drop table if exists t1,t2;
|
||||||
|
connection master;
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
@ -376,3 +376,8 @@ Item *create_load_file(Item* a)
|
|||||||
{
|
{
|
||||||
return new Item_load_file(a);
|
return new Item_load_file(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item *create_wait_for_master_pos(Item* a, Item* b)
|
||||||
|
{
|
||||||
|
return new Item_master_pos_wait(a, b);
|
||||||
|
}
|
||||||
|
@ -85,3 +85,4 @@ Item *create_func_ucase(Item* a);
|
|||||||
Item *create_func_version(void);
|
Item *create_func_version(void);
|
||||||
Item *create_func_weekday(Item* a);
|
Item *create_func_weekday(Item* a);
|
||||||
Item *create_load_file(Item* a);
|
Item *create_load_file(Item* a);
|
||||||
|
Item *create_wait_for_master_pos(Item* a, Item* b);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ft_global.h>
|
#include <ft_global.h>
|
||||||
|
#include "slave.h" // for wait_for_master_pos
|
||||||
|
|
||||||
/* return TRUE if item is a constant */
|
/* return TRUE if item is a constant */
|
||||||
|
|
||||||
@ -1387,6 +1388,28 @@ void item_user_lock_release(ULL *ull)
|
|||||||
delete ull;
|
delete ull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wait until we are at or past the given position in the master binlog
|
||||||
|
on the slave
|
||||||
|
*/
|
||||||
|
|
||||||
|
longlong Item_master_pos_wait::val_int()
|
||||||
|
{
|
||||||
|
THD* thd = current_thd;
|
||||||
|
String *log_name = args[0]->val_str(&value);
|
||||||
|
int event_count;
|
||||||
|
|
||||||
|
if(thd->slave_thread || !log_name || !log_name->length())
|
||||||
|
{
|
||||||
|
null_value = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ulong pos = (ulong)args[1]->val_int();
|
||||||
|
if((event_count = glob_mi.wait_for_pos(thd, log_name, pos)) == -1)
|
||||||
|
null_value = 1;;
|
||||||
|
return event_count;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a user level lock. If the thread has an old lock this is first released.
|
Get a user level lock. If the thread has an old lock this is first released.
|
||||||
Returns 1: Got lock
|
Returns 1: Got lock
|
||||||
|
@ -778,6 +778,18 @@ class Item_func_release_lock :public Item_int_func
|
|||||||
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* replication functions */
|
||||||
|
|
||||||
|
class Item_master_pos_wait :public Item_int_func
|
||||||
|
{
|
||||||
|
String value;
|
||||||
|
public:
|
||||||
|
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
|
longlong val_int();
|
||||||
|
const char *func_name() const { return "master_pos_wait"; }
|
||||||
|
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Handling of user definiable variables */
|
/* Handling of user definiable variables */
|
||||||
|
|
||||||
|
@ -398,6 +398,8 @@ static SYMBOL sql_functions[] = {
|
|||||||
{ "LOWER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
|
{ "LOWER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
|
||||||
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
|
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
|
||||||
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
|
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
|
||||||
|
{ "MASTER_POS_WAIT", SYM(FUNC_ARG2),0,
|
||||||
|
CREATE_FUNC(create_wait_for_master_pos)},
|
||||||
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
|
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
|
||||||
{ "MAX", SYM(MAX_SYM),0,0},
|
{ "MAX", SYM(MAX_SYM),0,0},
|
||||||
{ "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
|
{ "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
|
||||||
|
58
sql/slave.cc
58
sql/slave.cc
@ -616,6 +616,46 @@ int flush_master_info(MASTER_INFO* mi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int st_master_info::wait_for_pos(THD* thd, String* log_name, ulong log_pos)
|
||||||
|
{
|
||||||
|
if(!inited) return -1;
|
||||||
|
bool pos_reached = 0;
|
||||||
|
int event_count = 0;
|
||||||
|
for(;!pos_reached && !thd->killed;)
|
||||||
|
{
|
||||||
|
int cmp_result;
|
||||||
|
char* basename;
|
||||||
|
pthread_mutex_lock(&lock);
|
||||||
|
if(*log_file_name)
|
||||||
|
{
|
||||||
|
basename = strrchr(log_file_name, FN_LIBCHAR);
|
||||||
|
if(basename)
|
||||||
|
++basename;
|
||||||
|
else
|
||||||
|
basename = log_file_name;
|
||||||
|
cmp_result = strncmp(basename, log_name->ptr(),
|
||||||
|
log_name->length());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cmp_result = 0;
|
||||||
|
|
||||||
|
pos_reached = ((!cmp_result && pos >= log_pos) || cmp_result > 0);
|
||||||
|
if(!pos_reached && !thd->killed)
|
||||||
|
{
|
||||||
|
const char* msg = thd->enter_cond(&cond, &lock,
|
||||||
|
"Waiting for master update");
|
||||||
|
pthread_cond_wait(&cond, &lock);
|
||||||
|
thd->exit_cond(msg);
|
||||||
|
event_count++;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
if(thd->killed)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return event_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int init_slave_thread(THD* thd)
|
static int init_slave_thread(THD* thd)
|
||||||
{
|
{
|
||||||
@ -1003,10 +1043,17 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|||||||
{
|
{
|
||||||
Rotate_log_event* rev = (Rotate_log_event*)ev;
|
Rotate_log_event* rev = (Rotate_log_event*)ev;
|
||||||
int ident_len = rev->ident_len;
|
int ident_len = rev->ident_len;
|
||||||
|
pthread_mutex_lock(&mi->lock);
|
||||||
memcpy(mi->log_file_name, rev->new_log_ident,ident_len );
|
memcpy(mi->log_file_name, rev->new_log_ident,ident_len );
|
||||||
mi->log_file_name[ident_len] = 0;
|
mi->log_file_name[ident_len] = 0;
|
||||||
mi->pos = 4; // skip magic number
|
mi->pos = 4; // skip magic number
|
||||||
|
pthread_cond_broadcast(&mi->cond);
|
||||||
|
pthread_mutex_unlock(&mi->lock);
|
||||||
flush_master_info(mi);
|
flush_master_info(mi);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
if(abort_slave_event_count)
|
||||||
|
++events_till_abort;
|
||||||
|
#endif
|
||||||
delete ev;
|
delete ev;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1045,6 +1092,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
|
|||||||
|
|
||||||
pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
slave_begin:
|
||||||
|
#endif
|
||||||
THD *thd; // needs to be first for thread_stack
|
THD *thd; // needs to be first for thread_stack
|
||||||
MYSQL *mysql = NULL ;
|
MYSQL *mysql = NULL ;
|
||||||
|
|
||||||
@ -1068,8 +1118,8 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
|
|||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
events_till_abort = abort_slave_event_count;
|
events_till_abort = abort_slave_event_count;
|
||||||
#endif
|
#endif
|
||||||
pthread_cond_broadcast(&COND_slave_start);
|
pthread_cond_broadcast(&COND_slave_start);
|
||||||
pthread_mutex_unlock(&LOCK_slave);
|
pthread_mutex_unlock(&LOCK_slave);
|
||||||
|
|
||||||
int error = 1;
|
int error = 1;
|
||||||
bool retried_once = 0;
|
bool retried_once = 0;
|
||||||
@ -1241,6 +1291,10 @@ position %ld",
|
|||||||
net_end(&thd->net); // destructor will not free it, because we are weird
|
net_end(&thd->net); // destructor will not free it, because we are weird
|
||||||
delete thd;
|
delete thd;
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
if(abort_slave_event_count && !events_till_abort)
|
||||||
|
goto slave_begin;
|
||||||
|
#endif
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
DBUG_RETURN(0); // Can't return anything here
|
DBUG_RETURN(0); // Can't return anything here
|
||||||
}
|
}
|
||||||
|
@ -14,17 +14,20 @@ typedef struct st_master_info
|
|||||||
uint port;
|
uint port;
|
||||||
uint connect_retry;
|
uint connect_retry;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
pthread_cond_t cond;
|
||||||
bool inited;
|
bool inited;
|
||||||
|
|
||||||
st_master_info():pending(0),fd(-1),inited(0)
|
st_master_info():pending(0),fd(-1),inited(0)
|
||||||
{
|
{
|
||||||
host[0] = 0; user[0] = 0; password[0] = 0;
|
host[0] = 0; user[0] = 0; password[0] = 0;
|
||||||
pthread_mutex_init(&lock, NULL);
|
pthread_mutex_init(&lock, NULL);
|
||||||
|
pthread_cond_init(&cond, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
~st_master_info()
|
~st_master_info()
|
||||||
{
|
{
|
||||||
pthread_mutex_destroy(&lock);
|
pthread_mutex_destroy(&lock);
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
}
|
}
|
||||||
inline void inc_pending(ulonglong val)
|
inline void inc_pending(ulonglong val)
|
||||||
{
|
{
|
||||||
@ -35,6 +38,7 @@ typedef struct st_master_info
|
|||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
pos += val + pending;
|
pos += val + pending;
|
||||||
pending = 0;
|
pending = 0;
|
||||||
|
pthread_cond_broadcast(&cond);
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
// thread safe read of position - not needed if we are in the slave thread,
|
// thread safe read of position - not needed if we are in the slave thread,
|
||||||
@ -45,6 +49,8 @@ typedef struct st_master_info
|
|||||||
var = pos;
|
var = pos;
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wait_for_pos(THD* thd, String* log_name, ulong log_pos);
|
||||||
} MASTER_INFO;
|
} MASTER_INFO;
|
||||||
|
|
||||||
typedef struct st_table_rule_ent
|
typedef struct st_table_rule_ent
|
||||||
|
@ -281,6 +281,25 @@ public:
|
|||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
bool store_globals();
|
bool store_globals();
|
||||||
|
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
|
||||||
|
const char* msg)
|
||||||
|
{
|
||||||
|
const char* old_msg = proc_info;
|
||||||
|
pthread_mutex_lock(&mysys_var->mutex);
|
||||||
|
mysys_var->current_mutex = mutex;
|
||||||
|
mysys_var->current_cond = cond;
|
||||||
|
proc_info = msg;
|
||||||
|
pthread_mutex_unlock(&mysys_var->mutex);
|
||||||
|
return old_msg;
|
||||||
|
}
|
||||||
|
inline void exit_cond(const char* old_msg)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mysys_var->mutex);
|
||||||
|
mysys_var->current_mutex = 0;
|
||||||
|
mysys_var->current_cond = 0;
|
||||||
|
proc_info = old_msg;
|
||||||
|
pthread_mutex_unlock(&mysys_var->mutex);
|
||||||
|
}
|
||||||
inline time_t query_start() { query_start_used=1; return start_time; }
|
inline time_t query_start() { query_start_used=1; return start_time; }
|
||||||
inline void set_time() { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
|
inline void set_time() { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
|
||||||
inline void end_time() { time(&start_time); }
|
inline void end_time() { time(&start_time); }
|
||||||
|
@ -26,6 +26,36 @@
|
|||||||
|
|
||||||
extern const char* any_db;
|
extern const char* any_db;
|
||||||
extern pthread_handler_decl(handle_slave,arg);
|
extern pthread_handler_decl(handle_slave,arg);
|
||||||
|
static int fake_rotate_event(NET* net, String* packet,
|
||||||
|
const char* log_file_name);
|
||||||
|
|
||||||
|
static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
|
||||||
|
const char**errmsg)
|
||||||
|
{
|
||||||
|
char header[LOG_EVENT_HEADER_LEN];
|
||||||
|
memset(header, 0, 4); // when does not matter
|
||||||
|
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
|
||||||
|
char* p = strrchr(log_file_name, FN_LIBCHAR);
|
||||||
|
// find the last slash
|
||||||
|
if(p)
|
||||||
|
p++;
|
||||||
|
else
|
||||||
|
p = log_file_name;
|
||||||
|
|
||||||
|
uint ident_len = (uint) strlen(p);
|
||||||
|
ulong event_len = ident_len + sizeof(header);
|
||||||
|
int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
|
||||||
|
int4store(header + EVENT_LEN_OFFSET, event_len);
|
||||||
|
packet->append(header, sizeof(header));
|
||||||
|
packet->append(p,ident_len);
|
||||||
|
if(my_net_write(net, (char*)packet->ptr(), packet->length()))
|
||||||
|
{
|
||||||
|
*errmsg = "failed on my_net_write()";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int send_file(THD *thd)
|
static int send_file(THD *thd)
|
||||||
{
|
{
|
||||||
@ -281,6 +311,15 @@ sweepstakes if you report the bug";
|
|||||||
// we need to start a packet with something other than 255
|
// we need to start a packet with something other than 255
|
||||||
// to distiquish it from error
|
// to distiquish it from error
|
||||||
|
|
||||||
|
if(pos == 4) // tell the client log name with a fake rotate_event
|
||||||
|
// if we are at the start of the log
|
||||||
|
{
|
||||||
|
if(fake_rotate_event(net, packet, log_file_name, &errmsg))
|
||||||
|
goto err;
|
||||||
|
packet->length(0);
|
||||||
|
packet->append("\0", 1);
|
||||||
|
}
|
||||||
|
|
||||||
while(!net->error && net->vio != 0 && !thd->killed)
|
while(!net->error && net->vio != 0 && !thd->killed)
|
||||||
{
|
{
|
||||||
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
|
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
|
||||||
@ -437,36 +476,15 @@ sweepstakes if you report the bug";
|
|||||||
|
|
||||||
end_io_cache(&log);
|
end_io_cache(&log);
|
||||||
(void) my_close(file, MYF(MY_WME));
|
(void) my_close(file, MYF(MY_WME));
|
||||||
if ((file=open_log(&log, log_file_name, &errmsg)) < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
// fake Rotate_log event just in case it did not make it to the log
|
// fake Rotate_log event just in case it did not make it to the log
|
||||||
// otherwise the slave make get confused about the offset
|
// otherwise the slave make get confused about the offset
|
||||||
{
|
if ((file=open_log(&log, log_file_name, &errmsg)) < 0 ||
|
||||||
char header[LOG_EVENT_HEADER_LEN];
|
fake_rotate_event(net, packet, log_file_name, &errmsg))
|
||||||
memset(header, 0, 4); // when does not matter
|
goto err;
|
||||||
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
|
|
||||||
char* p = strrchr(log_file_name, FN_LIBCHAR);
|
|
||||||
// find the last slash
|
|
||||||
if(p)
|
|
||||||
p++;
|
|
||||||
else
|
|
||||||
p = log_file_name;
|
|
||||||
|
|
||||||
uint ident_len = (uint) strlen(p);
|
packet->length(0);
|
||||||
ulong event_len = ident_len + sizeof(header);
|
packet->append("\0",1);
|
||||||
int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
|
|
||||||
int4store(header + EVENT_LEN_OFFSET, event_len);
|
|
||||||
packet->append(header, sizeof(header));
|
|
||||||
packet->append(p,ident_len);
|
|
||||||
if(my_net_write(net, (char*)packet->ptr(), packet->length()))
|
|
||||||
{
|
|
||||||
errmsg = "failed on my_net_write()";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
packet->length(0);
|
|
||||||
packet->append("\0",1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user