Lock visitor until mysql query is complete
I have a bunch of pages on a site for which the actions that can be taken on one page are contingent upon the info in the database for the site visitor. So, let's say Visitor A comes to page B and updates a database to show that they have joined a certain group. Then the visitor goes to page C, the group page. If the user is a group member, they are shown member content. If they are not, they are shown non-member content. Here comes the issue (btw, pages are in php):
In an ideal world, the query run on page B would be completed instantaneously before the user goes to page C so the database is always filled with the most recent info on membership states. However, it can happen that the server is under a lot of load and the query does not complete by the time the user goes to page C. So, even t开发者_如何学Pythonhough the user is a member of the group, that is not reflected on page C since the query has yet to complete.
Is there a way to make it so that if a user run a query on a page, until that query completes any other page they try to visit will just "hang" and load after there query is complete, or until a given amount of time has passed? I can make this system manually, but if mysql and php already have something built in, that would be preferable.
In case it matters, I am using a LAMP server.
Unless you do anything fancy like replicated database servers or message que systems, this is in fact how a single MySQL server and PHP already work. Issue the UPDATE or INSERT on page B, and the query wont return until it is committed. So don't return any HTML from page B until you have done the query - which you won't want to anyway, as you will want to make sure there was no error first. Then page C will be fine.
Can't the visitor simply be not shown the link to page C until the confirmation happens in page B? So they join the group in page B which happens by submitting a form post to a separate intermediate form processor page F, and then once that's done (ie mysql insert completed successfully), it loads page B again with the proper new information and directions to page C.
If page C links have to appear always, or the user can have it bookmarked, then perhaps page C can also display the date of the record, offering the user a "Refresh" button in case his record doesn't match what he just did as a way of telling him to wait a bit and try again.
In any case, in mysql you're talking about the concept or row locking but you're trying to apply that to a multi-entry site. I don't know of any such built-in mechanism in PHP but you could fake it with semaphores per user if you'd like:
- user initiates action
- PHP sets a lock for that user either by creating a unique file, or setting a unique key in a memory store like memcache, or in the user session
- that lock indicates that the action has not finished yet
- PHP performs action (mysql insert, whatever)
- once action is complete and validated, remove lock
Then you can use the existence of the lock to determine wether page C should load and display something descriptive to the user, such as my above suggestion of a Refresh button.
Assuming you have a string that uniquely identifies the current user, say 'identifyuser'
, pick a reasonable timeout and do a SELECT GET_LOCK('identifyuser',timeout)
before any other database activity for a given request and SELECT RELEASE_LOCK('identifyuser')
after all database activity for the request.
精彩评论