PDO (SQLite) General error: 5 database is locked, как бороться ?

alienzzzz

интернет бизнес
PDO (SQLite) General error: 5 database is locked, как бороться ?

есть 2 скрипта:

PHP:
/* 1..... */
try{
    $oDB->service->transaction( );
    $oDB->service->set('update service set srv_descr = :srv_descr where srv_id = :srv_id',array('srv_id' => 169,'srv_descr' => 'test-'.uniqid()));
   /* для отлова ошибки database lock */
    sleep( 10 );
    $aService = $oDB->service->getRow('select * from service where srv_id = :srv_id',array('srv_id' => 169));
    $oDB->service->commit( );
    print_r( $aService );
}catch(Except  $oExcept ){
    echo $oExcept->GetMsg();
}

PHP:
/* 2 ..... */
try{
    $oDB->service->transaction( );
    $oDB->service->set('update service set srv_descr = :srv_descr where srv_id = :srv_id',array('srv_id' => 169,'srv_descr' => 'test-'.uniqid()));
    $aService = $oDB->service->getRow('select * from service where srv_id = :srv_id',array('srv_id' => 169));
    $oDB->service->commit( );
    print_r( $aService );
}catch(Except  $oExcept ){
    echo $oExcept->GetMsg();
}

Они одинаковые, одна разница только в том, что в первом скрипте я вставил функцию sleep .


проблема в том, что, во втором скрипте(когда первый работает), когда я выполняю обновление ($oDB->service->set('update....) у меня возникает ошибка
SQLSTATE[HY000]: General error: 5 database is locked

А хотелось бы сделать, чтоб второй скрипт подождал, пока первый не освободит базу(закончится ф. sleep) и после этого он сделал UPDATE.

Можно убрать транзакции ( $oDB->service->transaction( ); ), тогда все работает и ошибки нет, но получается не чисто (., так как много обращений будет и не обязательно такие простые как в примере.
 

tashkentchi

Новичок
SQLite такого не умеет. Это нужно будет реализовывать средствами ПХП.

Например, в случае "General error: 5", применить sleep(10); и повторить попытку.
 

alienzzzz

интернет бизнес
sleep(10) - многовато будет. причем я так же могу получить general error (
 

tashkentchi

Новичок
sleep(10) взято с потолка (вернее из вашего кода).

Если из первого скрипта уберете sleep(10) (он там зачем?), то напороться на ошибку будет маловероятно.

Если вы во втором скрипте сделаете повторную попытку через (допустим) sleep(1), то ошибка станет еще маловероятнее маловероятна :)

Но если даже исчезающе малая вероятность ошибки недопустима, то можно повторять попытку в цикле (через sleep(1)) до первой удачной.
 

alienzzzz

интернет бизнес
уважаемый. правильно, что слеп 10 с потолка . я не спорю, но я хотел сказать, что даже маловероятная ошибка почему то возникает в самый не удобный момент.
___
Я бы хотел все таки найти какой нибудь вариант с ожиданием., это было бы очень идеально в моем случае.
___
Либо склоняюсь к теме убрать транзакции пока на этом участке кода.

в любом случае даже слер 1 при допустим 1000 записей затормозит систему. так как по сути 1 транзакция(которая будет открыта), затормозит всех на 1 сек. понимаете о чем я )

-~{}~ 14.05.08 17:01:

2 tashkentchi, жаль , что так мало людей отвечающих вы да я (
___

Там много на самом деле у меня таких серрвисов будет - около 30-40 ( поэтому мне и не хотелось бы делать задержку.
___
 

tashkentchi

Новичок
даже если уберете транзакцию, база все равно будет залочена/разлочена 1000 раз в цикле (на каждый апдейт). Думаю, что шанс получить "General error: 5" для второго скрипта от этого не уменьшится. Даже увеличится, так как первый скрипт будет работать дольше.

С другой стороны, если второму скрипту удалось начать транзакцию и выполнить первый апдейт, то "General error: 5" ему уже не грозит, так как база будет залочена уже им.

-~{}~ 14.05.08 19:11:

А возможно ли 30-40 сервисов рассовать по отдельным базам? Тогда лок одной базы не быдет мешать работе с другими.
 

alienzzzz

интернет бизнес
1. у меня 30-40 пишут в одну, а потом на вебе можно смотреть ситуацию (ну там прогресс, сколько осталось до завершения и т.д.)
2. убираю транзакцию и в цикл - работает без лока.
 

tashkentchi

Новичок
2. убираю транзакцию и в цикл - работает без лока.
С sqlite'ом такого не бывает. Если вы сами не стартуете транзакцию, то перед каждым апдейтом он сам ее стартует (с локом базы), а после апдейта завершает. Просто во время "sleep( 10 );" текущих транзакций нет. Поэтому вы локов не замечаете.
 
Сверху