Bug 259508 - [DB API] Need a way to force SELECTs to the Master Db
Summary: [DB API] Need a way to force SELECTs to the Master Db
Status: VERIFIED FIXED
Alias: None
Product: Community
Classification: Eclipse Foundation
Component: Website (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: phoenix.ui CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-12-22 11:33 EST by Denis Roy CLA
Modified: 2008-12-22 16:49 EST (History)
2 users (show)

See Also:


Attachments
Patch (994 bytes, patch)
2008-12-22 11:37 EST, Denis Roy CLA
no flags Details | Diff
Patch v2 (997 bytes, patch)
2008-12-22 12:15 EST, Denis Roy CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Denis Roy CLA 2008-12-22 11:33:05 EST
The DB API does a great way of sending SELECT queries to the slave db, but there are some cases where we need to force a SELECT to go to the master. For instance, when checking for the presence of a key before adding it.

The current code has this:
if(strtoupper(substr(trim($query), 0, 6)) == 'SELECT') {  // Try to use read-only when possible
	$classfile = $this->get($key . '_db_classfile_ro');
	$class = $this->get($key . '_db_class_ro');
}


I see two possible solutions:

1. We can either use a SQL comment to tell the API to use the master.

SELECT /*HIGH PRIORITY*/ field from table....

2. We simply use SELECT HIGH_PRIORITY

From the MySQL docs:
HIGH_PRIORITY gives the SELECT higher priority than a statement that updates a table. You should use this only for queries that are very fast and must be done at once.


I vote for #2, as the statement will fail if there's a typo in HIGH_PRIORITY (which is good), whereas #1 is error prone and will not fail if there is a typo (the query will work, but go to the slave).
Comment 1 Denis Roy CLA 2008-12-22 11:37:01 EST
Created attachment 121080 [details]
Patch

Here's a patch.  Karl, Nate, does this make sense?
Comment 2 Nathan Gervais CLA 2008-12-22 11:52:00 EST
Looks good +1
Comment 3 Karl Matthias CLA 2008-12-22 12:02:40 EST
The code looks good to me and I like the idea of being able to force it to go to the master.  The only thing is that the MySQL docs on HIGH_PRIORITY make me wonder if it's the best way to do it.  The reason I say that is that it says:

"HIGH_PRIORITY gives the SELECT higher priority than a statement that updates a table. You should use this only for queries that are very fast and must be done at once. A SELECT HIGH_PRIORITY query that is issued while the table is locked for reading runs even if there is an update statement waiting for the table to be free. This affects only storage engines that use only table-level locking (MyISAM, MEMORY, MERGE).

HIGH_PRIORITY cannot be used with SELECT statements that are part of a UNION."

The last statement means that using this method, a certain number of queries (those using a UNION) can't be done against the master and if we're enabling a method for doing that then it should probably support any query.

Also the earlier statement that it will take priority over even an updating query is a little concerning if you're just using HIGH_PRIORITY to force it to the master.  What if you have a fairly lengthy query that needs to go to the master?

My preference would be to make this as general as possible by either:

1. Having a switch like $App->query_master that needs to be flipped one way or ther other.
2. Better yet, having an option to the *_sql() functions that forces the individual query to go to the master.
3. Or maybe better yet, using Denis' other idea about an SQL comment to trigger it

What do you guys think?
Comment 4 Denis Roy CLA 2008-12-22 12:15:40 EST
Created attachment 121083 [details]
Patch v2

My thoughts were that only quick key lookups should be forced to the master.  If the query is lengthy, or complex enough to use UNIONS, then you shouldn't be forcing it the master anyway.  But I'll concede that all queries should work regardless of the server.

In trying to not hack the API, let's go with a comment, but let's make the comment explicitly describe what we want to achieve (ie, not HIGH PRIORITY, but use master):

SELECT /* USE_MASTER */ field from table

Here's another patch.
Comment 5 Karl Matthias CLA 2008-12-22 12:23:31 EST
(In reply to comment #4)
> Created an attachment (id=121083) [details]
> Patch v2
> 
> My thoughts were that only quick key lookups should be forced to the master. 
> If the query is lengthy, or complex enough to use UNIONS, then you shouldn't be
> forcing it the master anyway.  But I'll concede that all queries should work
> regardless of the server.
> 
> In trying to not hack the API, let's go with a comment, but let's make the
> comment explicitly describe what we want to achieve (ie, not HIGH PRIORITY, but
> use master):
> 
> SELECT /* USE_MASTER */ field from table
> 
> Here's another patch.
> 

+1!
Comment 6 Nathan Gervais CLA 2008-12-22 13:19:39 EST
+1 for the new patch.
Comment 7 Denis Roy CLA 2008-12-22 16:21:36 EST
This is committed on Phoenix and will be live shortly.

I have updated the Phoenix docs, and I'll send an email to phoenix-dev

http://wiki.eclipse.org/Using_Phoenix#Querying_the_master_database
Comment 8 Denis Roy CLA 2008-12-22 16:40:30 EST
I added /* USE MASTER */ to my session code, and it works swimmingly if the slave database is stopped.
Comment 9 Karl Matthias CLA 2008-12-22 16:49:24 EST
Cool!