За последние 24 часа нас посетил 19561 программист и 1604 робота. Сейчас ищут 944 программиста ...

Оптимизация обращений к базе

Тема в разделе "PHP и базы данных", создана пользователем freeneutron, 18 июн 2011.

  1. freeneutron

    freeneutron Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    226
    Симпатии:
    3
    Доброго времени дня всем заглянувшим.
    Хочу, что бы вы вникли в следующие примеры, которые по сути являются оболочкой для метода PDO::exec() и, как предполагается, должны исключить коллизии между параллельными процессами, использующими данный метод:
    PHP:
    1. <?php
    2. $dbh = new PDO('sqlite:'.$db_config['dbname']);  //insert обращение
    3. $dbh->beginTransaction();                        //Начало транзакции
    4. $contition1 = $dbh->query("select count(*) from items where item_name=".item_name[$id])->fetchAll();
    5. if($contition1[0][0] == 0){
    6.     $dbh->exec("
    7.        insert into item
    8.            (item_count,item_name)
    9.        values
    10.            (".item_count[$id].",".item_name[$id].")
    11.    ");
    12.     $dbh->commit();                              //Завершение транзакции
    13. }esle
    14.     $dbh->rollBack();
    15.  
    16.  
    PHP:
    1. <?php
    2. $dbh = new PDO('sqlite:'.$db_config['dbname']);  //update обращение
    3. $dbh->beginTransaction();                        //Начало транзакции
    4. $contition1 = $dbh->query("select count(*) from items where item_name=".item_name[$id])->fetchAll();
    5. $contition2 = $dbh->query("select count(*) from items where item_id=".$id)->fetchAll();
    6. if($contition1[0][0] == 0 && $contition2[0][0] != 0){
    7.     $dbh->exec("update item set item_count=".item_count[$id]." where item_id=".$id);
    8.     $dbh->commit();                              //Завершение транзакции
    9. }esle
    10.     $dbh->rollBack();
    11.  
    12.  
    Их суть заключается в том, что перед внесением изменений в таблицу item скрипт проверяет отсутствие значения $item_name[$id] в поле item_name, а во втором примере - еще и наличие значения $id в поле item_id. Это позволяет быть уверенным в том, что другие процессы не успели испортить рассматриваемую таблицу до открытия транзакции. А сама транзакция и вовсе исклюцает коллизии. Так вот, глядя на эти примеры, у меня возникает вопрос: Как бы их оптимизировать по времени выполнения?
    Хотелось бы обсудить разные способы.
     
  2. freeneutron

    freeneutron Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    226
    Симпатии:
    3
    Эх. Зря потратил время на составление вопроса. Нарыл ответ уже самостоятельно:
    PHP:
    1. <?php
    2.  $dbh = new PDO('sqlite:'.$db_config['dbname']);  //update обращение
    3.  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
    4.  $dbh->beginTransaction();                        //Начало транзакции
    5.  $res = $dbh->exec("update item set item_count=".item_count[$id]." where item_id=".$id);
    6.  if($res === false)
    7.      $error[] = $dbh->errorInfo();
    8.  
    9.  if(isset($error))
    10.      $dbh->rollBack();
    11.  esle
    12.      $dbh->commit();                              //Завершение транзакции
    13.  
    Думаю, это наиболее оптимальный способ исключения коллизий. Плюс, получаем код ошибки ($error). Если в транзакции буде не один запрос, то можно будет потом разобрать, в каком запросе и что пошло не так.