Kalıcı Bağlantılı Veritabanı Bağlantıları

Kalıcı bağlantılar betiğinizin çalışması bittiğinde kapanmayan bağlantılardır. Bir kalıcı bağlantı istendiğinde PHP evvelce açılmış eşdeğer bir kalıcı bağlantı var mı diye bakar ve varsa onu kullanır. Yoksa yeni bir bağlantı oluşturur. Bir 'eşdeğer' bağlantı, aynı konağa (uygulanabildiği takdirde) aynı kullanıcı adı ve parola kullanılarak açılmış bağlantıdır.

HTTP sunucuları hakkında tam bilgi sahibi olmayan kişiler ne yaptıklarını bilmeden yükü yanlış kalıcı bağlantılara dağıtabilir ve bu yanlış bağlantılarla çalışabilirler. Özellikle, size aynı bağlantı üzerinde 'kullanıcı oturumları' açma olanağını, verimli hareket işlemleri kurulmasını ve başka birçok şeyi bir bütün halinde sağlamazlar. Aslında, son derece net olarak, kalıcı bağlantılar, kalıcı olmayan bağlantılarla mümkün olmayan işlevselliği size sağlayamazlar.

Neden?

Bu HTTP sunucusunun işi nasıl yaptığı ile ilgilidir. PHP'nin HTML sayfalarını üretmek için HTTP sunucusunu üç şekilde kullanabilir.

İlk yöntem, PHP'yi bir CGI "sarmalayıcı" olarak kullanmaktır. Bu yolla, HTTP sunucusundan her PHP sayfası isteğinde PHP yorumlayıcısının yeni bir örneği oluşturulup yok edilir. Yorumlayıcı her istekten sonra yok edildiğinden kazanılan özkaynaklar da (bir SQL veritabanı bağlantısı gibi) kaybedilir. Bu durumda, kalıcı bağlantılar kullanarak da hiç bir şey kazanamazsınız; çünkü özkaynaklar kalıcı olmayacaktır.

İkinci ve en çok kullanılan yöntem, PHP'yi çok süreçli bir sunucuda bir modül olarak çalıştırmaktır. Bu olanak şimdilik sadece Apache HTTP sunucusu ile mümkündür. Çok süreçli bir sunucu, işleri sayfaları sunmak olan bir çok (alt) süreci denetimi altında tutan bir ana sürece sahiptir. Bir istemciden bir istek geldiğinde, başka istemcilere hizmet sunmayan alt süreçlerden birini bu isteğe tahsis eder. Eğer aynı istemci ikinci bir istek yaparsa bu isteğe başka bir alt süreç yanıt verebilir. Kalıcı bir bağlantı açıldığında SQL hizmeti isteği yapılan her sayfa isteği SQL sunucuya tahsis edilen aynı bağlantıdan sunulur.

Son yöntem, PHP'yi çok evreli bir sunucuda bir eklenti olarak kullanmaktır. PHP4 şimdilik, PHP'nin bir eklenti olarak kullanımına izin veren Netscape FastTrack (iPlanet), Microsoft's Internet Information Server (IIS) ve O'Reilly's WebSite Pro gibi çok evreli HTTP sunucularında ISAPI, WSAPI ve (Windows üzerinde) NSAPI için destek vermektedir. Davranış esas olarak ikinci yöntemde açıklanan çok süreçli yöntemle aynıdır.

Kalıcı bağlantılar ek bir işlevselliğe sahip değilseler bunlar neden tercih ediliyorlar?

Yanıtı oldukça basittir: Verimlilik. SQL sunucunuza bağlantı açmak çok masraflıysa kalıcı bağlantılar kurmak daha iyidir. Bu bedel gerçekte birçok sebebe bağlı olabileceği gibi olmayabilir de. Bu, veritabanının, HTTP sunucunun bulunduğu makinede olup olmamasından SQL sunucusunun makineye ne kadar yük bindirdiğine kadar geniş bir yelpazede değerlendirilebilir. Son değerlendirmede, eğer bu bedel yüksekse kalıcı bağlantıların büyük ölçüde yardımı olacaktır. SQL sunucuya yapılan her bağlantı isteğinde alt süreç sadece o sayfayı işleyeceği yerde, kalıcı bağlantı durumunda her alt sürecin ömrü boyunca bir bağlantı krmasına olanak tanınır. Yani, bir kalıcı bağlantı açmış her alt sürecin kendine ait bir kalıcı bağlantısı vardır. Örneğin, SQl sunucunuza kalıcı bağlantı açan betiğiniz 20 ayrı alt süreç çalıştırıyorsa alt süreç başına bir tane olmak 20 ayrı bağlantı var demektir.

Ancak şuna dikkat edin, bağlantı sayısı sınırlı bir veritabanını bu sınırın üstünde kalıcı bağlantılarla kullanıyorsanız bunun bazı götürüleri olabilir. Eğer veritabanınız aynı anda 16 bağlantılık bir sınıra sahipse ve çok meşgul bir sunucu oturumunda 17 alt evre bağlantı açmaya çalışıyorsa biri bunu başaramayacaktır. Eğer betiğinizde (sonsuz döngü gibi durumlarda) bağlantıların kapatılmasına izin vermeyen hatalar varsa, veritabanı sadece 16 bağlantı ile hızla batağa saplanacaktır. Terkedilmiş ve boştaki bağlantıların devreye sokulması hakkında bilgi edinmek için veritabanınızın belgelerine bakınız.

Uyarı

Kalıcı bağlantıları kullanırken hesaba katmanız gereken bir çok yetersizlik vardır. Bunlardan biri, bir kalıcı bağlantı üzerinden tablo kilitlemesi yapıyorsanız ve betiğiniz herhangi bir şekilde kilidi serbest bırakamazsa aynı bağlantıyı kullanan sonraki betikler sonsuza kadar engellenebilir ve bunun sonucu olarak HTTP sunucunuzu veya veritabanı sunucunuzu yeniden başlatmak zorunda kalabilirsiniz. Bir diğer durumda, hareketleri (transaction) kullanırken, bir hareket bloğu tamamlanmadan betiğiniz çalışmasını bitirirse aynı bağlantıyı kullanan sonraki betiklerin işleri başlarından aşacaktır. Her durumda, tablolarınızın kilitlerini açmak ve hareketleri başa sarmak için register_shutdown_function() işlevini kullanarak bir temizlik işlevi tanımlayabilirsiniz. Daha da iyisi, tablo kilitleri veya hareket blokları kullanan betiklerde kalıcı bağlantıları kullanmayarak bu sorunlardan tamamiyle kurtulabilirsiniz.

Özetle, kalıcı bağlantılar normal bağlantılarla bire bir eşleşecek şekilde tasarlanmışlardır. Yani, betiğinizin davranışını değiştirmeden kalıcı bağlantılar yerine her zaman kalıcı olmayan bağlantılar kullanabilirsiniz. Bu, muhtemelen betiğinizin verimliliğini etkileyecektir ama davranışında bir değişikliğe yol açmayacaktır!

Ayrıca bakınız: fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(), mysql_pconnect(), ociplogon(), odbc_pconnect(), oci_pconnect(), pfsockopen(), pg_pconnect() ve sybase_pconnect().

add a note add a note

User Contributed Notes 13 notes

up
5
pacerier at gmail dot com
2 years ago
Did anyone else notice that the last paragraph contradicts everything above it?

( cached page: https://archive.is/ZAOwy )
up
5
ynzhang from lakeheadu canada
8 years ago
It seems that using pg_pconnect() will not persist the temporary views/tables. So if you are trying to create temporary views/tables with the query results and then access them with the next script of the same session, you are out of luck. Those temporary view/tables are gone after each PHP script ended. One way to get around this problem is to create real view/table with session ID as part of the name and record the name&creation time in a common table. Have a garbage collection script to drop the view/table who's session is expired.
up
3
php at alfadog dot net
3 years ago
One additional not regarding odbc_pconnect  and possibly other variations of pconnect:

If the connection encounters an error (bad SQL, incorrect request, etc), that error will return with  be present in odbc_errormsg for every subsequent action on that connection, even if subsequent actions don't cause another error.

For example:

A script connects with odbc_pconnect.
The connection is created on it's first use.
The script calls a query "Select * FROM Table1".
Table1 doesn't exist and odbc_errormsg contains that error.

Later(days, perhaps), a different script is called using the same parameters to odbc_pconnect.
The connection already exists, to it is reused.
The script calls a query "Select * FROM Table0".
The query runs fine, but odbc_errormsg still returns the error about Table1 not existing.

I'm not seeing a way to clear that error using odbc_ functions, so keep your eyes open for this gotcha or use odbc_connect instead.
up
3
Tom
7 years ago
There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.
up
2
christopher dot jones at oracle dot com
10 years ago
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.
up
0
fabio
11 years ago
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.
up
-1
ambrish at php dot net
7 years ago
In IBM_DB2 extension v1.9.0 or later performs a transaction rollback on persistent connections at the end of a request, thus ending the transaction. This prevents the transaction block from carrying over to the next request which uses that connection if script execution ends before the transaction block does.
up
-3
RQuadling at GMail dot com
11 years ago
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+).
up
-3
andy at paradigm-reborn dot com
10 years ago
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.
up
-7
whatspaz at g NO dot SPAM mail dot c o m
11 years ago
in response to web at nick, have you tried FLUSH PRIVILEGES. this should reload those privileges.
up
-12
jean_christian at myrealbox dot com
15 years ago
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."
up
-22
aaryal at foresightint dot com
13 years ago
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.
up
-28
jorgeleon85 at gmail dot com
6 years ago
I've been looking everywhere for a benchmark or at least comparison of the overhead used by oci_connect and oci_pconnect.
Just saying "oci_connect is slower because the overhead..." is not enough for me. For than I wrote a couple scripts to compare perfomance.
At the end I found out an average of 34% more time using a oci_connect than oci_pconnect, using a query of 50 rows and 100 columns.
Obviously this wasn't a real benchmark however it gives a simple idea of the efficiency of each function.
To Top