mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-34705: Binlog-in-engine: Fix hang with event group of specific size
If the event group fitted in the binlog cache without the GTID event but not with, the code would attempt to spill part of the GTID event as out-of-band data, which is not correct. In release builds this would hang the server as the spilling would try to lock an already owned mutex. Fix by checking if the GTID event fits, and spilling any non-GTID data as oob if it does not. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
@@ -3262,6 +3262,40 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
/*
|
||||
This is used to compute a compile-time constant max for the size (in bytes)
|
||||
of a GTID event (Gtid_log_event::max_size).
|
||||
|
||||
It is carefully written to take boolean parameters corresponding directly
|
||||
to each conditional in Gtid_log_event::write(), so that the calculation here
|
||||
will match the actual length computed by write().
|
||||
|
||||
Please ensure that that any new conditionals added in write() that affect
|
||||
the event length are similarly extended with a boolean parameter for this
|
||||
function so future code changes do not introduce incorrect result of this
|
||||
function.
|
||||
*/
|
||||
static constexpr uint32_t
|
||||
cap_gtid_event_size(uint32_t proposed_size)
|
||||
{
|
||||
/* This just because std::min is not constexpr in c++11. */
|
||||
return LOG_EVENT_HEADER_LEN +
|
||||
(proposed_size < GTID_HEADER_LEN ? GTID_HEADER_LEN : proposed_size);
|
||||
}
|
||||
static constexpr uint32_t
|
||||
get_gtid_event_size(bool fl_commit_id, bool fl_xa, bool fl_extra,
|
||||
bool fl_multi_engine, bool fl_alter,
|
||||
int bq_size, int gt_size)
|
||||
{
|
||||
return cap_gtid_event_size((fl_commit_id ? GTID_HEADER_LEN + 2 : 13) +
|
||||
(fl_xa ? 6 + bq_size + gt_size : 0) +
|
||||
(fl_extra ? 1 : 0) +
|
||||
(fl_multi_engine ? 1 : 0) +
|
||||
(fl_alter ? 8 : 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@class Gtid_log_event
|
||||
|
||||
@@ -3392,12 +3426,19 @@ public:
|
||||
involving multiple storage engines. No flag and extra data are added
|
||||
to the event when the transaction involves only one engine.
|
||||
*/
|
||||
static const uchar FL_EXTRA_MULTI_ENGINE_E1= 1;
|
||||
static const uchar FL_START_ALTER_E1= 2;
|
||||
static const uchar FL_COMMIT_ALTER_E1= 4;
|
||||
static const uchar FL_ROLLBACK_ALTER_E1= 8;
|
||||
static constexpr uchar FL_EXTRA_MULTI_ENGINE_E1= 1;
|
||||
static constexpr uchar FL_START_ALTER_E1= 2;
|
||||
static constexpr uchar FL_COMMIT_ALTER_E1= 4;
|
||||
static constexpr uchar FL_ROLLBACK_ALTER_E1= 8;
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
static constexpr uint32_t max_size=
|
||||
get_gtid_event_size(FL_GROUP_COMMIT_ID,
|
||||
(bool)(FL_PREPARED_XA|FL_COMPLETED_XA),
|
||||
true, FL_EXTRA_MULTI_ENGINE_E1,
|
||||
(bool)(FL_COMMIT_ALTER_E1|FL_ROLLBACK_ALTER_E1),
|
||||
MAXBQUALSIZE, MAXGTRIDSIZE);
|
||||
|
||||
Gtid_log_event(THD *thd_arg, uint64 seq_no, uint32 domain_id, bool standalone,
|
||||
uint16 flags, bool is_transactional, uint64 commit_id,
|
||||
bool has_xid= false, bool is_ro_1pc= false);
|
||||
@@ -3430,6 +3471,7 @@ public:
|
||||
}
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
uint32_t get_size() const noexcept;
|
||||
bool write(Log_event_writer *writer) override;
|
||||
static int make_compatible_event(String *packet, bool *need_dummy_event,
|
||||
ulong ev_offset, enum_binlog_checksum_alg checksum_alg);
|
||||
|
Reference in New Issue
Block a user