web-dev-qa-db-fra.com

Table Verrouillage à nouveau, je le fais-je correct?

J'ai eu un problème avec le verrouillage de la table, résolu dans cette question:

Table 'WatchDog' n'a pas été verrouillé avec des tables de verrouillage sur un module personnalisé

Je veux partager mon code actuel, car je ne suis toujours pas sûr que je le fais bien.

J'ai deux tables:

  1. eventi_List, pour stocker les utilisateurs réservant à l'événement sélectionné s'il y a des lieux gratuits de cet événement
  2. eventi_Wait, pour stocker les utilisateurs de réservation s'il n'y a pas d'endroits libres pour un événement sélectionné. Si un utilisateur retire sa réservation, la plus ancienne réservation pour l'événement en cours (si elle existe) de ce tableau passe à Eventi_List Table.

    function eventi_book($nid) {
        $nid = (int) $nid;
        if (_eventi_if_node($nid)) {
            global $user;
            $uid = (int) $user->uid;
            $is_booked = _eventi_is_booked($uid, $nid);
            if (! $is_booked) {
                $is_booked = _eventi_is_booked($uid, $nid, 'eventi_waits');
            }
            if (! $is_booked) {
                db_query('LOCK TABLES content_type_event WRITE, eventi_list WRITE, eventi_waits WRITE, watchdog WRITE');
                $amount =  _eventi_places_amount($nid);
                if ($amount > 0) {
                    _eventi_add($uid, $nid);
                    db_query("UPDATE {content_type_event} SET field_event_places_amount_value = field_event_places_amount_value - 1 WHERE nid=$nid");
                  //  cache_clear_all();
                } else {
                    _eventi_add($uid, $nid, 'eventi_waits');
                }
                db_unlock_tables();
            }
        }
       // _eventi_redirect_to_prev();
    }
    
    
    function _eventi_if_node($nid) {
        $query = db_query("SELECT COUNT(nid) as count FROM {node} WHERE nid=$nid AND type='event'");
        $result = db_fetch_array($query);
        return $result['count'] > 0;
    }
    
    function _eventi_is_booked($uid, $nid, $tbl_name = 'eventi_list') {
        $tbl_name = '{'.$tbl_name.'}';
        $query = db_query("SELECT count(nid) AS count FROM $tbl_name WHERE nid=$nid AND uid=$uid");
        $result = db_fetch_array($query);
        return $result['count'] > 0;
    }
    
    function _eventi_places_amount($nid) {
        $query = db_query("SELECT field_event_places_amount_value AS amount FROM {content_type_event} WHERE nid=$nid");
        $result = db_fetch_array($query);
        return (int) $result['amount'];
    }
    

    fonction _eventi_add ($ uid, $ nid, $ tbl_name = 'eventi_list') {$ tbl_name = '{'. $ Tbl_name. '}'; $ t = heure (); Retour db_query ("Insérez-vous dans $ tbl_name (UID, NID, CREDY_AT_AT) ($ UID, $ NID, $ t)"); }

Je veux m'assurer que je ne finis jamais avec un nombre négatif de lieux libres d'événement sélectionné. Je dois donc avoir un accès atomique au montant des lieux:

$amount =  _eventi_places_amount($nid);

et puis je peux mettre à jour le montant des lieux, quand je suis sûr que $ montant est supérieur à 0:

db_query("UPDATE {content_type_event} SET field_event_places_amount_value = field_event_places_amount_value - 1 WHERE nid=$nid");

Je n'aime pas cette solution, car je dois bloquer de nombreuses tables. Y a-t-il une meilleure façon de le faire à Drupal?

3
user1077

Myisam effectue une serrure de niveau de table pour faire n'importe quel SQL sur une table myisam.

Si vous convertissez tout en InnoDB, le verrouillage au niveau des lignes est implicitement fait pour vous. Contrôle de la concurrence multiversion (MVCC) permet à chaque utilisateur de verrouiller uniquement la (s) rangée (s) nécessaire.

De plus, vous voudrez peut-être effectuer toutes les écrivies atomiques dans un commencement ... COMMIS une transaction pour regrouper plusieurs mises à jour de table comme une seule unité. C'est ce que InnoDB fera pour vous. InnoDB est plainte acide . L'A signifie atomicité , la capacité d'une transaction à être atomique.

2
RolandoMySQLDBA