For the oci8 extension it is not true that " [...] when using transactions, a transaction block will also carry over to the next script which uses that connection if script execution ends before the transaction block does.". The oci8 extension does a rollback at the end scripts using persistent connections, thus ending the transaction. The rollback also releases locks. However any ALTER SESSION command (e.g. changing the date format) on a persistent connection will be retained over to the next script.
Постоянни връзки с бази от данни
Постоянните връзки са връзки, които не прекъсват при приключване на работата на скрипта. Когато бъде заявена постоянна връзка, PHP проверява дали вече съществува идентична постоянна връзка (която е заявена и оставена непрекъсната от по-рано) и ако такава съществува, тя бива използвана. Ако такава връзка не съществува, тя ще бъде създадена. "Идентична" връзка е такава, която е отворена от същия хост, със същото потребителско име и същата парола (където е приложима такава).
Хората, които не са напълно запознати с естеството на работа на уеб-сървърите и начина, по който те разпределят натоварването, могат да объркат постоянните връзки с това което те не са. По-специално те не ви дават възможност да правите 'потребителски сесии' в същата връзка, не ви дават възможност да увеличите ефективността на транзакциите, не ви дават възможност да правите и един куп други неща. Всъщност, за да бъдем пределно ясни, постоянните връзки не дават никаква допълнителна функционалност, която техните непостоянни еквиваленти да не могат да ви предоставят.
Защо?
Проблемът е обвързан с естеството на работа на уеб-сървърите. Има три начина уеб-сървърът да накара PHP да генерира уеб-страници.
Първият метод е PHP да се използва като "опаковка" от тип CGI. По този начин при всяка заявка към (PHP страница на) уеб сървъра ви се създава и унищожава една инстанция на интерпретатора на PHP. Точно поради унищожаването на тази инстанция след всяка заявка, всеки ресурс, който тя използва (например връзка към база от данни) също бива унищожен. В този случай не печелите нищо от употребата на постоянни връзки - те не остават отворени.
Вторият и най-популярен метод е стартирането на PHP като модул на уеб-сървър в многопроцесен режим, което понастоящем включва единствено Apache. Обикновено уеб сървърът в многопроцесен режим има един процес (родителски), който координира група процеси (наследници), които всъщност извършват генерирането на уеб-страници. Когато постъпи заявка от потребител, тя бива прехващана от някой от процесите наследници, който в момента не обслужва друг потребител. Това означава, че когато същият потребител направи друга заявка впоследствие, той може да бъде обслужен от различен процес наследник от този, който го е обслужвал преди това. При отварянето на постоянна връзка, всяка заявка към база от данни направена от този потребител, използва един и същи ресурс за връзка с нея.
Последният метод е PHP да се използва като приставка към многонишков уеб-сървър. Понастоящем PHP4 има поддръжка за ISAPI, WSAPI, и NSAPI (за Windows), всеки от които позволява PHP да се използва като приставка за многонишков сървър, като например Netscape FastTrack (iPlanet), Microsoft's Internet Information Server (IIS) и O'Reilly's WebSite Pro. Поведението е съвсем същото като при многопроцесния модел описан по-горе.
След като постоянните връзки нямат никаква допълнителна функционалност, защо трябва да ги използваме?
Отговорът е изключително прост - ефективност. Постоянните връзки са подходящи в случаите, когато усилието за осъществяване на връзка с базата от данни е голямо. А дали това усилие е голямо или не се определя от много фактори. Например, каква е базата от данни, дали работи на същата машина на която работи и вашия уеб-сървър, колко натоварена е тя и т.н. Равносметката е, че при голямо натоварване и голям трафик към базата от данни, постоянните връзки повишават ефективността значително. Причината е, че на процеса наследник му се налага да осъществи връзка към базата от данни само веднъж и той я използва през цялото врема на работа, вместо да осъществява връзка всеки път когато се обработва страница. Това означава също така, че на всеки процес наследник, който е отворил постоянна връзка, се полага по една такава. Например, ако имате 20 различни наследствени процеса, всеки един от които е образувал постоянна връзка към база от данни, ще имате 20 различни дълготрайни връзки, по една от всеки процес наследник.
Забележете, че това може да има някои недостатъци, ако използвате база от данни с ограничен брой налични отворени връзки и този брой е надхвърлен от броя на процесите, които се опитват да осъществят връзка. Ако базата от данни има ограничение от 16 връзки, а точно в този момент 17 процеса заявяват връзка с нея, един от тях няма да успее. Ако има програмни грешки във вашия скрипт, които не позволяват на връзките да бъдат спрени (например при безкрайни цикли), базата от данни със само 16 отворени връзки може да бъде блокирана. Потърсете информация за обработка на изоставени или чакащи връзки в документацията на базата от данни, която използвате.
Има няколко неща, които трябва да имате наум, когато използвате постоянни връзки. На първо място, когато използвате заключване на таблица заедно с постоянна връзка, ако скриптът по някаква причина не може да отключи таблицата, то тогава последващите скриптове, използващи същата постоянна връзка, ще бъдат блокирани. Ще ви се наложи да рестартирате уеб-сървъра или сървъра на базата от данни. Също така, когато използвате транзакции, имайте предвид, че транзакционният блок ще се пренесе върху следващия изпълнен скрипт, ако изпълнението на скрипта приключи преди да е приключило изпълнението на транзакцията. В който и да е от тези случаи, използвайте register_shutdown_function(), за да стартирате почистваща функция, която да отключи заключените ви таблици или да превърти транзакциите ви. Най-добре не използвайте постоянни връзки, когато използвате заключване на таблици или транзакции (можете да ги използвате при всички останали случаи).
Важна информация. Постоянните връзки са проектирани да имат съвсем същата функционалност, каквато имат и обикновените такива. Това означава, че би трябвало при всички случаи да можете да замените постоянните връзки с непостоянни и това да не промени по никакъв начин начина на работа на скриптовете ви. Това може да доведе до промяна на ефективността (и вероятно ще доведе), но не и до промяна на крайния резултат.
Вж. още fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(), mysql_pconnect(), ociplogon(), odbc_pconnect(), ora_plogon(), pfsockopen(), pg_pconnect() и sybase_pconnect().
Постоянни връзки с бази от данни
26-Jun-2007 07:46
20-Feb-2007 05:13
To those using MySQL and finding a lot of leftover sleeping processes, take a look at MySQL's wait_timeout directive. By default it is set to 8 hours, but almost any decent production server will have been lowered to the 60 second range. Even on my testing server, I was having problems with too many connections from leftover persistent connections.
26-Nov-2006 12:02
in response to web at nick, have you tried FLUSH PRIVILEGES. this should reload those privileges.
06-Mar-2006 12:43
If you have multiple databases on the same server AND you are using persistent connections, you MUST prefix all the table names with the specific database name.
Changing the database using the xxx_select_db functions alters the database for the connection for all users who are sharing that connection (assuming PHP is running shared and not CGI/CLI).
If you have 2 databases (live and archive) and your script is talking to both, you cannot use 2 persistent connections and change the database for each one.
Internally, persistent connections are used even if you do not specify that you want to use persistent connections. This is why new_link was added to mysql_connect/mssql_connect (PHPV4.2.0+).
12-Jan-2006 12:54
You can in fact provide a port for the connection, take a look at http://de2.php.net/manual/en/function.mysql-pconnect.php#AEN101879
Just use "hostname:port" for the server address.
16-Jan-2004 12:21
this one bit quite a bit of chunk out of my you-know-what. seems like if you're running multiple database servers on the same host (for eg. MySQL on a number of ports) you can't use pconnect since the port number isn't part of the key for database connections. especially if you have the same username and password to connect to all the database servers running on different ports. but then it might be php-MySQL specific. you might get a connection for an entirely different port than the one you asked for.
02-Dec-2003 11:41
This may only pertain to Apache/MySQL:
After several hours of wrestling with MySQL "Access denied" messages, I determined that persistent database connections don't necessarily reflect subsequent privilege changes.
I loaded a PHP script attempting a LOAD DATA statement, and got an "Access denied" error. I granted FILE privileges to the MySQL user, and was able to run LOAD DATA statements from the terminal, but still got "Access denied" from my PHP pages. When I switched from mysql_pconnect() to mysql_connect(), the problem went away; eventually I restarted apache to kill the persistent connection and switched back to mysql_pconnect(), and now everything works fine.
15-Aug-2002 12:13
If anyone ever wonders why the number of idle db process (open connections) seems to grow even though you are using persistent connections, here's why:
"You are probably using a multi-process web server such as Apache. Since
database connections cannot be shared among different processes a new
one is created if the request happen to come to a different web server
child process."
18-Apr-2000 04:28
Yes, with nonpersistent connections database connections last only while a database-related request is processed, thus reducing the load on the database server.
However, latency will be somewhat higher since a database connection must be opened before a request can be handeled.
