joon
joon

Reputation: 864

How do I make sure the rapidly changing data from my MySQL DB is accurately represented in php scripts?

I have a database with lots of game objects, which is being queried by the following 3 PHP scripts.

  1. List objects: gets a JSON object with all the items I need
  2. Add object: adds an object to the database
  3. Reset: wipes all objects from the table

All three of them work, somewhat. Although, there is a timing mismatch. When the game calls the reset function, it restarts. When the game restarts, it automatically loads all the objects. Unfortunately,and here's the problem, if the game has just been reset, objects will still be pulled by script 1.

I know of transactions, but I have never used them and I have no idea how I would implement those here, since my transaction is involving things from different scripts that are run at different times.

For bonus credit: will this setup (AS3 > php > MySQL) get me in trouble with a heavy load? The game might get picked up by 10, 100, 1000 people, is there anything I can read about that subject?

Edit: new idea/question

Currently, the wiping works as such: The objects table has a field 'deleted' which is set to '1' when the reset method is called. It might be smarter to copy the existing data into an archive table and then truncate the live table...

Edit: Here's the (relevant) PHP code I'm using

Add Object:

if ($db_found) {

$x = $_GET['x'];
$y = $_GET['y'];
$type = $_GET['type'];
$name = $_GET['name'];
$text = $_GET['text'];

$SQL = "INSERT INTO bodies  (x,y,type,name,text)
VALUES ('".$x."','".$y."','".$type."','".$name."','".$text."' )";

if (!mysql_query($SQL))
  {
  die('Error: ' . mysql_error());
  }

};

mysql_close($db_handle);

List/Get Objects:

if ($db_found) {

$SQL = "SELECT * FROM bodies WHERE deleted = 0";
$res = mysql_query($SQL);

    $rows = array();
    while($r = mysql_fetch_assoc($res)) {
        print $r['x'] . ','
        . $r['y']
        . ','
        . $r['type']
        . ','
        . $r['name']
        . ','
        . $r['text']
        .  ';';
    }

};
mysql_close($db_handle);

Reset: (EDIT 2)

mysql_query("LOCK TABLES bodies WRITE;");

$SQL = " DELETE FROM bodies";

if (!mysql_query($SQL))
  {
  die('Error: ' . mysql_error());
  }
};

mysql_query("UNLOCK TABLES;");

Upvotes: 3

Views: 189

Answers (1)

Basti
Basti

Reputation: 4042

How to do Transactions in MySQL.

In your case you might be interessted in the atomicity and isolation of transactions, meaning that when restarting a game, you want to ensure that before the reset has not fully finished, nobody can fetch any of your intermediate data. Doing the reset inside a transaction will ensure this property*. (* for TRUNCATE see below)

You will need InnoDB as your Engine for all tables that are involved in your transactions. MyISAM does not support transactions.

Changing large amounts of data inside a transaction can potentially cause high query delays, as transaction use special undo/redo-logs to be able to undo all the things you did in your transaction, if you decide to ROLLBACK.

I wouldn't wipe the tables when starting a new game. Instead give your data a game_id and use a new game_id when starting a new game. Space shouldn't really be an issue nowadays. This has the advantage that you will need little to none table locking when reseting the game.

If you must, be sure to use TRUNCATE when clearing out the tables. As far as I know TRUNCATE in MySQL cannot be rolled back, so doing it inside a transaction won't do anything useful.

I think PHP/MySQL will perform fine if used correctly, even for larger visitor counts. You can use profiling tools like xdebug or the MySQL slow query log to trace and remove performance bottle necks.

Upvotes: 1

Related Questions