Я еще кое-что протестировал:
код на гисте.
В test.php нужно присвоить $x значение текущего microtime(true) + несколько секунд и одновременно запустить пару-тройку экземпляров через командную строку. Вот что получается:
Первый экземпляр:
S: -> 1393581800.0007
1: -> 1393581800.0167
2: -> 1393581800.0497
3: -> 1393581800.0507
array(3) {
["id"]=>
string(2) "10"
["name"]=>
string(5) "Sonya"
["disabled"]=>
string(1) "Y"
}
Второй (с ошибками, потому, что был только 1 элемент с disabled = 'N'):
S: -> 1393581800.0007
1: -> 1393581800.0497
2: -> 1393581800.0507
string(146) "You have an error in your SQL syntax; check the manual that corresp
onds to your MySQL server version for the right syntax to use near '' at line 1"
3: -> 1393581800.0517
string(146) "You have an error in your SQL syntax; check the manual that corresp
onds to your MySQL server version for the right syntax to use near '' at line 1"
PHP Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, bool
ean given in W:\OpenServer\domains\mydomain.local\tmp\test.php on line 41
NULL
1. Старт происходит одновременно
S: -> 1393581800.0007
2. Затем первый экземпляр делает выборку
1: -> 1393581800.0167
, а второй получает блокировку.
3. Первый выполняет UPDATE
2: -> 1393581800.0497
и тут же слетает блокировка. Поэтому второй экземпляр может теперь выполнить SELECT
1: -> 1393581800.0497
.
...
В общем, получается, что весь секрет в
FOR UPDATE
. Можно смело убирать транзакцию и уровень ее изоляции. Даже больше - если оставить транзакцию и изоляцию, но убрать
FOR UPDATE
картина становится плачевной.
Все верно? Или я все-таки где-то лапухнулся?