Getting a connection
The primary entry point isIConnectionProvider, retrieved from the service container:
IConnectionProvider interface exposes two methods that reflect the read/write split:
The convention
$dbr (replica/read) and $dbw (write/primary) is used throughout MediaWiki’s codebase. Always use the correct handle for the operation you are performing.The read/write split
Large MediaWiki installations like Wikimedia run a primary MySQL server with many replica servers. Replicas handle all read traffic; the primary handles writes. TheIConnectionProvider interface encodes this pattern directly.
getReplicaDatabase()
Returns a connection to a replica (read-only). Use for all SELECT queries. Automatically load-balances across available replicas.
getPrimaryDatabase()
Returns a connection to the primary (read/write). Use for INSERT, UPDATE, DELETE, and any read that must see the latest committed data.
A complete read/write example
Supported database backends
MediaWiki is written primarily for MySQL/MariaDB, which is the canonical database and has the most optimized schema. The following backends are also supported:MySQL / MariaDB
The primary supported backend. Queries and schema are optimized for it. Required for production Wikimedia deployments.
PostgreSQL
Supported to varying degrees. Additional configuration and known issues are documented in
docs/databases/.SQLite
Supported for small or development installations. Not suitable for high-traffic production use.
The abstract schema system (see Database Schema) allows a single table definition to generate correct DDL for all three backends.
Transaction handling
By default, MediaWiki opens a transaction at the first query in a request and commits it before sending the response. This means locks are held from query execution until the end of the request. To minimize lock contention, do as much computation as possible before issuing write queries. When you need tighter control, you can open an explicit transaction around a small group of writes:Replication lag
Replicas apply writes from the primary serially, so a long write query causes replicas to lag behind. MediaWiki’s load balancer avoids sending reads to a replica lagged by more than a few seconds (LoadBalancer::MAX_LAG_DEFAULT = 6 seconds, configurable via max lag in $wgLBFactoryConf).
When a replica is too far behind, MediaWiki enters lagged replica mode (ILBFactory::laggedReplicaUsed), which automatically shortens object cache and CDN cache expiry so stale data converges quickly.
To write lag-friendly code:
Split large writes
Break bulk writes into one-row-at-a-time loops. Multi-row
INSERT ... SELECT queries are the worst offenders and should be avoided. Do the SELECT first, then INSERT row by row.Read from replicas
For the vast majority of reads, replica data is acceptable. Sending all queries to the primary to avoid lag is not a scalable solution.
Query groups
Query groups direct replica reads to a preferred set of database hosts. This reduces cache misses by concentrating similar queries on the same host, and isolates expensive queries from impacting general traffic.| Group | Purpose |
|---|---|
api | Queries specific to api.php requests, set via ApiBase::getDB() |
dump | Dump and export maintenance scripts; affects all queries in the process |
vslow | Expected long-running queries (> 1 second on large wikis); use in jobs, maintenance scripts, or behind $wgMiserMode |
Cross-wiki database access
Some multi-wiki installations share tables (for example, a centraluser table) across wikis using $wgSharedDB. MediaWiki’s LBFactory provides cross-wiki connection management through getDBLoadBalancerFactory(), but for most extension development you should use IConnectionProvider directly and let the framework handle routing.
GROUP BY compatibility
MySQL allowsGROUP BY without listing all non-aggregate SELECT columns. PostgreSQL and SQLite are stricter and require every non-aggregate column in SELECT to also appear in GROUP BY. For this reason, avoid SELECT * in any query that uses GROUP BY.