I'm running a LAMP with ubuntu server 12, mysql innodb_version 5.5.49 on a WordPress platform (3 websites virtualized). Has been running without issue for about 2 years, but I just started getting an error "Error establishing a database connection" error. My other virtualized sites get a "max connections exceeded" error occasionally as well. No new plugins, no db changes.
When I log into mysql as root and run show full processlist;
I get a list of 150 Sleep processes spawned by only one of my site's primary login. Of course, 150 is my max_connections limit, so these processes are dragging the entire server down. Given the time each one is up, it appears that about 6 are being spawned every second.
My problem is that I've run out of troubleshooting ideas. I'm a DBA neophyte to be sure. Here's what I've tried so far:
- Looked at current traffic to the site to see if I was getting attacked. Nothing out of the ordinary there. Just in case, I changed where my DNS pointed for a brief time, but the processes were still being spawned. I think this rules out an attack or SQL injection.
- Tried setting wait_timeout=60, but even this wasn't short enough given the rate of process spawning. No difference.
- Updated WP, disabled all WP plugins and switched themes. No change. AFAIK, WP doesn't even use persistent db connections, so it shouldn't even be a WP issue.
For now I've limited the max processes that that single site can run to 50% of the max_connections, so my other sites are actually running. Willing to try just about anything at this point. Debugging insight please.
Here's the output from the MySQL log file that I briefly enabled:
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 669
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 667
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 591
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 568
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 561
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 553
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 541
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 461
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 439
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 393
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 359
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 301
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 299
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 297
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 13
7990364 Query SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 1
Here are the results from:
EXPLAIN SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_loved' AND post_id = 669;
1 | SIMPLE | wp_postmeta | ref | post_id,meta_key | post_id | 8 | const | 5 | Using where
Results from show create table wp_postmeta;
| wp_postmeta | CREATE TABLE `wp_postmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`meta_key` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meta_value` longtext COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`),
KEY `meta_key` (`meta_key`(191))
) ENGINE=InnoDB AUTO_INCREMENT=3360 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
Also:
innodb_buffer_pool_size: 134217728
*************************** 1. row ***************************
Name: wp_postmeta
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 1388
Avg_row_length: 247
Data_length: 344064
Max_data_length: 0
Index_length: 131072
Data_free: 72351744
Auto_increment: 3360
Create_time: 2016-04-22 13:46:34
Update_time: NULL
Check_time: NULL
Collation: utf8mb4_unicode_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
The size of the database is about 5MB.
This is a tiny DB, I honestly think this is potentially a problem with the WP code. It's not a matter of individual queries taking a long time, but that the max_connections
is filled up. Every time I check, max_connections
is always maxed out. Spawning 6/second.
Best Answer
(Partial answer only for the queries shown, you maybe identify other offenders when this is fixed.)
For this query the best index would be
(post_id, meta_key)
, but becausemeta_key
is defined asvarchar(255)
with theutf8mb4
charset, such index would be too big with standard settings.You can instead use
To create index which is not as optimal but still gives a bit better performance by accessing less rows from the table.
You might try to create the optimal index if you check and change the
innodb_large_prefix
setting (but it has some additional requirements about the row format as mentioned in the manual). That would lead to index-only ref access which is as fast as a query can be optimized using indexes.