it-swarm-ko.tech

다시 테이블 잠금, 올바르게하고 있습니까?

이 질문에서 해결 된 테이블 잠금에 문제가 있습니다.

'watchdog'테이블이 사용자 정의 모듈의 LOCK TABLES로 잠기지 않았습니다.

현재 코드를 공유하고 싶습니다. 올바른 코드인지 아직 확실하지 않기 때문입니다.

두 개의 테이블이 있습니다.

  1. eventi_list,이 이벤트의 여유 공간이있는 경우 선택한 이벤트에 대한 사용자 예약 저장
  2. eventi_wait, 선택한 이벤트에 대한 여유 공간이없는 경우 사용자 예약을 저장합니다. 사용자가 자신의 예약을 철회하면이 테이블에서 현재 이벤트 (존재하는 경우)에 대한 가장 오래된 예약이 eventi_list 테이블로 이동합니다.

    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'];
    }
    

    function _eventi_add ($ uid, $ nid, $ tbl_name = 'eventi_list') {$ tbl_name = '{'. $ tbl_name. '}'; $ t = 시간 (); return db_query ( "INSERT INTO $ tbl_name (uid, nid, created_at) VALUES ($ uid, $ nid, $ t)"); }

선택한 이벤트의 무료 장소가 음수로 끝나지 않도록하고 싶습니다. 그래서 나는 장소에 대한 원자 적 접근을해야한다.

$amount =  _eventi_places_amount($nid);

$ amount가 0보다 큰 경우 장소 금액을 업데이트 할 수 있습니다.

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

많은 테이블을 잠 가야하기 때문에이 솔루션이 마음에 들지 않습니다. Drupal에서이 작업을 수행하는 더 좋은 방법이 있습니까?

3
user1077

MyISAM은 MyISAM 테이블에서 SQL을 수행하기 위해 테이블 ​​수준 잠금을 수행합니다.

모든 것을 InnoDB로 변환하면 행 수준 잠금이 암시 적으로 수행됩니다. MVCC (Multiversioning Concurrency Control)를 사용하면 각 사용자가 필요한 행만 잠글 수 있습니다.

또한 BEGIN ... COMMIT 트랜잭션에서 모든 원자 쓰기를 수행하여 여러 테이블 업데이트를 하나의 단위로 그룹화 할 수 있습니다. 그것이 InnoDB가 당신을 위해 할 일입니다. InnoDB는 ACID 불만 입니다. A는 ATOMICITY를 나타냄 , 원 자성이 될 수있는 트랜잭션의 능력.

2
RolandoMySQLDBA