Транзакции SQL-сервера в PHP - PullRequest
1 голос
/ 05 января 2010

Я пытаюсь полностью понять идею транзакций. Поэтому следующий вопрос ... (конечно, новичок, так что не смейтесь: D)

Я установил (упрощенную) транзакцию в PHP (используя драйвер PHP PHP от Microsoft). Я хочу получить строки, которые собираюсь удалить, для дополнительной обработки позже:

sqlsrv_begin_transaction($conn);
$sql = "SELECT * FROM test WITH (XLOCK) WHERE a<10";
$statement = sqlsrv_query($conn,$sql);
$sql = "DELETE FROM test WHERE a<10";
sqlsrv_query($conn,$sql);

$result = get_result_array($statement);
sqlsrv_commit($conn);
$result2 = get_result_array($statement);

1) Я получаю ожидаемый результат в $ result, но пустой массив в $ result2. Почему?

Я бы ожидал только результат в $ result2, потому что тогда транзакция фактически была выполнена. Я предполагаю, что результат в $ result является своего рода «временным» результатом в памяти, а не результатом реальной базы данных.

2) Возможно, что между моментом запуска транзакции и фактической фиксацией другой запрос из другого соединения изменил соответствующие строки (a <10)? Это означает, что ожидаемые результаты в соответствии с $ result будут отличаться от реальных изменений в базе данных. </p>

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

После ввода этого сообщения я ожидаю ответа b ....?

Ответы [ 2 ]

1 голос
/ 05 января 2010

Я не знаком с драйвером sqlsrv, но если он работает так же, как и большинство других драйверов БД PHP, результатом вызова sqlsrv_query является не набор результатов в какой-либо форме массива, а ресурс PHP (см. http://www.php.net/manual/en/language.types.resource.php). Вызов get_result_array по-прежнему извлекает данные из этого ресурса, в данном случае из базы данных, и делает это немедленно. COMMIT влияет только на записи в базу данных, а не на чтение, поэтому вы сразу видите свой результат в result1. После фиксации вашего транзакции (т.е. УДАЛИТЬ), следующий вызов правильно возвращает пустой набор результатов.

0 голосов
/ 06 января 2010

Я проверил это с помощью некоторых инструментов MySQL (с которыми я более знаком): 1. Когда я начинаю транзакцию и делаю «выбор» одной конкретной записи, я сразу получаю результат. Затем из другого соединения я удаляю ту же запись (с автокоммитом), она пропадает для этого соединения, но для первого соединения запись все еще там (я снова сделал «select», не совершая транзакцию). Только после совершения транзакции первого соединения и повторного выбора, запись исчезает. 2. Когда я делаю то же самое, но получаю эксклюзивную блокировку для первого запроса «выбор», тогда запрос на удаление второго соединения ожидает, пока транзакция первого соединения не будет зафиксирована.

Вывод: В ситуации (1) для второго запроса на выборку первого соединения база данных возвращает результат, какой он был на момент начала транзакции ... таким образом, БЕЗ учета других (запись) Запросы выполняются ПОСЛЕ начала транзакции. Ситуация (2) - это как раз ответ 2b из моего первоначального вопроса. :)

...