Made sending of events more strict
The decision to send an event to a slave can now only be made in one place. This will force all events to pass the same checks before they are sent to the slaves.
This commit is contained in:
@ -1914,59 +1914,69 @@ blr_distribute_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint8_t *
|
|||||||
spinlock_acquire(&router->binlog_lock);
|
spinlock_acquire(&router->binlog_lock);
|
||||||
|
|
||||||
slave_event_action_t slave_action = SLAVE_FORCE_CATCHUP;
|
slave_event_action_t slave_action = SLAVE_FORCE_CATCHUP;
|
||||||
|
const bool same_file = strcmp(slave->binlogfile, router->binlog_name) == 0;
|
||||||
|
const bool rotate = hdr->event_type == ROTATE_EVENT &&
|
||||||
|
strcmp(slave->binlogfile, router->prevbinlog);
|
||||||
|
|
||||||
if (router->trx_safe && slave->binlog_pos == router->current_safe_event &&
|
if (router->trx_safe && (same_file || rotate) &&
|
||||||
(strcmp(slave->binlogfile, router->binlog_name) == 0 ||
|
slave->binlog_pos == router->current_safe_event)
|
||||||
(hdr->event_type == ROTATE_EVENT &&
|
|
||||||
strcmp(slave->binlogfile, router->prevbinlog))))
|
|
||||||
{
|
{
|
||||||
/**
|
/** Slave needs the current event being distributed */
|
||||||
* Slave needs the current event being distributed
|
|
||||||
*/
|
|
||||||
slave_action = SLAVE_SEND_EVENT;
|
slave_action = SLAVE_SEND_EVENT;
|
||||||
}
|
}
|
||||||
else if (slave->binlog_pos == router->last_event_pos &&
|
else if (!router->trx_safe && (same_file || rotate) &&
|
||||||
(strcmp(slave->binlogfile, router->binlog_name) == 0 ||
|
slave->binlog_pos == router->last_event_pos)
|
||||||
(hdr->event_type == ROTATE_EVENT &&
|
|
||||||
strcmp(slave->binlogfile, router->prevbinlog))))
|
|
||||||
{
|
{
|
||||||
if (router->trx_safe)
|
/** Transaction safety is off */
|
||||||
|
slave_action = SLAVE_SEND_EVENT;
|
||||||
|
}
|
||||||
|
else if (same_file)
|
||||||
|
{
|
||||||
|
if (slave->binlog_pos == hdr->next_pos)
|
||||||
{
|
{
|
||||||
MXS_ERROR("Slave %s:%d, server ID %u: Sending event from an "
|
/*
|
||||||
"incomplete transaction from file %s. Slave position: %u "
|
* Slave has already read record from file, no
|
||||||
"Caller role: %s Current safe event: %lu Event type: %x",
|
* need to distrbute this event
|
||||||
slave->dcb->remote, ntohs((slave->dcb->ipv4).sin_port),
|
*/
|
||||||
slave->serverid, slave->binlogfile, slave->binlog_pos,
|
slave_action = SLAVE_EVENT_ALREADY_SENT;
|
||||||
ROLETOSTR(role), router->current_safe_event, hdr->event_type);
|
}
|
||||||
|
else if ((slave->binlog_pos > hdr->next_pos - hdr->event_size))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The slave is ahead of the master, this should never
|
||||||
|
* happen. Force the slave to catchup mode in order to
|
||||||
|
* try to resolve the issue.
|
||||||
|
*/
|
||||||
|
MXS_ERROR("Slave %s:%d server ID %d is ahead of expected position %s@%u. "
|
||||||
|
"Expected position %d", slave->dcb->remote,
|
||||||
|
ntohs((slave->dcb->ipv4).sin_port), slave->serverid,
|
||||||
|
slave->binlogfile, slave->binlog_pos,
|
||||||
|
hdr->next_pos - hdr->event_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MXS_ERROR("Slave %s:%d server ID %d is at position %u when "
|
||||||
|
"it should be at %u.", slave->dcb->remote,
|
||||||
|
ntohs((slave->dcb->ipv4).sin_port), slave->serverid,
|
||||||
|
slave->binlog_pos, hdr->next_pos - hdr->event_size);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Transaction safety is off or there are no pending transactions
|
|
||||||
*/
|
|
||||||
|
|
||||||
slave_action = SLAVE_SEND_EVENT;
|
|
||||||
}
|
}
|
||||||
else if (slave->binlog_pos == hdr->next_pos
|
else if (rotate)
|
||||||
&& strcmp(slave->binlogfile, router->binlog_name) == 0)
|
|
||||||
{
|
{
|
||||||
/*
|
/** Slave is more than one binlog file behind */
|
||||||
* Slave has already read record from file, no
|
MXS_ERROR("Slave %s:%d server ID %d is behind more than one binlog file "
|
||||||
* need to distrbute this event
|
"from the master. Slave is using '%s' with position %d "
|
||||||
*/
|
"when master binlog file is '%s'.", slave->dcb->remote,
|
||||||
slave_action = SLAVE_EVENT_ALREADY_SENT;
|
ntohs((slave->dcb->ipv4).sin_port), slave->serverid,
|
||||||
|
slave->binlogfile, slave->binlog_pos, router->binlog_name);
|
||||||
}
|
}
|
||||||
else if ((slave->binlog_pos > hdr->next_pos - hdr->event_size)
|
else
|
||||||
&& strcmp(slave->binlogfile, router->binlog_name) == 0)
|
|
||||||
{
|
{
|
||||||
/*
|
/** Slave is using unexpected binlog file */
|
||||||
* The slave is ahead of the master, this should never
|
MXS_ERROR("Slave %s:%d server ID %d is using an unexpected binlog file '%s' with "
|
||||||
* happen. Force the slave to catchup mode in order to
|
"position %d. Master binlog file is '%s'.", slave->dcb->remote,
|
||||||
* try to resolve the issue.
|
ntohs((slave->dcb->ipv4).sin_port), slave->serverid,
|
||||||
*/
|
slave->binlogfile, slave->binlog_pos, router->binlog_name);
|
||||||
MXS_ERROR("Slave %d is ahead of expected position %s@%lu. "
|
|
||||||
"Expected position %d",
|
|
||||||
slave->serverid, slave->binlogfile,
|
|
||||||
(unsigned long)slave->binlog_pos,
|
|
||||||
hdr->next_pos - hdr->event_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&router->binlog_lock);
|
spinlock_release(&router->binlog_lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user