PHP / MySQL - cómo prevenir dos solicitudes * Actualización

Tengo una pregunta ... ejemplo: un usuario comprará algo por su USD

Compruebe su saldo de USDDeducir el USD de su cuenta.Hacer un pedido -> ordenar colael usuario obtiene su artículo y el otro obtiene su USD

Digamos que los usuarios hacen 5 solicitudes en el mismo segundo (muy rápido). Por lo tanto, es posible (y sucede) que se estén ejecutando 5 solicitudes. Solo tiene dinero para comprar solo de 1 pedido. Ahora las solicitudes son tan rápidas, que el script verifica su saldo, pero no es tan rápido, que deduce el dinero de su cuenta. Así que las solicitudes pasarán dos veces! ¿Cómo resolverlo?

Uso LOCK en mysql antes de comenzar el proceso:

IS_FREE_LOCK - verifique si hay un bloqueo para este usuario si no es -> 2.GET_LOCK - establece el bloqueohacer el pedido / transacciónRELEASE_LOCK - libera el bloqueo

Pero esto realmente no funciona. ¿Hay otra manera?

function lock($id) {
  mysql_query("SELECT GET_LOCK('$id', 60) AS 'GetLock'");
}

function is_free($id) {
  $query = mysql_query("SELECT IS_FREE_LOCK('$id') AS 'free'");
  $row = mysql_fetch_assoc($query);
  if($row['free']) {
    return true;
  } else {
    return false;
  }
}

function release_lock($id) {
  mysql_query("SELECT RELEASE_LOCK('$id')");
}

function account_balance($id) {
  $stmt = $db->prepare("SELECT USD FROM bitcoin_user_n WHERE id = ?");
  $stmt->execute(array($id));
  $row = $stmt->fetch(PDO::FETCH_ASSOC);

  return $row['USD'];
}

if(is_free(get_user_id())) {
  lock(get_user_id());
  if(account_balance(get_user_id()) < str2num($_POST['amount'])) {
    echo "error, not enough money";
  } else {
    $stmt = $db->prepare("UPDATE user SET USD = USD - ? WHERE id = ?");
    $stmt->execute(array(str2num($_POST['amount']), get_user_id()));
    $stmt = $db->prepare("INSERT INTO offer (user_id, type, price, amount) VALUES (?, ?, ?, ?)");
    $stmt->execute(array(get_user_id(), 2, str2num($_POST['amount']), 0));
}

Actualizar Probó la función de transacción con SELECT ... PARA ACTUALIZAR

$db->beginTransaction();
$stmt = $db->prepare("SELECT value, id2 FROM test WHERE id = ? FOR UPDATE");
$stmt->execute(array(1));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($row['value'] > 1) {
  sleep(5);
  $stmt = $db->prepare('UPDATE test SET value = value - 5 WHERE id = 1');
  $stmt->execute();
  $stmt = $db->prepare('UPDATE test SET value = value + 5 WHERE id = 2');
  $stmt->execute();
  echo "did have enough money";
} else {
  echo "no money";
}
$db->commit();

Respuestas a la pregunta(5)

Su respuesta a la pregunta