I am using a script that sync data betweens two databases (locally to an hosted domain). I made the sync occurs when someone log out from the CMS. Unfortunatly, I have seen cases when two logout happen close enough that the sync script is executed twice. It's not the part of the system I'm trying to change but I was expecting an easy way to makes that script (sync.php) not executing if it's already running.
I have came up with that test scripts:
$db = new DB_Mysql();
if ( $db->transactionBegun() == "0" )
{
$_Continue = true;
$_Continue = $_Continue && $db->squery( "START TRANSACTION" );
$_Continue = $_Continue && $db->squery( "SET @TransactionBegun = true" );
sleep( 10 );
$_Continue = $_Continue && $db->squery( "INSERT INTO tbConfiguration VALUES( NOW(), NOW() )" );
$_Continue = $_Continue && $db->squery( "SET @TransactionBegun = false" );
if ( $_Continue )
{
$db->query( "COMMIT" );
} else {
$db->query( "ROLLBACK" );
}
}
The transactionBegun method consist of:
function transactionBegun()
{
$_ResultSet = $this->query("SELECT @TransactionBegun AS TransactionBegun")->fetch_all(true);
return $_ResultSet[ 'TransactionBegun' ];
}
For some strange alien reason, I can run the script twice (in the same time) and both entry will be made.
Any ideas??
Edit:
I forgot to mention that I am using a开发者_如何转开发 mysql_pconnect()
and that the server is hosted on a Windows machine. The whole system is a cash register machine using a tablet PC. The only client accessing the server is "localhost".
The variables are per-connection, not per-user. With two independent scripts, you'll have two seperate independent connections, each with its own variable space.
If you need to truly handle locking out parallel usage, you'll need to use a server-side lock acquired via GET_LOCK()
or use a transaction mode that does exclusive locking on the resource.
Use file-based locks.
When the script begins, have it check for a file like "sync_db.lock". If it exists, another instance of the script is running. At this point, you can choose to sleep for a few seconds and begin again, or simply give up.
If it doesn't exist, create the file and complete the DB transaction. When the transaction is completed, simply delete the file.
To avoid issues with failed threads, write the current timestamp to the file. When the script checks for the file, read its contents and see if a given time period has passed. Don't forget to overwrite the timestamp if your script continues with the transaction.
A little psudo code: check to see if a file (/var/tmp/.trans.lck) is there if it is exit create lock file if not when finish remove lock file
精彩评论