Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have an environment running WP 3.0.1 with a Master db and two slaves. I am using HyperDB to force all writes to go to the Master, and all reads to read from the two slaves.

I am experiencing a variety of issues in wp-admin pages where data is being written to the master, and WordPress attempts to read from a slave, and the data has not reached the slave yet. An example of this is when I hook 'dbx_post_advanced' to preset some category and custom taxonomy terms on new posts. I have verified that when I configure HyperDB to read and write from the Master alone, the 'dbx_post_advanced' hook works fine.

I'm currently looking into the following options to resolve this issue:

  • Dedicate only one web server to all wp-admin traffic
    • Configure that server to read and write to/from the Master db only
    • Configure the load balancer to route all /wp-admin url's to that web server
  • Configure HyperDB to read/write against the Master only for wp-admin pages
  • Setup MySQL Semisynchronous Replication

Let me know if you have any advice for this issue.

Thanks, Dave

share|improve this question
    
I just noticed that the latest version of HyperDB contains a new function called send_reads_to_master(), which should solve my problem technically. However, I'm not sure under what conditions this flag should be set. It does not appear anywhere in the code that I can tell. Anyone have any insight into that? –  Dave Morris Jan 17 '11 at 21:47
    
I noticed that you discussed this on the wp-hackers mailing list, as well. Did you get a solution working based on send_reads_to_master() and is_admin()? If so, you might want to post an answer here with some details. –  Dougal Campbell Feb 28 '11 at 18:31
add comment

3 Answers

You didn't mention a HyperDB revision so I'm assuming trunk @337290.

HyperDB's SRTM feature (send reads to master) works two ways. First, it keeps track of which tables have received writes during the current script and sends all subsequent reads for those tables to the master. Second, it gives you a way to force all reads to the master.

In the first case, it is still possible for a read to hit the slave after a write to the same table. If the read is a join query or another kind of query that can place table names far from the beginning of the query, it might slip through. If you can inspect the query that is improperly going to the slave, see if that's the case. If so, try increasing the substr length here:

if ( preg_match($pattern, substr($query, 0, 1000)) )

It's important to understand that the SRTM feature only keeps track during one script. So if you write a record (in 1st script) and then get redirected (now in 2nd script) and then try to read that record back out of the database, you will probably be reading from the slave on that second script.

Lastly, let me address the is_admin() idea. It's a fine idea, simple and effective. Add something like this to your db-config file:

if ( is_admin() )
    $wpdb->send_reads_to_masters();
share|improve this answer
add comment

I would advise that you deploy another copy of your site with different connection details to http://admin.example.com/ This admin area would use the master connection details and do reads and writes to the master and would not suffer from any issues from data not being available. You can force the admin URL to be different by setting flags in the wp-config.

    define('WP_SITEURL', 'http://admin.example.com');
    define('WP_CONTENT_URL', 'http://admin.example.com');

The frontend site http://example.com/ would work as it does currently.

share|improve this answer
    
That would require a lot more work. After a while your admin.example.com url would start getting out in the wild. You would need to add a lot of filters to change the URL and you'd need to make sure your template used canonical urls, had proper noindex meta data / robots.txt rules for admin.example.com, etc. It could be dangerous from an SEO perspective, and disasterous if the url became public and visitors started hitting that url (bypassing your read slaves, etc). –  gabrielk Mar 31 '11 at 18:45
    
admin.example.com would be configured to only show the wp-admin and never actually serve a page, you need to mess with the DocumentRoot but it's possible. If the URLs on the frontend never linked back to admin.example.com you could put admin.example.com behind a http basic auth for added security and prevent crawling. –  Tom Apr 1 '11 at 10:10
    
I wouldn't recommend this. I've been down that road, and found that it caused a lot of headaches. I was a lot happier after I just made some nginx rules to proxy wp-admin requests to another box. –  Mark Jaquith Jun 7 '11 at 3:53
    
@Mark Jaquith what kind of issues were you seeing? –  Tom Jun 7 '11 at 6:58
    
I had plugins not work. Cookies had to be changed. There were tons of little "why isn't that working?" moments. It was just simpler to have the proxy recognize wp-admin requests and send them to the right box. –  Mark Jaquith Jun 8 '11 at 17:39
add comment

Have you looked into Tungsten Replicator based MySQL replication http://code.google.com/p/tungsten-replicator/, it improves on native MySQL replication and improves slave lag etc http://vbtechsupport.com/1318/.

Wonderful cookbook of example setups to get you started at http://code.google.com/p/tungsten-replicator/wiki/TungstenReplicatorCookbook

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.