That is not remotely the problem and transactions (just being used to run the same queries) will not help. The "issue" is that
SQL_TQuery is asynchronous (which is exactly the point of it, so the game server doesn't get blocked waiting on results), so you don't have the response from the query until the completion callback is called.
To serialise dependent threaded queries (generally), you need to make the next query from the callback of the preceding one. In your case, that means moving everything after
SQL_TQuery(dbConn, SQL_CreateGang, query, client); into
SQL_CreateGang. Obviously, you need to do all your gathering from the command and store it away (in the query works just fine) - don't forget the serial of the client who called the command and the ReplySource to use. You do not need to serialise the other two queries, as
sQuery_UpdatePlayer doesn't use the result from
sQuery_CreateGang. You haven't provided enough code to show you how to do this with your queries, but it is pretty simple.
There is a
serious problem with this though with your existing queries: race conditions. If
Cmd_CreateGang is called again after the SQL server has calculated the result set but before
SQL_CreateGang is called, there is a chance it could return the same ID twice.
In your case, we can do better than general case by rewriting your queries and using a transaction to clean up the code a bit. Again, can't show you with your queries because you didn't provide them. But the gist of it is to:
- Insert into the gang table with NULL as the ID.
- Insert or update the players table, getting the new gang ID with LAST_INSERT_ID()
- You may need to run a 3rd query to get the gang ID back from the DB, but this will be safely atomic (and you could store it in a session variable to start with to avoid querying the players table).
I've merged your threads together because this makes a lot more sense with the context... You've gone a bit overboard with 4 threads for what is basically the same thing you are working on.
__________________