[PHP, SQL], транзакции и перезагрузка скриптов
а ты уверен, что это именно одно и тоже соединение, и что оно не переоткрывается?
Конечно, уверен. По крайней мере, в мануалах что по mysql_pconnect, что по pg_pconnect, что по mssql_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.
Это-то мне и нужно. Вот только работать оно отказывается. Причём когда я пробовал это делать в мускуле, таблицы всё равно лочились (хотя я в начале скрипта делаю коммит или роллбэк и начинаю новую транзакцию и разлочить их помогал только перезапуск серсиса мускула. Чую я, что-то не так.
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.
Блин, что же я могу делать не так?
Есть еще два дополнительных предостережения, которые следует помнить при работе с постоянными соединениями. В случае, если скрипт блокирует таблицу и по каким-либо причинам не может ее освободить, при использовании постоянного соединения все последующие скрипты, которые используют это соединение будут блокированы бесконечно долго и могут потребовать рестарта веб-сервера или сервера баз данных. Второе предостережение заключается в том, что открытые транзакции, если они не были закрыты до завершения работы скрипта, будут продолжены в следующем скрипте, использующем это же постоянное соединение.
Если честно, я не понимаю, как могут сосуществовать эти два предупрежедния. Они же противоречат друг другу! И тем не менее всё так и есть. То есть постоянное соединение остаётся тем же в новом скрипте, а вот разлочить таблицу через коммит уже не выходит.
Но ведь как-то эта проблема решается?
Я вот одного не пойму - у тебя всего один пользователь?
А я вот другого не пойму. Такая постановка задачи - или ошибка кодирования или ошибка проектирования.
А это-то каким боком связано с поставленной задачей?
Чтобы пользователь мог отменять действие после заполнения формы и занесения данных в БД.
А это-то каким боком связано с поставленной задачей?Способ, которым ты пытаешься её решить, не будет работать, если пользователей много. Связано это с поставленной задачей или нет - решать конечно тебе.
Нет, что этот способ левый, я и так знаю. Не поддерживает ПХП распределение транзакций на несколько скриптов. Но при чём тут количество пользователей?
Но при чём тут количество пользователей?у тебя скрипт, который вызвал другой пользователь, будет использовать то же соединение.
Хм. Постоянные соединения в ПХП даже с теми же параметрами на каждый процесс свои. Если http-сервер создал на новое соединение (от другого пользователя) новый процесс, то и постоянное соединение будет новое.
Если 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.
А вообще мне интересно, как решать эту проблему. Пусть не так, не через транзакции, не через постоянные соединения.
Более того, если даже у тебя на нового пользователя родился процесс, то с чего ты взял что следующий HTTP-запрос от этого пользователя будет обрабатываться тем же самым процессом?
Одно обращение к веб-серверу = одна транзакция.
Но как решить задачу? Если клиент заполнил форму, нажал ок, данные внеслись в базу, скрипт перегрузился, а клиенту вдруг захотелось отменить последнее действие?
Да тут много чего придумать можно. Например, ввести версионность: добавляется поле "версия", в базе хранятся все версии, а при необходимости отмены последнего изменения создаётся новая версия как копия предпоследней версии.
А как отменять удаление? Не удалять, а просто ставить галочку "удалено"?
Да
Хм, надо обдумать. Но ведь тогда база будет очень быстро разрастаться.
Оставить комментарий
Flack_bfsp
Хочу начать транзакцию, потом, допустим, перейти на другой скрипт, или даже заново загрузить этот же, но с другими параметрами, и уже там отменить эту транзакцию, либо принять её.Понятно, что непостоянные соединения после выхода из PHP-интерпретатора закрываются и коммитятся или роллбэкаются, в зависимости от настроек. Поэтому, чтобы реализовать такую фишку, нужно использовать постоянные соединения. То есть при загрузке скрипта я создаю постоянное соединение с теми же параметарми и PHP использует старое, вместо открытия нового.
Отменяются транзакции на ура! А вот с их принятием проблема. Не принимаются они и всё тут. Пробовал делать лог каждого запроса. Получается что-то в этом роде:
start transaction;
insert ...
commit;
Последний из трёх операторов - уже в другом скрипте, но на том же постоянном соединении. Сервер баз данных никаких ошибок не выдаёт. Пробовал вводить ту же последовательность запросов непосредственно в консоль управления, всё работает на ура.
Думал, что проблема в MySQL. Попробовал на PostgreSQL, потом - на MS SQL. То же самое.
Что я делаю не так?
Как сделать так, чтобы транзакции начинались в одном скрипте, а закоммитить их можно было в другом?