Я пытаюсь реализовать двухэтапную фиксацию с использованием PHP и MySQL, и у меня не получается.

Главный блок, который я обнаружил, заключается в том, что я не могу сохранить ресурс подключения MySQL в том месте, где я могу снова найти его для второй фазы. Можно ли сериализовать дескриптор базы данных?

Вот случай, для которого я пытаюсь написать код:

  1. Пользователь отправляет данные
  2. Сервер запускает транзакцию MySQL и выполняет некоторые запросы на основе полученных данных.
  3. Сервер отправляет файл обратно пользователю
  4. Когда пользователь успешно получил файл, сервер совершает транзакцию. Иначе откатывает обратно.

Похоже, для этого требуется два цикла HTTP-запроса / ответа, поэтому мне нужно иметь возможность повторно подключиться к тому же дескриптору базы данных во втором запросе, чтобы зафиксировать транзакцию. Я терпел неудачу в этой части.

Приветствуются любые советы, даже если «это невозможно в PHP».

2
TomL 12 Окт 2009 в 13:09
1
Звучит как сложный вопрос о повторном подключении к дескриптору базы данных из другого запроса. Кроме того, если вы используете PDO :: beginTransaction, PDO автоматически откатит транзакцию после завершения скрипта. Вы можете объяснить, зачем вам это нужно?
 – 
rojoca
12 Окт 2009 в 22:38

3 ответа

Лучший ответ

Взгляните на LIXA Transaction Manager (http://lixa.sourceforge.net/), он интегрирует PHP и MySQL, начиная с версии 0.9.0.

Он также обеспечивает распределенную обработку транзакций и двухфазную фиксацию.

Отношении

Гл. Ф.

2
Ch.F. 22 Апр 2012 в 14:15
Интересно. Я обязательно это проверю.
 – 
TomL
25 Апр 2012 в 14:55

Поскольку php основан на запросах / ответах, реализация постоянного соединения с БД невозможна, AFAIK.

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

  1. Пользователь отправляет данные
  2. Сервер запускает транзакцию MySQL и выполняет некоторые запросы на основе полученных данных, присваивая этой транзакции «уникальный» билет.
  3. Сервер отправляет файл и билет обратно пользователю
  4. Когда пользователь успешно получил файл и отправил другой запрос, содержащий этот билет, сервер фиксирует свою транзакцию. Иначе откатывает обратно.
  5. ссылаясь на комментарий Касси: по прошествии определенного периода времени все невыполненные TA должны быть откатаны, чтобы предотвратить `` затопление '' вашей базы данных старыми транзакциями

HTH

2
KB22 12 Окт 2009 в 14:09
1
Хорошая идея! Однако я бы добавил пятый пункт: откат также должен произойти через определенное время без загрузки пользователем. В противном случае база данных будет заполнена отмененными операциями.
 – 
Dan Soap
12 Окт 2009 в 14:04
1
Это то, что я имел в виду, поскольку билет был ссылкой на идентификатор в общей памяти, где я сохранил дескриптор базы данных с ожидающей транзакцией. Единственная проблема в том, что вы не можете сериализовать дескрипторы базы данных в PHP, поэтому я остаюсь с проблемой невозможности гарантировать, что второй запрос получит тот же дескриптор базы данных, что и в первый раз. Насколько я понимаю, транзакции должны быть зафиксированы на том же подключении к базе данных, с которого они были начаты. Есть ли способ пометить транзакции, чтобы к ним можно было вернуться позже?
 – 
TomL
13 Окт 2009 в 08:12
Я не думаю, что это вообще возможно. Я бы придерживался упомянутого обходного пути и попытался бы «эмулировать» механизм транзакции с помощью собственной таблицы транзакций. Что-то вроде STRING (вот и собственно строки SQL) BOOLEAN (для фиксации). Первый запрос записывает запрос во временную таблицу, помеченную как toCommit = false; второй запрос выполняет фактический запрос. Я согласен с вопросом Роджока: почему вы не хотите делать это прямо таким образом?
 – 
KB22
13 Окт 2009 в 10:54

Чтобы ответить на вопросы KB22 и rojoca, причина, по которой мне нужно сделать это таким образом, заключается в том, что «файл», о котором я говорю, на самом деле является базой данных sqlite, которая в конечном итоге становится хранилищем данных на мобильном устройстве.

Первый запрос отправляет обновленную базу данных sqlite на сервер, который пытается объединить данные из таблиц sqlite; Проблемы возникают, когда мобильное устройство не получает новую базу данных sqlite (ту, которая отражает изменения мобильного устройства и любые другие новые данные из веб-приложения), потому что затем оно пытается отправить ту же (старую) базу данных sqlite в web во второй раз, что приводит к дублированию записей в веб-таблицах для всего, что было создано на мобильном устройстве.

Таким образом, Интернет должен быть уверен, что на устройстве есть новая база данных, прежде чем фиксировать изменения слияния. Учитывая капризы сетей, это кажется возможным только в том случае, если устройство может отправлять явный ACK после получения новой базы данных sqlite. И это возможно только в том случае, если мы сделаем два запроса (1. База данных sqlite для слияния; 2. ACK получения новой базы данных sqlite на устройстве).

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

[Я также не думаю, что могу использовать таблицу транзакций, потому что мне нужно возвращать данные на устройство на основе «реальных» таблиц веб-базы данных. Я думаю, что столкнулся бы с проблемами с полями auto_increment, если бы не использовал настоящие таблицы]

Спасибо за все ваши комментарии.

0
TomL 13 Окт 2009 в 16:50