From 30ee5096db101998dff5cdc3c8e7bf972edcdc23 Mon Sep 17 00:00:00 2001 From: Kirill Solomko Date: Tue, 21 Apr 2026 13:29:28 +0200 Subject: [PATCH] MT#64920 mediator improve session binlog_format setup * new function medmysql_set_session_binlog_format(medmysql_handler *mysql) that checks current binlog_format and sets it to 'statement' only if the current formed is mixed, as well as writes to the logs the current format and if the format is changed. * medmysql_handler_init() use medmysql_set_session_binlog_format(). * always stop mediator with L_CRITICAL if binlog_format cannot be changed, because with the "binlog admin" privilege there are no errors, nor warnings regardless of the current global binlog_format. * that is to address a scenario when mediator always changes binlog_format to 'statement' (because with the 'binlog admin' privilege it does not throw an error), and if the global format is 'row', it causes 'unsafe warnings' spam in mysql-error.log. Change-Id: Iaee992cf6e2bdf14095387256483b3a9f8b6f2da --- medmysql.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/medmysql.c b/medmysql.c index dfa38ae..7c43c22 100644 --- a/medmysql.c +++ b/medmysql.c @@ -385,6 +385,53 @@ static int medmysql_query_wrapper_tx(medmysql_handler *mysql, const char *stmt_s return !!err; } +static int medmysql_set_session_binlog_format(medmysql_handler *mysql) { + const char *query = "select LOWER(@@binlog_format)"; + if (medmysql_query_wrapper(mysql, query, strlen(query))) { + L_CRITICAL("Error getting DB value (query '%s'): %s", + query, mysql_error(mysql->m)); + return -1; + } + MYSQL_RES *res = mysql_store_result(mysql->m); + if (!res) { + L_CRITICAL("No result set returned from SQL (query '%s'): %s", + query, mysql_error(mysql->m)); + return -1; + } + MYSQL_ROW row = mysql_fetch_row(res); + if (!row || !row[0]) { + L_CRITICAL("No row returned from SQL (query '%s'): %s", + query, mysql_error(mysql->m)); + mysql_free_result(res); + return -1; + } + + if (strcmp("mixed", row[0])) + { + L_INFO("db '%s' binlog_format=%s", mysql->name, row[0]); + } + else + { + const char *set_query = "SET SESSION binlog_format = 'STATEMENT'"; + if (medmysql_query_wrapper(mysql, set_query, strlen(set_query))) + { + L_CRITICAL("Error setting session binlog_format = 'STATEMENT': %s", + mysql_error(mysql->m)); + mysql_free_result(res); + return -1; + } + else + { + L_INFO("db '%s' change session binlog_format old=%s new=%s", + mysql->name, row[0], "statement"); + } + } + + mysql_free_result(res); + + return 0; +} + static medmysql_handler *medmysql_handler_init(const char *name, const char *host, const char *user, const char *pass, const char *db, unsigned int port) { @@ -417,11 +464,12 @@ static medmysql_handler *medmysql_handler_init(const char *name, const char *hos L_CRITICAL("Error setting reconnect-option for %s db: %s", name, mysql_error(ret->m)); goto err; } - if (medmysql_query_wrapper(ret, "SET SESSION binlog_format = 'STATEMENT'", 39)) + + if (medmysql_set_session_binlog_format(ret) != 0) { - L_WARNING("Error setting binlog_format = 'STATEMENT' for %s db: %s", name, - mysql_error(ret->m)); + goto err; } + if(mysql_autocommit(ret->m, 1) != 0) { L_CRITICAL("Error setting autocommit=1 for %s db: %s", name,