WL#2975: RBR: Stopping slave in middle of non-transaction, no primary key

Affects: Server-7.0   —   Status: Assigned   —   Priority: Low


Need to handle when slave stops in the middle of a transaction using
MyISAM without primary keys.

See also BUG#14418.


2005-11-07: Lars and Mats thinks this must be fixed before we push
            into main source tree.
2005-12-02: Elliot, Guilhem, Lars, Mats agree we can limit ourselves to the 
            solution outlined in BUG#14418 in a first step before the push in
            5.1, and do the more complete solution outlined above in a second
            step after the push in 5.1.


For MyISAM tables, and any other non-transactional tables, changes to
the tables are writted directly to the binary log. For tables that have
primary keys, idempotency is guaranteed: the rows will be overwritten if
a new row arrives. For tables without primary keys, there are no such


We replicate to a MyISAM table on the slave and stop the slave in the
middle of a transaction.  The events that has already been executed
are not rolled back in MyISAM, since it is non-transactional.  Since
MyISAM can have tables without primary key, idempotency of the log is
not ensured.

Therefore, it is necessary to restart from the point of failure.
However, upon restart, the table map events have not been seen, so the
table id for the binrow event does not make sense. It is therefore
necessary to reread the table map events that have been generated
between the start of the transaction/statement and the point of 
failure in the binary log.


The solution implemented should take "WL#2765 interleaving" into 
account, since at some point in time we should have that and any 
code written now should be extendable into WL#2765.

We have two log positions of interest:

1. the group position (G) pointing at the start of the transaction (which
   can be used to find the table map events), and
2. the "normal" position (P) pointing at the last executed statement (or
   binrow event, as it is in this case)

If we would have idempotency, the problem would be easy to solve.
Then we would simply rerun the whole transaction from G.

Since we don't have idempotency, we will instead have to reexecute
the table map events from G until we reach P, and first when we 
reach P will we execute all events.


An alternative solution would be to start from P but somehow have a
way to locate the table map events by searching the log.  This seems
more complex and will not be done.