MXS-1141: maxbinlogcheck to replace an event with ignorable event
maxbinlogcheck utility can replace an event at pos with an ignorable event New option is -R, —replace -R $pos The -R needs -f as file will be modified
This commit is contained in:
@ -111,7 +111,6 @@ static int blr_handler_config(void *userdata, const char *section, const char *n
|
|||||||
static int blr_handle_config_item(const char *name, const char *value, ROUTER_INSTANCE *inst);
|
static int blr_handle_config_item(const char *name, const char *value, ROUTER_INSTANCE *inst);
|
||||||
static int blr_load_dbusers(const ROUTER_INSTANCE *router);
|
static int blr_load_dbusers(const ROUTER_INSTANCE *router);
|
||||||
static int blr_check_binlog(ROUTER_INSTANCE *router);
|
static int blr_check_binlog(ROUTER_INSTANCE *router);
|
||||||
int blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug);
|
|
||||||
void blr_master_close(ROUTER_INSTANCE *);
|
void blr_master_close(ROUTER_INSTANCE *);
|
||||||
void blr_free_ssl_data(ROUTER_INSTANCE *inst);
|
void blr_free_ssl_data(ROUTER_INSTANCE *inst);
|
||||||
static void destroyInstance(MXS_ROUTER *instance);
|
static void destroyInstance(MXS_ROUTER *instance);
|
||||||
@ -2304,7 +2303,7 @@ static int blr_check_binlog(ROUTER_INSTANCE *router)
|
|||||||
* router->current_pos is the last event found.
|
* router->current_pos is the last event found.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
n = blr_read_events_all_events(router, 0, 0);
|
n = blr_read_events_all_events(router, NULL, 0);
|
||||||
|
|
||||||
MXS_DEBUG("blr_read_events_all_events() ret = %i\n", n);
|
MXS_DEBUG("blr_read_events_all_events() ret = %i\n", n);
|
||||||
|
|
||||||
|
|||||||
@ -73,6 +73,7 @@ MXS_BEGIN_DECLS
|
|||||||
/* BINLOG_EVENT_LEN_OFFSET points to event_size in event_header */
|
/* BINLOG_EVENT_LEN_OFFSET points to event_size in event_header */
|
||||||
#define BINLOG_EVENT_LEN_OFFSET 9
|
#define BINLOG_EVENT_LEN_OFFSET 9
|
||||||
#define BINLOG_FATAL_ERROR_READING 1236
|
#define BINLOG_FATAL_ERROR_READING 1236
|
||||||
|
#define BINLOG_DATA_TRUNCATED 2032
|
||||||
|
|
||||||
/* Binlog Encryption */
|
/* Binlog Encryption */
|
||||||
#define BINLOG_ENC_ALGO_NAME_LEN 13
|
#define BINLOG_ENC_ALGO_NAME_LEN 13
|
||||||
@ -638,6 +639,23 @@ typedef struct binlog_encryption_ctx
|
|||||||
char *binlog_file; /**< Current binlog file being encrypted */
|
char *binlog_file; /**< Current binlog file being encrypted */
|
||||||
} BINLOG_ENCRYPTION_CTX;
|
} BINLOG_ENCRYPTION_CTX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds information about:
|
||||||
|
* truncating a corrupted file
|
||||||
|
* or replace an event at specified pos
|
||||||
|
* or replace a transaction that start
|
||||||
|
* at specified pos
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct binlog_pos_fix
|
||||||
|
{
|
||||||
|
bool fix; /**< Truncate file to last safe pos */
|
||||||
|
uint64_t pos; /**< Position of the event to be replaced
|
||||||
|
* by an Ignorable Event */
|
||||||
|
bool replace_trx; /**< Replace all events belonging to
|
||||||
|
* a transaction starting at pos */
|
||||||
|
} BINLOG_FILE_FIX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines and offsets for binlog encryption
|
* Defines and offsets for binlog encryption
|
||||||
*
|
*
|
||||||
@ -809,7 +827,7 @@ extern int blr_send_custom_error(DCB *, int, int, char *, char *, unsigned int);
|
|||||||
extern int blr_file_next_exists(ROUTER_INSTANCE *, ROUTER_SLAVE *);
|
extern int blr_file_next_exists(ROUTER_INSTANCE *, ROUTER_SLAVE *);
|
||||||
uint32_t extract_field(uint8_t *src, int bits);
|
uint32_t extract_field(uint8_t *src, int bits);
|
||||||
void blr_cache_read_master_data(ROUTER_INSTANCE *router);
|
void blr_cache_read_master_data(ROUTER_INSTANCE *router);
|
||||||
int blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug);
|
int blr_read_events_all_events(ROUTER_INSTANCE *, const BINLOG_FILE_FIX *, int);
|
||||||
int blr_save_dbusers(const ROUTER_INSTANCE *router);
|
int blr_save_dbusers(const ROUTER_INSTANCE *router);
|
||||||
char *blr_get_event_description(ROUTER_INSTANCE *router, uint8_t event);
|
char *blr_get_event_description(ROUTER_INSTANCE *router, uint8_t event);
|
||||||
void blr_file_append(ROUTER_INSTANCE *router, char *file);
|
void blr_file_append(ROUTER_INSTANCE *router, char *file);
|
||||||
|
|||||||
@ -1297,13 +1297,15 @@ blr_file_next_exists(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
|||||||
*
|
*
|
||||||
* Routine detects errors and pending transactions
|
* Routine detects errors and pending transactions
|
||||||
*
|
*
|
||||||
* @param router The router instance
|
* @param router The router instance
|
||||||
* @param fix Whether to fix or not errors
|
* @param action Whether to fix errors or blank events at pos
|
||||||
* @param debug Whether to enable or not the debug for events
|
* @param debug Whether to enable or not the debug for events
|
||||||
* @return 0 on success, >0 on failure
|
* @return 0 on success, >0 on failure
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug)
|
blr_read_events_all_events(ROUTER_INSTANCE *router,
|
||||||
|
const BINLOG_FILE_FIX *action,
|
||||||
|
int debug)
|
||||||
{
|
{
|
||||||
unsigned long filelen = 0;
|
unsigned long filelen = 0;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
@ -1337,6 +1339,7 @@ blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug)
|
|||||||
BINLOG_EVENT_DESC fde_event;
|
BINLOG_EVENT_DESC fde_event;
|
||||||
int fde_seen = 0;
|
int fde_seen = 0;
|
||||||
int start_encryption_seen = 0;
|
int start_encryption_seen = 0;
|
||||||
|
bool fix = action ? action->fix : false;
|
||||||
|
|
||||||
memset(&first_event, '\0', sizeof(first_event));
|
memset(&first_event, '\0', sizeof(first_event));
|
||||||
memset(&last_event, '\0', sizeof(last_event));
|
memset(&last_event, '\0', sizeof(last_event));
|
||||||
@ -1973,6 +1976,27 @@ blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace event at pos with an IGNORABLE EVENT
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fix &&
|
||||||
|
action->pos > 4 &&
|
||||||
|
pos == action->pos)
|
||||||
|
{
|
||||||
|
char *event_desc = blr_get_event_description(router, hdr.event_type);
|
||||||
|
|
||||||
|
MXS_DEBUG("*** Filling event (%s) at pos %lu with an IGNORABLE EVENT\n",
|
||||||
|
event_desc ? event_desc : "unknown",
|
||||||
|
action->pos);
|
||||||
|
|
||||||
|
router->last_written = action->pos;
|
||||||
|
router->master_chksum = found_chksum;
|
||||||
|
|
||||||
|
/* Create and write Ingonrable event into binlog file at action->pos */
|
||||||
|
blr_write_special_event(router, pos, hdr.event_size, &hdr, BLRM_IGNORABLE);
|
||||||
|
}
|
||||||
|
|
||||||
/* If MariaDB 10 compatibility:
|
/* If MariaDB 10 compatibility:
|
||||||
* check for MARIADB10_GTID_EVENT with flags
|
* check for MARIADB10_GTID_EVENT with flags
|
||||||
* This marks the transaction starts instead of
|
* This marks the transaction starts instead of
|
||||||
|
|||||||
@ -65,11 +65,12 @@ static struct option long_options[] =
|
|||||||
{"header", no_argument, 0, 'H'},
|
{"header", no_argument, 0, 'H'},
|
||||||
{"key_file", required_argument, 0, 'K'},
|
{"key_file", required_argument, 0, 'K'},
|
||||||
{"aes_algo", required_argument, 0, 'A'},
|
{"aes_algo", required_argument, 0, 'A'},
|
||||||
|
{"replace", required_argument, 0, 'R'},
|
||||||
{"help", no_argument, 0, '?'},
|
{"help", no_argument, 0, '?'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
char *binlog_check_version = "2.1.0";
|
char *binlog_check_version = "2.2.0";
|
||||||
|
|
||||||
int
|
int
|
||||||
maxscale_uptime()
|
maxscale_uptime()
|
||||||
@ -81,14 +82,14 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
int debug_out = 0;
|
int debug_out = 0;
|
||||||
int fix_file = 0;
|
|
||||||
int mariadb10_compat = 0;
|
int mariadb10_compat = 0;
|
||||||
char *key_file = NULL;
|
char *key_file = NULL;
|
||||||
char *aes_algo = NULL;
|
char *aes_algo = NULL;
|
||||||
int report_header = 0;
|
int report_header = 0;
|
||||||
char c;
|
char c;
|
||||||
|
BINLOG_FILE_FIX binlog_file = {0, false, false};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "dVfMHK:A:?", long_options, &option_index)) >= 0)
|
while ((c = getopt_long(argc, argv, "dVfMHK:A:R:?", long_options, &option_index)) >= 0)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -103,7 +104,7 @@ int main(int argc, char **argv)
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
fix_file = 1;
|
binlog_file.fix = true;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
mariadb10_compat = 1;
|
mariadb10_compat = 1;
|
||||||
@ -114,6 +115,9 @@ int main(int argc, char **argv)
|
|||||||
case 'A':
|
case 'A':
|
||||||
aes_algo = optarg;
|
aes_algo = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'R':
|
||||||
|
binlog_file.pos = atol(optarg);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
printUsage(*argv);
|
printUsage(*argv);
|
||||||
exit(optopt ? EXIT_FAILURE : EXIT_SUCCESS);
|
exit(optopt ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
@ -162,7 +166,7 @@ int main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = open(path, fix_file ? O_RDWR : O_RDONLY, 0666);
|
int fd = open(path, binlog_file.fix ? O_RDWR : O_RDONLY, 0666);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
printf("ERROR: Failed to open binlog file %s: %s.\n",
|
printf("ERROR: Failed to open binlog file %s: %s.\n",
|
||||||
@ -203,7 +207,7 @@ int main(int argc, char **argv)
|
|||||||
MXS_NOTICE("Checking %s (%s), size %lu bytes", path, inst->binlog_name, filelen);
|
MXS_NOTICE("Checking %s (%s), size %lu bytes", path, inst->binlog_name, filelen);
|
||||||
|
|
||||||
/* read binary log */
|
/* read binary log */
|
||||||
int ret = blr_read_events_all_events(inst, fix_file, debug_out | report_header);
|
int ret = blr_read_events_all_events(inst, &binlog_file, debug_out | report_header);
|
||||||
|
|
||||||
mxs_log_flush_sync();
|
mxs_log_flush_sync();
|
||||||
|
|
||||||
@ -236,7 +240,7 @@ printUsage(const char *progname)
|
|||||||
printVersion(progname);
|
printVersion(progname);
|
||||||
|
|
||||||
printf("The MaxScale binlog check utility.\n\n");
|
printf("The MaxScale binlog check utility.\n\n");
|
||||||
printf("Usage: %s [-f] [-d] [-v] [<binlog file>]\n\n", progname);
|
printf("Usage: %s [-f] [-M] [-d] [-V] [-H] [-K file] [-A algo] [-R pos] [<binlog file>]\n\n", progname);
|
||||||
printf(" -f|--fix Fix binlog file, require write permissions (truncate)\n");
|
printf(" -f|--fix Fix binlog file, require write permissions (truncate)\n");
|
||||||
printf(" -d|--debug Print debug messages\n");
|
printf(" -d|--debug Print debug messages\n");
|
||||||
printf(" -M|--mariadb10 MariaDB 10 binlog compatibility\n");
|
printf(" -M|--mariadb10 MariaDB 10 binlog compatibility\n");
|
||||||
@ -244,6 +248,7 @@ printUsage(const char *progname)
|
|||||||
printf(" -K|--key_file AES Key file for MariaDB 10.1 binlog file decryption\n");
|
printf(" -K|--key_file AES Key file for MariaDB 10.1 binlog file decryption\n");
|
||||||
printf(" -A|--aes_algo AES Algorithm for MariaDB 10.1 binlog file decryption (default=AES_CBC, AES_CTR)\n");
|
printf(" -A|--aes_algo AES Algorithm for MariaDB 10.1 binlog file decryption (default=AES_CBC, AES_CTR)\n");
|
||||||
printf(" -H|--header Print content of binlog event header\n");
|
printf(" -H|--header Print content of binlog event header\n");
|
||||||
|
printf(" -R|--replace Replace the event at pos with an IGNORABLE EVENT\n");
|
||||||
printf(" -?|--help Print this help text\n");
|
printf(" -?|--help Print this help text\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user