Skip to content

PXC-4603: Code refresh for - PXC 9.2.0#2111

Merged
kamil-holubicki merged 1259 commits into
percona:release-9.2.0from
kamil-holubicki:PXC-4603
Jun 26, 2025
Merged

PXC-4603: Code refresh for - PXC 9.2.0#2111
kamil-holubicki merged 1259 commits into
percona:release-9.2.0from
kamil-holubicki:PXC-4603

Conversation

@kamil-holubicki

Copy link
Copy Markdown
Contributor

No description provided.

Tor Didriksen and others added 30 commits December 12, 2024 16:36
Change-Id: I0db2bc1822efd3da64a5f3f095dd7c309d7dd635
Backport to 5.7.49.

Problem: Test used deprecated time zone name MET, and prints it in
result file. When OS changes the time zone name used when specifying
TZ=MET there is a result diff.

Solution: Switch from deprected MET to CET as the name for the time
zone.

Change-Id: I6c69c3ad62153a79c9337da4ecb4f5a13a248d56
Backport to 5.7.49.

Problem: Test used deprecated time zone name MET, and prints it in
result file. When OS changes the time zone name used when specifying
TZ=MET there is a result diff.

Solution: Switch from deprected MET to CET as the name for the time
zone.

Change-Id: I28e99f5f4738171c1587ca90c6302e1d9d32a13a
Change-Id: If71335c377a815bda02ce6cd11965d7e0005fee4
Change-Id: Id5a7e40d8c81a94bcd9c6977a367a28b9291780e
Change-Id: I67b284d5592f4111f73bee16270a47b234b81321
Backport to 5.7.49.

Access to /proc/$pid/task/$thread_id/mem is required by stacktrace
code.

Change-Id: I6b6f8dd5c07ae5e867e0358fcbeccd5c5cd29bde
              Item_rollup_sum_switcher::current_arg

Backport to 5.7.49.

Problem is seen when a subquery containing a aggregate
function with rollup is part of a row value comparator
and if there were no rows returned from the subquery.

cmp_item_row::store_value() evaluates the subquery and
goes ahead to store the values of the expressions in
the comparator without checking if the result was assigned
for the subquery. This leads to evaluation of a rollup
expression when it is marked as not to be evaluated as
aggregation was completed earlier. For the failing
query, AggregateIterator() does evaluate the expressions.
However HAVING clause does not qualify the rows. So the
result of the aggregation is never cached.

If a subquery returns empty result, bring_value()
would set the "null_value" to true.
cmp_item_row::store_value() now stores the value of
the underlying comparator objects only when the
result is not null. Else the result is set
to null.

Change-Id: I7bb17e621f1e5b439f6284c279ce69b80dace237
Backport to 5.7.49.

Breaking the comment for a mysys option definition
requires that no single word at the end of the comment
(or every 57 chars if the comment is longer than 57 chars * 2)
is longer 57 chars.
Fixed the logic to handle the lack of space.

Change-Id: I2f48da5e0d066c208606058d095c7706dc12722c
…d 32-bit value

Backport to 5.7.49.

Issue:
FTS_DOC_ID is a 64-bit field and can have values 2^32 and higher. However
current implementation only supports 32-bit value range. This limtation
takes the form of:
 - Assertions
 - Use of unsigned long type which resolves to 32-bit on some platforms
 - VLC (variable length coding) implementation supporting up to 35 buts

Fix:
Support 64-bit doc IDs:
 - Remove assertions
 - Replace use of unsigned long for doc ID deltas with uint64_t
 - Extend VLC functions to support full unsigned 64-bit range

Change-Id: Ifb56b33c5ec75e578391612eb371c41fc6aeef31
Backport to 5.7.49.

Problem: Test used deprecated time zone name MET, and prints it in
result file. When OS changes the time zone name used when specifying
TZ=MET there is a result diff.

Solution: Switch from deprected MET to CET as the name for the time
zone.

Change-Id: I6c69c3ad62153a79c9337da4ecb4f5a13a248d56
Change-Id: I678b4679985bde7241640dbd9560f38e4a8ea2d9
Change-Id: I664c8aa9b66e73be3485f162e8be1284887034f3
Change-Id: I2f473b9afde662d26df24699d4e2635d0485a07c
…imes out

postfix for build-failures on windows.

Change-Id: Ide5cc89e95286fad62ad11f89b3f6bfad421d9d4
Change-Id: I9fa7c3d7d8732934a44a1f80cd4b18fac890ae9e
…lly in .4node4rpl

Context:
runMultiCrashTest crashes a subset of the running data nodes in
a cluster in a rolling restart fashion or in parallel, to check
that whether the situations where the cluster survives or the
cluster dies are as expected.

Problem:
In one of the cases (4 replica), test gracefully crashes 3 of 4
replicas in a node group and expects the 4th replica to die as
well (via a crash insertion in QMGR). Then test checks that all
nodes expected to be dead are dead and that the remaining nodes
are alive, finally test start all nodes again. Problem is that,
when nodes are started (via mgmapi) sometimes the 4th node is
not yet connected to the cluster and therefore the 'start'
command fails.

Solution:
Ensure that, before start the nodes via mgmapi, all the nodes
are already connected to the cluster.

Change-Id: Ib2d4265f4816bc6b975570f69aebfe3952e9bb96
Change-Id: I2e3c4cd825fb9b09591bf39f25a80ba464ff880d
…lly in .4node4rpl

Backport to 7.6

Context:
runMultiCrashTest crashes a subset of the running data nodes in
a cluster in a rolling restart fashion or in parallel, to check
that whether the situations where the cluster survives or the
cluster dies are as expected.

Problem:
In one of the cases (4 replica), test gracefully crashes 3 of 4
replicas in a node group and expects the 4th replica to die as
well (via a crash insertion in QMGR). Then test checks that all
nodes expected to be dead are dead and that the remaining nodes
are alive, finally test start all nodes again. Problem is that,
when nodes are started (via mgmapi) sometimes the 4th node is
not yet connected to the cluster and therefore the 'start'
command fails.

Solution:
Ensure that, before start the nodes via mgmapi, all the nodes
are already connected to the cluster.

Change-Id: Ib2d4265f4816bc6b975570f69aebfe3952e9bb96
Change-Id: Ic189c9adaf5338a806d1520f3018eb1d88a12e91
Change-Id: I7c15787622dfbe8bde6dbfe713e186726806047f
Problem:
Ndb_cluster_connection destructor calls g_eventLogger::stopAsync()
in order to release the buffers used by the async log mechanism as
well as to stop the threads responsible for the async logging.
Problem is that, if g_eventLogger object is deleted before the
destructor of the Ndb_cluster_connection is called, program crash
because it is trying to use a method on a null object.

This can happen in two different ways:

1- Api programs deletes the logger object before deleting the
   Ndb_cluster_connection
2- ndb_end() is called before Ndb_cluster_connection is deleted.

Solution:
In cluster_connection Destructor do not call stopAsync() when
g_eventLogger object is NULL.
A warning is also added to inform API users that g_eventLogger
is *wrongly* deleted before cluster_connection Dtor is called.

Change-Id: I57ff648949a60b45841e8b568030259f1540180b
Change-Id: If85ac4aa815e775211fc3ab62629baa072212b75
Queries of the form SELECT DISTINCT..FROM t1 WHERE NOT IN(SELECT...)
would get transformed into an anti-join if possible, starting from 8.0+.
This made the optimizer not choose group skip scan for table "t1" which
otherwise, it would in 5.7 resulting in performance degradation for such
queries on 8.0+. Group skip scan is not chosen as the query is now no
more a single table query post the anti-join transformation and this
access method is enabled only for single table queries. The same
behaviour can be seen even for queries which are transformed into
semi-joins too. However, group skip scan access method could still be
picked for such queries if the access method is used only for duplicate
removal (i.e DISTINCT/GROUP BY without aggregation functions)
even in these cases.

Solution:
Enable group skip scan when there is only one table originally in the
query, irrespective of the number of semijoin tables present after
internal transformations and if the query doesn't contain aggregation
functions.

Change-Id: I8beb8996c1751b1ade4680582446760c2a24455f
Queries of the form SELECT DISTINCT..FROM t1 WHERE NOT IN(SELECT...)
would get transformed into an anti-join if possible, starting from 8.0+.
This made the optimizer not choose group skip scan for table "t1" which
otherwise, it would in 5.7 resulting in performance degradation for such
queries on 8.0+. Group skip scan is not chosen as the query is now no
more a single table query post the anti-join transformation and this
access method is enabled only for single table queries. The same
behaviour can be seen even for queries which are transformed into
semi-joins too. However, group skip scan access method could still be
picked for such queries if the access method is used only for duplicate
removal (i.e DISTINCT/GROUP BY without aggregation functions)
even in these cases.

Solution:
Enable group skip scan when there is only one table originally in the
query, irrespective of the number of semijoin tables present after
internal transformations and if the query doesn't contain aggregation
functions. Changes were made for hypergraph optimizer to take care
of "has_group_skip_scan" flag for join access paths. This flag indicates
the given access path can produce results with deduplication and/or
aggregation based on the query.

Change-Id: I8beb8996c1751b1ade4680582446760c2a24455f

Null-Merge branch 'mysql-8.0' into mysql-8.4
Issue:
  When clearing AHI index from all pages of the buffer pool, the block
  state may change to BUF_BLOCK_MEMORY before acquiring the block mutex.
  In these cases the AHI index will be null, and we must skip this block
  and go to the next instead of trying to make it null using
  btr_search_set_block_not_cached function.

Fix:
  Continue to next block after asserting that AHI index is null for
  blocks in other state (state other than BUF_BLOCK_FILE_PAGE and
  BUF_BLOCK_REMOVE_HASH).

Background:
  As indicated by AHI index's documentation, index may be modified to
  nullptr if btr_search_enabled is false and block is held in private in
  BUF_BLOCK_REMOVE_HASH state in buf_LRU_free_page(). This is what has
  happended in this scenario.

Change-Id: Ib0d07b1b1bf13c4cb8872bc06b97e95d86b74c40
Change-Id: I06077f436370cc92c9054b8b282aad006aa0e8e1
If the client connects to the read-write splitting port and sets

    SET sql_mode="ANSI_QUOTES"

(like Drupal does with PDO/PHP), the router logs:

2024-12-10 09:12:26 routing WARNING [7fd7e6709700] Unknown column
'06f96450-e53e-11ee-bcc3-005056ab1089:10830875' in 'field list'

which is the GTID to wait for when switching to the read-only server.

Change
======

- make the wait-for-gtid query ANSI_QUOTES safe by quoting the GTID
  with ' instead of "

Change-Id: Ia8ed1f2ceb41db3e29ad181cd086e66199e03a30
kamil-holubicki and others added 17 commits June 3, 2025 17:36
https://perconadev.atlassian.net/browse/PXC-4603

Implemented notify_state_change() method
Updated galera, wsrep-lib, wsrep-api repo pointers
https://perconadev.atlassian.net/browse/PXC-4603

Added component_connection_control suite for Jenkins execution
https://perconadev.atlassian.net/browse/PXC-4603

MTR fixes:
sp.cc::create_string() now returns false instead of true on success.
Adjusted logic in WSREP part.
https://perconadev.atlassian.net/browse/PXC-4603

MTR fixes:
sp.cc::create_string() now returns false instead of true on success.
Adjusted logic in WSREP part.

re-records (mysqld--help-notwin)
https://perconadev.atlassian.net/browse/PXC-4657

Fixes also:
PXC-4684: UPDATE query that matches two tables but modifies only one
causes an MDL BF-BF conflict on other nodes.

https://perconadev.atlassian.net/browse/PXC-4684

PXC-4657:

Problem:
We have tables t1 and t2 and an update trigger on t1 that inserts into
t2. If update on t1 doesn't change a row, no events related to update
are created however, t2 insert event is created by the trigger.
As the result a writeset corresponding to t1 update contains
Table_map_log_event related to t1 and t2. On the applier side it causes
locking of t1 and t2 tables, even if only t2 is modified. But as
the update to t1 was skipped on the source node, a writeset doesn't
contain t1-related certification keys.
If at the same time a DDL is executed on t1, Galera certification
mechanism doesn't see the dependency between these two transactions and
order them for parallel apply.
As both transactions acquire MDL locks on t1, on the applier side we
end up with BF-BF abort.

Cause:
Writeset related to t1 update does not contain t1-related certification
keys.

PXC-4684:

Problem:
For queries like
UPDATE t2 JOIN t1 USING (i) SET t2.d = t2.d+1, t1.d = t1.d;
t1 is not updated, as MySql detects that t1 row didn't change.
The result is a writeset having Table_map_log_event related to t1 and t2
but having only t2 certification keys.

Cause:
Transaction dependencies calculation is affected and BF-BF abort is
seen on replicated node that have more than one applier thread.

Solution:
In 'normal' case, when the row is updated, certification keys are added
from InnoDB level during row update. The update is skipped, but we still
need to add t1 to the certification keys in case there are triggers on
t1.
…case_table_names=1

Problem:
The PXC startup script grants the mysql.pxc.sst.role role access to the PERCONA_SCHEMA database to support PXB’s history feature.
However, when the lower_case_table_names = 1 setting is used in a PXC cluster, it results in duplicate role mapping entries —
one for the `PERCONA_SCHEMA` database and another for `percona_schema` database.
This happens because PXB creates the PERCONA_SCHEMA database using uppercase letters.

Solution:
To address this issue, a fix should be applied on the PXB side by renaming the PERCONA_SCHEMA database to lowercase.

As a temporary workaround, during grants in startup script we check whether lower_case_table_names = 1 is set.

If it is, we grant permissions for mysql.pxc.sst.role on the lowercase percona_schema database.
Otherwise, we use the original uppercase PERCONA_SCHEMA.
Re-records:
information_schema_cs

Fixes because of FLUSH PRIVILEGES statement depreciation:
galera_wsrep_ddl_access_checking
Re-records:
information_schema_cs
grant_dynamics
mysql_upgrade_grant
grant_dynamic_flush_privileges_upgrade
perfschema.privilege_table_io
all_persisted_variables
galera_as_slave_gtid_replicate_do_db

Fixes because of FLUSH PRIVILEGES statement depreciation:
galera_wsrep_ddl_access_checking
galera_wsrep_ddl_access_checking2
pxc_create_alter_view
connection_expire

FLUSH PRIVILEGES deprecated, but still supported, so following tests
were re-recorded:
galera_flush
galera_flush_gtid
galera_flush_local
galera_toi_read_only_server
connection_auth_mechanism_memory2

Other fixes:
main.view - fix in sql_view.cc (skip wsrep checks if table with the same
name exists)
gis.srs - fix in mysql_system_tables_fix.sql - fix upgrade grants
innodb.recovery_small_bp_read_deadlock - disabled because of
incompatible InnoDB page size

Tests that needed re-recording because of
https://bugs.mysql.com/bug.php?id=117618:
group_replication.gr_member_join_with_inbound_channel_error
Fix for galera.galera_ssl_upgrade MTR test

Updated expired server certificate.

openssl x509 -req -in galera.csr -CA galera-upgrade-ca-cert.pem -CAkey galera-key.pem -CAcreateserial -days 3650 -out galera-upgrade-server-cert.pem

Certificate request self-signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd

openssl verify -CAfile galera-upgrade-ca-cert.pem galera-upgrade-server-cert.pem
galera-upgrade-server-cert.pem: OK

openssl x509 -in galera-upgrade-server-cert.pem -noout -dates
notBefore=May 20 11:52:38 2025 GMT
notAfter=May 18 11:52:38 2035 GMT
Partial cherry pick of commit 50001cf from 8.4.4 merge.

1. WSREP thread user explicitly specified as 'system user'. This is
   because of upstream commit 174795e that changed the logic of setting
   'system user' as the executing user in processlist table. Previously
   WSREP threads had to have 'root' user set (commit de17518, PXC-4179)
   Tests re-recorded.
2. Upstream commit 174795e also changed the way of reporting Host in
   processlist table. Now it is empty instead of NULL. Tests re-recorded
3. Upstream commit 1b11bb9 changed the logic of handing view dropping.
   Necessary adjustments implemented in sql_view.cc
Upstream commit 3522088 causes gtid_zip thread to be visible in
p_s.processlist table. This affected some galera tests.
Above-mentioned thread was filtered out to fix tests.
Corrected PXB path in SST script
…s causes the node to exit

PXC-4688: Empty transaction stalls the replica thread

https://perconadev.atlassian.net/browse/PXC-4664
https://perconadev.atlassian.net/browse/PXC-4688

Both issues are the regression caused by fix for PXC-4173 (introduction
of wsrep_async_monitor).

Problem 1:
When node1 and node2 commit the transaction with the same gtid (after
setting 'gtid_next' to the same value), replicated node exits with
sigsegv.

Cause:
If the transaction with a given GTID was committed on local node, and
another, replicated transaction with the same GTID is being applied by
wsrep applier thread, we detect that this GTID was already committed and
attempt to skip the transaction
(gtid_pre_statement_checks() => skip_statement()).
In skip_statement() there is a code that marks a given transaction to be
skipped by wsrep_async_monitor. wsrep_async_monitor-related code is
valid only for async replica worker thread, not for wsrep applier.
We distinguish both by checking if thd is SYSTEM_THREAD_SLAVE_WORKER
(both galera and async worker) and 'wsrep_applier' flag. Check for
wsrep_applier was missing, so it was incorrectly detected, that we are
in the context of async worker thread. Then we did a dynamic_cast of
thd->rli_slave (of type Relay_log_info) to Slave_worker type.
Such a conversion gives a valid pointer only for async worker thread.
In case of wsrep applier, the object type is Relay_log_info, so
dynamic_cast results in nullptr. Then we dereference a pointer, and as
a consequence of being wsrep applier, we dereference nullptr.

Solution:
Added missing check for wsrep_applier, to access wsrep_async_monitor
path only from async worker thread.

For all similar places:
Added debug assertion.
Additionally, wrapped the block where we try to dereference a pointer
with a check against nullptr.

Note:
After fixing sigsegv, it is still possible to end up with a deadlock
(PXC-4665). It is an old issue.

Problem 2:
Committing an empty transaction on an async replica source causes the
PXC async replica node to stall.

Cause:
If an empty transaction is replicated from async source, PXC flow
commits empty transaction in Galera. This caused entering and releasing
wsrep_async_monitor. As this is an empty transaction, we need to commit
(and replicate) its GTID. It happens in
MYSQL_BIN_LOG::gtid_end_transaction(). Here we replicate and commit
an empty transaction with a given gtid. This path tried to acquire
wsrep_async_monitor again with the same sequence number, which caused
infinite wait.

Solution:
If we commit an empty transaction in Galera, but thd owns a GTID, it
means it will be commited later. In such a case postpone
entering/leaving releasing wsrep_async_monitor to the point when real
replication takes place.

Added MTR tests for both issues, however providing a reliable test for
PXC-4664 is not possible without fixing PXC-4665. PXC-4665 is an old
issue which causes a deadlock between wsrep applier and local session
(gtid lock vs galera commit_monitor).
https://perconadev.atlassian.net/browse/PXC-4173

Fix for PXC-4173 introduced wsrep_async_monitor.

Problem:
The original fix disables group commit for transactions replicated from
async source.

Cause:
Galera orders transactions during replication (when every transaction
gets its global sequence number). Then transactions are commited in
that order.
TOI transactions are replicated before execution, DML transactions are
replicated during the commit. This was the source of the problems in
PXC-4173: transactions are dispatched to parallel async workers, so it
may happen that DDL that should commit after DML from async replication
perspective gets ordered in Galera before DML. This caused a deadlock
(Galera wants to commit in the other order than server's commit manager)

The idea behind introducing wsrep_async_monitor was  to enforce the same
galera ordering as the node receives from async source.

1. The original implementation acquired wsrep_async_monitor at TOI start
and kept it acquired for the whole time of its execution until TOI end.
2. The original implementation acquired wsrep_async_monitor before
group commit pipeline and released it after.

As the consequence transactions were allowed to get into group commit
pipeline one by one (only one transaction at a time), effectively
disabling group commit (there was no possibility to group transactions).

Solution:
It is enough to enforce the order of replicating transactions in Galera
world to be the same as for async replication. Once the transaction is
replicated in galera, it has the same commit order as for async
replication. So there is no point in keeping wsrep_async_monitor for
a long time (especially for commit time). Doing so will allow multiple
transactions to enter group commit pipeline and be commited together.

A simple benchmark test with 4 async workes shows that this approach
enables back the group commit and improves the performance 3-4 times.

Added MTR test for wsrep_async_monitor.
@kamil-holubicki
kamil-holubicki requested a review from aybek June 4, 2025 14:23
@it-percona-cla

it-percona-cla commented Jun 4, 2025

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
4 out of 6 committers have signed the CLA.

✅ inikep
✅ adivinho
✅ aybek
✅ kamil-holubicki
❌ dlenev
❌ percona-ysorokin
You have signed the CLA already but the status is still pending? Let us recheck it.

(trunk) PXC-4664: Executing transactions with the same GTID on different nodes causes the node to exit
…pxc_encrypt_cluster_traffic is disabled the script fails to connect to donor given a bug.

https://perconadev.atlassian.net/browse/PXC-4687

Cherry pick of commit ef1db13

Problem:
The script was still keeping the SSL as required and fails given the server settings are not enforcing SSL usage.

Cause:
During check of SSL settings one condition was missed

Solution:
Implemented a check on SSL server variable server_ssl_ca to not be equal NULL. When null MySQL is passing the string "NULL" as such the string is not empty.
(trunk) PXC-4687: When executing SST with clone script and not using SSL and pxc_encrypt_cluster_traffic is disabled the script fails to connect to donor given a bug.
https://perconadev.atlassian.net/browse/PXC-4173

Post-push fix. MTR test is valid only for debug builds. Added missing
include files.
https://perconadev.atlassian.net/browse/PXC-4603

information_schema_ci - remaining merge conflict solved
connection_reset_by_peer - made the test common with standard x suite
https://perconadev.atlassian.net/browse/PXC-4603

PXC-4676: Code refresh for  - PXC 8.4.5

https://perconadev.atlassian.net/browse/PXC-4676

Fixed MYSQL_MAINTAINER_MODE=ON build.
When mysqlbinlog.cc was compiled, WITH_WSREP was undefined. It caused
One Definition Rule violation, because handler.h is included indirectly
in several compilation units and it contains legacy_db_type that has
values conditionally compiled in (WITH_WSREP).

There is no reason why WITH_WSREP should be undefined for mysqlbinlog.cc
https://perconadev.atlassian.net/browse/PXC-4603

Partial cherry pick of commit 2ef6a20 (8.4)

1. Fixed detection of Valgrind in SST script
2. Fixed not initialized 'unmasked_server_id' member of the header of
Intvar_log_event. It is not used, but it was detected by Valgrind in
galera.galera_log_bin MTR test. The event is stored in gcache with this
uninitialized value, them msync-ed with the file during server shutdown
which triggers Valgrind waring.
@kamil-holubicki
kamil-holubicki merged commit 55b4be1 into percona:release-9.2.0 Jun 26, 2025
11 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.