2009-10-16 5 views
2

У меня есть таблица базы данных, где мне нужно вывести строку, проверить ввод пользователя для соответствия, а затем обновить строку, чтобы определить пользователя, который сделал совпадение. Если возникает условие гонки, мне нужно убедиться, что обновление первого пользователя не перезаписано другим пользователем.PHP, mysqli и блокировки таблиц?

Для достижения этой цели я намерен:
1. Чтение строк таблицы
2. Замка снова
3. Прочитайте ряда и сравните исходную строку
4. Если строки совпадают обновления, в противном случае ничего не делать (другой пользователя уже обновил строку)

Основываясь на информации, которую я нашел в Google, я ожидал, что оператор таблицы блокировки будет заблокирован до тех пор, пока не будет получен замок. Я создал небольшой тестовый скрипт в PHP, который задержится на 10 секунд, чтобы позволить мне вручную создать условие гонки.

// attempt to increment the victor number 
$aData["round_id"] = $DATABASE["round_id"]; 

// routine to execute a SELECT on database (ommited for brevity) 
$aRound = $oRound->getInfo($aData); 

echo "Initial Round Data:"; 
print_r($aRound); 

echo "Locking..."; 
echo $oRound->lock(); 

echo "Stalling to allow for conflict..."; 
sleep(10); 
echo "Awake..."; 

$aLockedRound = $oRound->getInfo($aData); 
if($aRound["victor_nation"] == $aLockedRound["victor_nation"]){ 
    $aData["victor_nation"] = $aRound["victor_nation"] + 1; 
    $oRound->update($aData); 
    echo "Incremented Victor Nation"; 
} 

где режим блокировки определяется как

function lock(){ 
     global $oDatabase; 
     $iReturn = 0; 

     // lock the table 
     $iReturn = $oDatabase->m_oConnection->query("LOCK TABLES round WRITE");  
     return $iReturn; 
    } 

Выше $oDatabase->m_oConnection является MySQLi соединение, которое я использую, чтобы выполнить подготовленные заявления по базе данных.

Когда я запускаю свой тестовый сценарий, я запускаю первого пользователя и жду, когда «Столбец разрешит конфликт ...», а затем запустите второй скрипт. Во втором скрипте я ожидал, что он заблокируется при «Блокировке ...», однако второй скрипт также продолжает «Стоять, чтобы разрешить конфликт ...».

Поскольку состояние LOCK не блокирует и не возвращает какой-либо индикатор получения блокировки (возвращаемое значение равно эхо и пустое), мне непонятно, что я фактически приобретаю блокировку. Даже если я, я не уверен, как действовать дальше.

Любые указатели?

+0

Innodb или MyIsam стол? –

+0

Таблица MyIsam –

ответ

3

Устранение неполадок: вы можете проверить успех блокировки таблицы, пытаясь работать с другой таблицей, которая не заблокирована. Если вы получили блокировку, попытка записи в таблицу, которая не была включена в оператор блокировки, должна генерировать ошибку.

Возможно, вы захотите рассмотреть альтернативное решение. Вместо блокировки выполните обновление, которое включает измененные элементы как часть предложения where. Если данные, которые вы изменяете, изменились с момента его чтения, обновление будет «сбой» и будет возвращено нулевые строки. Это устраняет блокировку таблицы и все беспорядочные ужасы, которые могут возникнуть с ней, включая взаимоблокировки.

+0

Спасибо Чарльзу! Избегайте блокировки вообще, используя claus, который отлично работает. –

Смежные вопросы