[PHP, SQL], транзакции и перезагрузка скриптов

Flack_bfsp

Хочу начать транзакцию, потом, допустим, перейти на другой скрипт, или даже заново загрузить этот же, но с другими параметрами, и уже там отменить эту транзакцию, либо принять её.
Понятно, что непостоянные соединения после выхода из PHP-интерпретатора закрываются и коммитятся или роллбэкаются, в зависимости от настроек. Поэтому, чтобы реализовать такую фишку, нужно использовать постоянные соединения. То есть при загрузке скрипта я создаю постоянное соединение с теми же параметарми и PHP использует старое, вместо открытия нового.
Отменяются транзакции на ура! А вот с их принятием проблема. Не принимаются они и всё тут. Пробовал делать лог каждого запроса. Получается что-то в этом роде:
start transaction;
insert ...
commit;
Последний из трёх операторов - уже в другом скрипте, но на том же постоянном соединении. Сервер баз данных никаких ошибок не выдаёт. Пробовал вводить ту же последовательность запросов непосредственно в консоль управления, всё работает на ура.
Думал, что проблема в MySQL. Попробовал на PostgreSQL, потом - на MS SQL. То же самое.
Что я делаю не так?
Как сделать так, чтобы транзакции начинались в одном скрипте, а закоммитить их можно было в другом?

zya369

а ты уверен, что это именно одно и тоже соединение, и что оно не переоткрывается?

Flack_bfsp

Конечно, уверен. По крайней мере, в мануалах что по mysql_pconnect, что по pg_pconnect, что по mssql_pconnect - везде написано, что при создании соединения сначала ищется уже имеющееся с теми же параметрами, и только в случае его отсутствия создаётся новое. А параметры-то одни и те же, они хардкодом прописаны.

Flack_bfsp

Мало того, в комментах к pg_pconnect вот что пишут:
If the page processing aborts and the transaction is not finished yet, the next script using the same persistent connection will be considered as the continuation of the transaction. In particular a lock of a table will persist. The explanation is as follows: After the abort of the script no COMMIT or ROLLBACK was sent to the db server.

Это-то мне и нужно. Вот только работать оно отказывается. Причём когда я пробовал это делать в мускуле, таблицы всё равно лочились (хотя я в начале скрипта делаю коммит или роллбэк и начинаю новую транзакцию и разлочить их помогал только перезапуск серсиса мускула. Чую я, что-то не так.

Flack_bfsp

А вот что пишут в комментах к mysql_pconnect:
You also may consider using pconnect if you have transactions that span multiple pages. For example, in applications that I develop, I start a transaction on the moment I query selecting the data that the user plans on editing. I then commit the transactions after the user hits the submit button and the data is committed.

Блин, что же я могу делать не так?

Flack_bfsp

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

Если честно, я не понимаю, как могут сосуществовать эти два предупрежедния. Они же противоречат друг другу! И тем не менее всё так и есть. То есть постоянное соединение остаётся тем же в новом скрипте, а вот разлочить таблицу через коммит уже не выходит.
Но ведь как-то эта проблема решается?

ava3443

Я вот одного не пойму - у тебя всего один пользователь?

gopnik1994

А я вот другого не пойму. Такая постановка задачи - или ошибка кодирования или ошибка проектирования.

Flack_bfsp

А это-то каким боком связано с поставленной задачей?

Flack_bfsp

Предложи альтернативу.
Чтобы пользователь мог отменять действие после заполнения формы и занесения данных в БД.

ava3443

А это-то каким боком связано с поставленной задачей?
Способ, которым ты пытаешься её решить, не будет работать, если пользователей много. Связано это с поставленной задачей или нет - решать конечно тебе.

Flack_bfsp

Объяснись.
Нет, что этот способ левый, я и так знаю. Не поддерживает ПХП распределение транзакций на несколько скриптов. Но при чём тут количество пользователей?

Andbar

Но при чём тут количество пользователей?
у тебя скрипт, который вызвал другой пользователь, будет использовать то же соединение.

Flack_bfsp

Хм. Постоянные соединения в ПХП даже с теми же параметрами на каждый процесс свои. Если http-сервер создал на новое соединение (от другого пользователя) новый процесс, то и постоянное соединение будет новое.

ava3443


Если http-сервер создал на новое соединение (от другого пользователя) новый процесс, то и постоянное соединение будет новое.

Apache always tries to maintain several spare or idle server processes, which stand ready to serve incoming requests. In this way, clients do not need to wait for a new child processes to be forked before their requests can be served.

Flack_bfsp

Ну я же и сказал - если.
А вообще мне интересно, как решать эту проблему. Пусть не так, не через транзакции, не через постоянные соединения.

ava3443

О том и речь, что на нормально настроенном первом апаче или втором апаче с MPM prefork твоё "если" практически всегда не верно, и уж тем более на втором апаче с MPM worker (я уж не знаю, как сейчас модно PHP к апачу подключать).
Более того, если даже у тебя на нового пользователя родился процесс, то с чего ты взял что следующий HTTP-запрос от этого пользователя будет обрабатываться тем же самым процессом?
Одно обращение к веб-серверу = одна транзакция.

Flack_bfsp

Хорошо, хорошо. Пусть одна. Я же говорю - я не спорю с тем, что плохой способ предложил.
Но как решить задачу? Если клиент заполнил форму, нажал ок, данные внеслись в базу, скрипт перегрузился, а клиенту вдруг захотелось отменить последнее действие?

ava3443

Да тут много чего придумать можно. Например, ввести версионность: добавляется поле "версия", в базе хранятся все версии, а при необходимости отмены последнего изменения создаётся новая версия как копия предпоследней версии.

Flack_bfsp

А как отменять удаление? Не удалять, а просто ставить галочку "удалено"?

ava3443

Да

Flack_bfsp

Хм, надо обдумать. Но ведь тогда база будет очень быстро разрастаться.
Оставить комментарий
Имя или ник:
Комментарий: