Commit graph

373 commits

Author SHA1 Message Date
Aaron Schulz
c1e1512698 rdbms: improve LoadBalancer connection pool reuse (ii)
Make DBConnRef enforce the DB domain selected during its lifetime
and allow more nested and successive use of the same connection handle
via DBConnRef. This can avoid extra connections in some cases where
getConnection()/getConnectionRef() is used.

Also:
* Reduce the number of connection pools arrays from six to two
* Merge getLocalConnection()/getForeignConnection() into one method
* Expand various related code comments

Since LoadBalancer::getReadOnlyReason() no longer user the local domain
but rather DOMAIN_ANY, it should not result in "USE" errors if the local
domain does not have a database on the server.

This version of the patch removes the unused reuseConnectionInternal()
method (the method was previously added back to the patch by mistake).

Bug: T226595
Change-Id: I62502f4de4f86a54f25be1699c4d1a1c1baee60b
2022-10-18 17:23:44 -07:00
jenkins-bot
11de30462e Merge "rdbms: remove DB domain parameter from various lag/read-only methods" 2022-10-18 23:17:23 +00:00
Aaron Schulz
561753416c rdbms: remove DB domain parameter from various lag/read-only methods
This effects:
* LoadBalancer::getReadOnlyReason()
* LoadBalancer::getLaggedReplicaMode()
* LoadBalancer::isPrimaryRunningReadOnly()
* LoadBalancer::getRandomNonLagged()

The lag/read-only mode is designed to be tracked per-server. The DB domain
is not useful here, and passing one complicates callers, causing needless
cache fragmentation, and cause can errors when a foreign LoadBalancer falls
back (or is provided) a local DB domain (which might not reside on the server).

Clarified some related "server" vs "DB" terminology in comments.

Bug: T318904
Change-Id: I3e09c1915d012db36be1bc505e00dcb0603fd388
2022-10-19 09:59:17 +11:00
jenkins-bot
6551e19d39 Merge "rdbms: Instead of reconfiguring all of LB, just remove depooled db" 2022-10-17 10:54:34 +00:00
Aaron Schulz
b23c6deb4e rdbms: remove DB domain parameter from LoadMonitor methods
The lag/read-only mode is designed to be tracked per-server.

The DB domain is not useful here, and passing one complicates callers,
causing needless cache fragmentation.

Change-Id: Ifd08659afadc4f7ae81b6d6f71c9b8032f3860b5
2022-10-12 14:41:22 +00:00
Amir Sarabadani
8a474d311f rdbms: Instead of reconfiguring all of LB, just remove depooled db
Bug: T298485
Change-Id: Id6d74c186dedc6253f56f29a6362b39d9be45093
2022-10-12 16:12:10 +02:00
jenkins-bot
056421a7b2 Merge "rdbms: Drop deprecated functions from LoadBalancer" 2022-09-29 17:31:18 +00:00
Amir Sarabadani
6b1d6e622d rdbms: Drop deprecated functions from LoadBalancer
- ::haveIndex()
  - ::isNonZeroLoad()

Deprecated in 1.34 and unused.

Change-Id: I08f8d8cad51ab1ec3c385c06737116d7ab71f2ca
2022-09-29 17:10:59 +00:00
Ladsgroup
4edae94817 Revert "rdbms: improve LoadBalancer connection pool reuse"
This reverts commit 76be4dca81.

Reason for revert: Caused T318904

Bug: T318904
Change-Id: I92f23205b4d62f69c0f27af40f972f104d1a7a7c
2022-09-29 12:12:14 +00:00
Aaron Schulz
76be4dca81 rdbms: improve LoadBalancer connection pool reuse
Make DBConnRef enforce the DB domain selected during its lifetime
and allow more nested and successive use of the same connection handle
via DBConnRef. This can avoid extra connections in some cases where
getConnection()/getConnectionRef() is used.

Also:
* Reduce the number of connection pools arrays from six to two
* Merge getLocalConnection()/getForeignConnection() into one method
* Expand various related code comments

Bug: T226595
Depends-On: If808cbab429d41e1f2289683533e4a781a4bdf5e
Change-Id: I540b08920997c57cad6445ddb09d8e663eaf4714
2022-09-23 10:53:58 +10:00
Umherirrender
b15e689d49 Remove unused local variables
Various variables are left from ealier refactor are now unused
and can be removed to make the code easier to read

Change-Id: Id51770af1f08e85c7e7a02234a2cd2ab5b47ee7a
2022-09-19 23:07:07 +02:00
Alexander Vorwerk
44c197d06a rdbms: Use plain array to store position data
Bug: T317606
Change-Id: Ifcc103cbb4ebdc2baf768bc7ded9cb23aae73e25
2022-09-14 14:28:24 +00:00
Kunal Mehta
499a1fe497 rdbms: Move Database::factory() to DatabaseFactory service
We also bring along Database::attributesFromType(), which relied on the
private ::getClass(). This requires us to inject DatabaseFactory through
the LBFactory/LoadBalancer hierarchy.

Database::factory() is now soft deprecated. All callers outside of
includes/installer/ still need migration.

Bug: T299691
Bug: T315270
Change-Id: I7d057a9438f1b097554679975e4e9b2fc99e7c2b
2022-08-31 10:53:50 +10:00
Aaron Schulz
fe7301c9ba rdbms: remove getTopologyRootPrimary() and clean up related fields/parameters
This method is unused and the naming is not very clear in terms of what
it returns (server name vs config map). Removing it reduces externally
exposed complexity.

Optimize DBConnRef::getServerName() when the server index is known.
Use this to eliminate the "topologicalMaster" parameter from Database.

Rename internal fields and paramters in Database to use "primary"
instead of "master", for consistency.

Add some additional clarifying comments.

Bug: T299691
Change-Id: I98515fa02a58a4c72a06f1ff283b249b1617c886
2022-08-26 12:26:10 -07:00
Amir Sarabadani
69840f27e0 rdbms: Switch to getConnectionInternal() in getPrimaryPos()
It's causing running Echo maint scripts to error with:
Cannot close DBConnRef instance; it must be shareable

Change-Id: Ic3c2c499a67e71ba9a3e3cd9af2d7eee5e582ac9
2022-08-22 17:18:25 +00:00
jenkins-bot
b6ded77b40 Merge "rdbms: Clean up file doc comments" 2022-08-10 05:21:14 +00:00
jenkins-bot
5538b4c0ac Merge "rdbms: add getDomainChangeException() call to DBConnRef::dbSchema()" 2022-08-10 04:14:36 +00:00
Timo Tijhof
90babf174a rdbms: Clean up file doc comments
* Document what the LBFactory/LoadBalancer (sub)classes do.

* Move useful descriptions from file doc to class doc so that we don't
  pointlessly maintain it in two places, and to allow for the file
  block to be consistently visually ignored instead of sometimes
  containing useful information.

  This patch removes various non-applicable or unrelated descriptions
  from the file block that were blindly copy-pasted, thus proving my
  point. It also removes two duplicate/clashing definition of the
  'Database' defgroup. Keeping only the primary one in IDatabase.php.

* Move ingroup tag to class block, as indexing the source file
  in Doxygen creates noise in the navigation sidebar and does not
  add add any benefit.

* Fix dead-end reference to a sqlite/README. I'll rework this
  in a later patch.

Change-Id: Iad0e67d766f4a7d5b97e7a471b49f2d8e60c506b
2022-08-09 12:53:32 +00:00
Aaron Schulz
eebb138bd9 rdbms: add getDomainChangeException() call to DBConnRef::dbSchema()
This matches the DB domain logic enforcement in the other class methods.

Change-Id: Ibc8603790de1e7a11ab9d07cc0a6473113ed37a6
2022-08-08 15:45:18 -07:00
daniel
5b0b54599b Allow DB config to be reloaded on the fly
This introduces $wgLBFactoryConf['configCallback'] which can be set to a
function that returns updates to be applied to $wgLBFactoryConf. The new
method LBFactory::autoreConfigure() can be called to check the callabck
and, if the config changed, reconfigure all existing LoadBalancers.

Reconfiguring the LoadBalancers causes all open connections to be
invalidated; however, any DBConnRef instances will remain valid and will
acquire a fresh connection from the LoadBalancer automatically when
appropriate.

As a proof of concept, this patch adds support for config reloding
into WikiExporter.

Bug: T298485
Change-Id: I6c3ffde62f6e038730736abe980befd90ec43e1a
2022-08-05 17:32:12 +02:00
Brian Wolff
ddacfae863 cast db name to string when checking if it is read only [php8.1]
According to docs on IDatabase::getDBName, a database does not
neccessarily have a name, so the function may return null in
such a case.

This fixes a unit test failure on php8.1 involving making cache
keys out of nulls

Bug: T313663
Change-Id: Iba880e2060d9c04ff07b883500cd653148eb54bf
2022-07-28 09:11:07 -07:00
Timo Tijhof
257456a13c rdbms: Remove LBFactory destructor
Follows-up I3adb57cbb1fd which added this in 2016 "just in case".

This has been causing fatal errors for several year since due to
LoadBalancer::closeAll calling into objects such as $this->logger,
which have in turn already began their own shutdown.

Destructors should generally be minimal and self-contained, which
these were not.

I could not find what case this is for, but I do note that the
Database objects have their own `__destruct` which calls
IDatabase::closeConnection, as implemented by DatabaseMysqli,
which means even if php-mysqli fails to disconnect, we should still
perform our own disconnect at the end of the process via destructors.

I've also removed the debug message while at it, as it appears to be
unreachable in practice and there are no explicit callers to closeAll.

Bug: T214734
Change-Id: I1ca2ad394fe39d444602d95e64e33408da3bce03
2022-07-21 15:17:28 -05:00
Tim Starling
0c92bc8a96 rdbms: Instrument LoadBalancer with statsd metrics
* Export the LoadMonitor weight metric to statsd on each global cache
  miss.
* Export the replication lag at the same time. This can replace the
  getLagTimes.php cron job and should eliminate the sawtooth effect seen
  in the cron job exports, which is presumably due to the offset
  between cron job start time and heartbeat time. It should also work
  around the bug which causes s3 to be missing.

Also:

* Fix a log message in TransactionProfiler. actualSeconds -> actual
  since this log message is used for counts as well as time.

Bug: T313004
Change-Id: I61e45870d750019ed2c92f45b2f8b9c33a7e7d65
2022-07-20 05:36:06 +00:00
jenkins-bot
78a3f54963 Merge "rdbms: Improve documentation around false/bool" 2022-07-13 16:02:48 +00:00
Matěj Suchánek
1865180ae7 Do minor code cleanup
Remove dead code and fix typos. Should cause no change in behavior.

Change-Id: I5d293b842bc93a28b8bcd799a31b5e6e30fe692e
2022-06-24 13:52:42 +02:00
Umherirrender
133760bf38 rdbms: Improve documentation around false/bool
Change type bool in union types to false where true is not allowed

Add false to DatabaseSqlite::getFulltextSearchModule

Change-Id: I1199b261c4e5c3f6ff184c756f46f2650b16b0c9
2022-06-18 10:33:40 +02:00
Aaron Schulz
3ce1067594 rdbms: add Database::flushSession() $mode safety parameter
This matches the begin(), commit(), and rollback() methods.

Change-Id: I3e66582052b2f42b2260bcf02b102caea8986f0a
2022-06-16 19:54:35 +00:00
Aaron Schulz
b6b53a0412 rdbms: make approvePrimaryChanges() trigger ping() in more cases
If there are row or named locks held, ping() should be called to
make sure that the locks where not lost. If they were lost, then
no transactions should be committed.

Slightly optimize isWriteQuery() by checking QUERY_CHANGE_TRX.

Bug: T307133
Change-Id: I8f97e1e3a4aa72c31ac2d642511af8dadf070b07
2022-06-01 20:45:36 +00:00
jenkins-bot
a04d835b14 Merge "rdbms: Normalize DBTransactionSizeError message" 2022-05-13 20:00:20 +00:00
Amir Sarabadani
a294e715a4 rdbms: Replace getConnection with getLazyConnectionRef
This would simplify the code for its users a lot.

Bug: T255493
Depends-On: I6ab4440a13f4682dd3a6e9cfc6c629222fbeab8a
Change-Id: I6e7544763bde56fc1e19de0358b71ba984a978ca
2022-05-12 07:43:03 +02:00
Amir Sarabadani
cf3a41a7c0 rdbms: Normalize DBTransactionSizeError message
The actual seconds vary, this makes the errors not getting aggregated in
logstash

Bug: T300194
Change-Id: Ibc6d6a3d8831b23a507f9175a4f9030975a1d5d9
2022-05-05 07:24:28 +02:00
Tim Starling
8632b5920a Replace LoadBalancer/LBFactory callback iteration with generators
Callback style iteration made sense before generators existed, but
generators make for simpler code. The "call method" variants made
sense before closures existed but defeat static analysis.

So, in LBFactory:

* Add ILBFactory::getAllLBs()
* Deprecate ILBFactory::forEachLB()
* Remove LBFactory::forEachLBCallMethod(), was protected.
* Add LBFactory::getLBsForOwner(), which is protected and has the
  internal interface in @return. Adding a new abstract method breaks
  Wikibase tests despite LBFactory not being stable to extend.
* Migrate callers. Generators allow you to return/break from the middle
  of the loop, which implies a little rearrangement for some callers.

In LoadBalancer, connections supposedly of type IDatabase were
routinely type-hinted as Database in closure parameters so that methods
could be called that were not in the interface. So it's convenient to
get rid of public iteration methods entirely in favour of private
methods returning Database[].

* Hard-deprecate ILoadBalancerForOwner::forEachOpenConnection()
  and replace it with a private generator method since nothing called
  it externally except for core tests.
* Hard-deprecate ILoadBalancerForOwner::forEachOpenPrimaryConnection()
  and replace it with a private generator. DeferredUpdates needed it for
  iterating over IDatabase::explicitTrxActive(), so add
  ILoadBalancer::explicitTrxActive() as a replacement.
* Replace private method LoadBalancer::forEachOpenReplicaConnection()
  with a generator.

Depends-On: If0b382231e27d6d1197fb7b6aef6ab50335df4e5
Change-Id: I64514e77b9bfe737be5b12e1d3c9c49976bb522f
2022-04-29 08:58:17 +10:00
Tim Starling
05701ffc40 rdbms: Remove instance ownership concept
Instance ownership is supposed to protect LoadBalancer and Database
against unauthorized calls to internal methods other than by the owning
LoadBalancer/LBFactory. This seems like unnecessary complexity. It was
introduced for T231443 and T217819, but the link was speculative and in
the end it didn't help to fix or isolate those bugs. Since then it has
caused a production error (T303885) and an intermittent CI failure
(T292239).

Instead, split the ILoadBalancer interface, introducing
ILoadBalancerForOwner, which contains the methods which are only safe
to call by LBFactory or by the caller of LBFactory::newMainLB(). This
allows phan to statically detect inappropriate calls to internal
methods.

Ownership was used for convenience for two things unrelated to its
original purpose:

* Suppressing calls to ScopedCallback::newScopedIgnoreUserAbort() when
  the caller has already called it. But nested calls are apparently
  harmless, so I just called it unconditionally.
* Suppressing exceptions from Database::close(). I extended the
  behaviour for owned instances to apply to all instances, so even
  unowned instances will no longer throw on close.

CodeSearch suggests nothing in extensions is calling these methods with
an owner parameter. One extension (Wikibase) overrides a method with an
owner parameter in a test mock class and so needs to be simultaneously
updated.

Depends-On: Ib03aba9d8f5f05b875a321d00b14483633a636a8
Change-Id: I27ba4973d24d759c88b3868c95e7db875801ca0c
2022-04-26 11:48:46 +10:00
jenkins-bot
d2e7be31d8 Merge "rdbms: make automatic connection recovery more robust" 2022-04-14 01:33:46 +00:00
Aaron Schulz
db36853718 rdbms: make automatic connection recovery more robust
Rename canRecoverFromDisconnect() in order to better describe
its function. Make it use the transaction ID and query walltime
as arguments and return an ERR_* class constant instead of a bool.
Avoid retries of slow queries that yield lost connection errors.

Track session state errors caused by the loss of named locks or
temp tables (e.g. during connection loss). Such errors will prevent
further queries except for rollback() and flushSession(), which must
be issued to resolve the error.

Add flushPrimarySessions() methods to LBFactory/LoadBalancer
and use it in places where session state loss is meant to be
safely aknowledged.

Change-Id: I60532f86e629c83b357d4832d1963eca17752944
2022-04-14 11:09:31 +10:00
Amir Sarabadani
280c2ed0d3 rdbms: Fold MaintainableDBConnRef into DBConnRef
We really don't need this complexity and it prevents us from improving
connection management.

MaintainableDatabase should stay but the connection ref shouldn't.

Bug: T255493
Change-Id: I867301dc7fa07cac298f8faba9cf82ca4617f50e
2022-04-14 01:57:11 +02:00
Ladsgroup
31c1ca8658 Revert "rdbms: make automatic connection recovery apply to more cases"
This reverts commit 4cac31de4e.

Reason for revert: Blocking the train, reverting the chain.

Change-Id: I7f275b3a25379c6f3256e90947c8eed4b232c0f4
2022-03-17 20:11:10 +01:00
Ladsgroup
c527d0b7df Revert "rdbms: provide $owner argument in LoadBalancer::flushPrimarySessions()"
This reverts commit ee3c65d541.

Reason for revert: Blocking the train, going to revert the whole chain.

Change-Id: I553115f310d93f98f7c6a2a77de28c4dda7762da
2022-03-17 18:28:09 +00:00
Ladsgroup
a8c5232702 Revert "rdbms: fix owner id and RELEASE_ALL_LOCKS query in session flushing methods"
This reverts commit eed58f2f61.

Reason for revert: Blocking the train, going to revert the whole chain

Change-Id: I64f9e5a9dde106671783f958a686ca697182077b
2022-03-17 18:25:48 +00:00
Aaron Schulz
eed58f2f61 rdbms: fix owner id and RELEASE_ALL_LOCKS query in session flushing methods
Use the LoadBalancer id in flushPrimarySessions(), not the LBFactory one,
and use assertOwnership() to check $owner, similar to other methods.

In DatabaseMysqlBase::doFlushSession(), change RELEASE_ALL_LOCKS() query
to use RELEASE_LOCK(), since only newer MariaDB versions (>=10.5.2) support
it. No errors were thrown in the method since they are suppressed, but the
syntax error would cause the transaction to be placed in an error state.

Add assertion to testTransactionCallbackChains() that would otherwise fail.

Randomize lock names in lock() tests to avoid contention.

Bug: T292239
Bug: T303887
Follow-Up: ee3c65d541
Follow-Up: 4cac31de4e
Change-Id: I414d737028338cfd5369eee24576df4aa26a2f6f
2022-03-17 02:55:43 +00:00
Aaron Schulz
ee3c65d541 rdbms: provide $owner argument in LoadBalancer::flushPrimarySessions()
This avoids DBUnexpectedError in LBFactory::flushPrimarySessions()

Follow-up: 4cac31de4e
Change-Id: I6b6e274135d842f379d71fb9efb42758984afc78
2022-03-15 10:42:21 -07:00
jenkins-bot
b9b75d9613 Merge "rdbms: make automatic connection recovery apply to more cases" 2022-03-10 00:08:35 +00:00
jenkins-bot
fc8b8e77fe Merge "Fix various documentation related to scalar types" 2022-03-09 21:58:03 +00:00
Umherirrender
d30b3d8926 Fix various documentation related to scalar types
Found by phan strict checks

Change-Id: If41d16b473baddd92cc4261cdc2bfbe65fedcb19
2022-03-09 20:49:51 +00:00
Amir Sarabadani
49a9d44b18 rdbms: Hard-deprecate LoadBalancer::getLazyConnectionRef
All deployed usages have been migrated.

Bug: T255493
Change-Id: I82683596d644bb61a109e79dde6b0cb22c72b399
2022-03-09 10:45:00 +01:00
Aaron Schulz
4cac31de4e rdbms: make automatic connection recovery apply to more cases
Rename canRecoverFromDisconnect() in order to better describe
its function. Make it use the transaction ID and query walltime
as arguments and return an ERR_* class constant instead of a bool.
Avoid retries of slow queries that yield lost connection errors.

Add methods and class constants to track session state errors
caused by the loss of named locks or temp tables. Such errors can
be resolved by a "session flush" method.

Make assertQueryIsCurrentlyAllowed() better distinguish ROLLBACK
queries from ROLLBACK TO SAVEPOINT queries. For some scenarios,
only full tranasction ROLLBACK queries should be allowed.

Add flushSession() method to Database and flushPrimarySessions()
methods to LBFactory/LoadBalancer.

Also:
* Rename wasKnownStatementRollbackError() and make it take the
  error number as an argument, similar to wasConnectionError().
  Add mysql error codes for query timeouts since they only cause
  statement rollbacks.
* Rename wasConnectionError() and mark it as protected. This is an
  internal method with no outside callers.
* Rename wasQueryTimeout(), remove some HHVM-specific code, and
  simplify the arguments.
* Make executeQuery() use a for loop for the query retry logic
  to reduce code duplication.
* Move the error state setting logic in executeQueryAttempt() up
  in order to reduce code duplication.
* Move the beginIfImplied() call in executeQueryAttempt() up to the
  retry loop in executeQuery(). This narrows the executeQueryAttempt()
  concerns to sending a single query and updating tracking fields.
* Make closeConnection() and doHandleSessionLossPreconnect() in
  DatabaseSqlite more consistent with the base class by releasing named locks.
* Mark trxStatus() as @internal.

Bug: T281451
Bug: T293859
Change-Id: I200f90e413b8a725828745f81925b54985c72180
2022-03-09 15:49:38 +11:00
Amir Sarabadani
0939e0faad rdbms: Change getConnectionRef to return with getLazyConnectionRef
This improves the performance of common requests.

Bug: T255493
Change-Id: Ia3d87267444c5b156bd9adb64e17d9e3607c38f0
2022-03-02 16:44:32 +00:00
Aaron Schulz
70d0e5fde5 Remove deprecated LoadBalancer::openConnection() method
Change-Id: Id88dc030c31b5509078412a1b845814252589dda
2022-02-14 23:03:09 -08:00
Tim Starling
e328de432e Throw an exception if the connection goes away
Fix the fixme in LoadBalancer::getServerConnection() and throw an
exception on connection loss if errors are not silenced. Otherwise a
server shutdown during a maintenance script always leads to an
InvalidArgumentException from DBConnRef::__construct().

Also, improve related log messages.

Change-Id: I8a5af3271264837d7a694382be4c70a735169f8d
2022-02-10 14:35:16 +11:00
Amir Sarabadani
058eb11d53 rdbms: Remove LB::safeGetLag()
This was soft-deprecated in 1.34 and codesearch doesn't bring anything
except this repo in github which is marked as defunct:
https://github.com/Brickimedia/GlobalContribs

Bug: T299392
Change-Id: I03943ca62688e2c9c41df3970ec49e644d46a8de
2022-01-21 16:18:14 +01:00