diff options
author | Andrei <andrei.elkin@mariadb.com> | 2022-05-11 13:12:48 +0300 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2022-05-18 09:48:57 +0200 |
commit | 98ca71ab28fffbb65c4590cda904f1f0dfd975bb (patch) | |
tree | ca5328fabb095485459669c8ecaa4450b821e120 /sql/handler.h | |
parent | e03e72234aa59016c71c51b7adc5a59ae7b126b2 (diff) | |
download | mariadb-git-98ca71ab28fffbb65c4590cda904f1f0dfd975bb.tar.gz |
MDEV-28461 semisync-slave server recovery fails to rollback prepared transaction
that is not in binlog.
Post-crash recovery of --rpl-semi-sync-slave-enabled server
failed to recognize a transaction in-doubt that needed rolled back.
A prepared-but-not-in-binlog transaction gets committed instead
to possibly create inconsistency with a master (e.g the way it was observed
in the bug report).
The semisync recovery is corrected now with initializing binlog coordinates
of any transaction in-doubt to the maximum offset which is
unreachable.
In effect when a prepared transaction that is not found in binlog
it will be decided to rollback because it's guaranteed to reside
in a truncated tail area of binlog.
Mtr tests are reinforced to cover the described scenario.
Diffstat (limited to 'sql/handler.h')
-rw-r--r-- | sql/handler.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/sql/handler.h b/sql/handler.h index 53a8c655d60..c50e1ced377 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -963,6 +963,7 @@ typedef struct xid_t XID; */ typedef uint Binlog_file_id; const Binlog_file_id MAX_binlog_id= UINT_MAX; +const my_off_t MAX_off_t = (~(my_off_t) 0); /* Compound binlog-id and byte offset of transaction's first event in a sequence (e.g the recovery sequence) of binlog files. @@ -977,14 +978,22 @@ struct xid_recovery_member my_xid xid; uint in_engine_prepare; // number of engines that have xid prepared bool decided_to_commit; - Binlog_offset binlog_coord; // semisync recovery binlog offset + /* + Semisync recovery binlog offset. It's initialized with the maximum + unreachable offset. The max value will remain for any transaction + not found in binlog to yield its rollback decision as it's guaranteed + to be within a truncated tail part of the binlog. + */ + Binlog_offset binlog_coord; XID *full_xid; // needed by wsrep or past it recovery decltype(::server_id) server_id; // server id of orginal server xid_recovery_member(my_xid xid_arg, uint prepare_arg, bool decided_arg, XID *full_xid_arg, decltype(::server_id) server_id_arg) : xid(xid_arg), in_engine_prepare(prepare_arg), - decided_to_commit(decided_arg), full_xid(full_xid_arg) , server_id(server_id_arg) {}; + decided_to_commit(decided_arg), + binlog_coord(Binlog_offset(MAX_binlog_id, MAX_off_t)), + full_xid(full_xid_arg), server_id(server_id_arg) {}; }; /* for recover() handlerton call */ |