Computer programming in PHP for business and passion
In: IIS| Microsoft SQL Server| PHP| Windows Server| Zend Server
15 Apr 2010If you have a PHP application that use session data and you want to scale using multiple servers or build a reliable architecture you have to share the session data between all the servers in some ways. One of the easy way to do that is to use a load balancer to distribute the traffic between multiple servers and use a database to share the session data.
In the open source community there are many examples on how to share session data using database but i didn’t found an example using MS SQL Server with the new Microsoft SQL Server Driver for PHP so I decided to write a new session handler from scratch. I used the last version 1.1 of the Microsoft SQL Server Driver. I tested the session handler using two Windows Server 2003 running IIS6 and Zend Server 5 CE. I used a SQL Server 2005 database to share the PHP session between the two servers (see diagram below).

The custom session handler
I built a PHP class named SQLSrv_Session with the following static methods: open, close, read, write, destroy, and gc (garbage collector). Basically these are the methods that you have to provide to built a custom PHP session handler (see the session_set_save_handler function of PHP for more info). For security reasons I provided a method (sqlsrv_escape) to escape the session data to write in the MS SQL Server. After the definition of the class I used the register_shutdown_function of PHP to call the session_write_close. This is a fix for a issue of the PHP session manager as of PHP 5.0.5 (see the comments on the pgp.net page of session_set_save_handler). Finally, in order to change the default session handler to the SQLSrv_Session I used the session_set_save_handler as follow:
1 2 3 4 5 6 7 | ini_set('session.save_handler', 'user'); session_set_save_handler(array('SQLSrv_Session', 'open'), array('SQLSrv_Session', 'close'), array('SQLSrv_Session', 'read'), array('SQLSrv_Session', 'write'), array('SQLSrv_Session', 'destroy'), array('SQLSrv_Session', 'gc')); |
In this way we configure PHP to use a custom session handler (user) and choose the new methods of the session manager.
If you want to use the SQLSrv_Session handler you have to include the SQLSrv_Session.php in of all of your scripts (i suggest to use require_once “SQLSrv_Session.php”; at the beginning of your PHP scripts).
After that you can use the PHP session as usual using the $_SESSION global variable. The PHP session manager will use the SQLSrv_Session class to manage the session data instead of the default one.
Installation
In order to use this custom session handler you have to enable the sqlsrv extension from the Zend Server web interface (or in the php.ini if you are a fan of the old school). To manage PHP extensions using Zend Server is very simple, you can do everything using the web interface, under the menu Server Setup > Extensions. You can Turn on the extension with a click and restart the PHP environment with another click on the button Restart PHP, located at the bottom of the page.
To use the sqlsrv extension ver. 1.1 you must have installed the Microsoft SQL Server 2008 Native Client. You can check the system requirements of the SQL Server Driver for PHP here.
After that, to start to use the custom session handler you have to create a database in your MS SQL Server to store the session data.
This database will contain one table with the following structure:
session_id VARCHAR(32) as primary key session_value VARCHAR(MAX) NULL updated_on DATETIME not NULL
To configure the SQLSrv_Session class to use the table created in the previous step you have to use the following constants: DB_HOST, DB_USER, DB_PASS, DB_NAME, and DB_SESSION_TABLE. After that you will be able to use the custom session handler.
Testing
In the .zip attached in this post you can find a simple PHP script to test the custom session handler. This script basically try to use the session handler storing some random values into the $_SESSION. You can check the data stored in your SQL Server database to see if all is working good. To test the destroy method of the custom session handler you have to call the test.php?destroy (passing the destroy parameter in the URL).
Please let me be clear on this point, I provided only some test on this class and I used it only in a simple PHP scenario. If you are planning to use this code on a production environment you have to provide a complete test on your application. However I will be happy to help you if you will find issue using this class, so please comment this post.
Performance consideration
The solution provided in this post is very simple, easy to install and manage, these are its advantages. If your PHP application is used in an high traffic scenario and you need performance this solution is not good enough. It’s a well known fact that share session data using a database is not so fast, there are better ways to do that. For instance, using Memcached to share data in memory or using the Session Cluster of Zend Server 5, especially for business critical scenarios. However, if you are looking for an easy and cheapest solution to share PHP session between multiples IIS servers, using MS SQL Server, this can be actually a good solution for you.
Special thanks
I would like to thanks Gobal Deva to helping me to test the SQLSrv_Session class.
Download
This is my personal blog about computer programming in PHP for business and passion. I'm Enrico Zimuel a Software Engineer since 1996. I work as Senior Consultant & Architect at Zend Technologies. For more info about me visit my web site.
8 Responses to PHP session sharing using Zend Server CE and MS SQL Server
Enrico Zimuel’s Blog: PHP session sharing using Zend Server CE and MS SQL Server | Development Blog With Code Updates : Developercast.com
April 16th, 2010 at 7:18 pm
[...] used SQL Server to do it. Enrico Zimuel has helped to solve that problem with his new post on using Zend Server and SQL Server to persist the session data. In the open source community there are many examples on how to share [...]
André R.
April 19th, 2010 at 10:14 pm
How exactly do you avoid that the two servers generate the same session id for two different users?
Seems like you do not handle this, and even if it will happen rarely, it will likely happen as the session id is generated independently on the two servers..
André R.
April 22nd, 2010 at 10:52 am
Ignore comment above, very unlikely to happen and you can use session.entropy_file and session.entropy_length to make it even more unlikely and less predictable.
Enrico Zimuel
April 22nd, 2010 at 11:54 am
The session ID is managed by the PHP engine. You can decrease the probability of ID collision using the session.entropy_file and session.entropy_length directives of php.ini (with a low number of sessions the probability of collision by default is around 2^-32). But if you have a big number of concurrency sessions, for instance 60K, the probability grows (near 0.5) and it’s mandatory increase he number of bytes used by session ID.
php developer
July 7th, 2010 at 12:11 pm
This is a nice article.. Easy to understand your explanation.
Doing good:-)
Thanks a lot..!
Piotr Szczerbowski
July 7th, 2010 at 8:56 pm
In MySQL it is simple to verify if there is a collision. Setting up an UNIQUE index on the CHAR(32) column (for session hash) returns an error if a duplicated session is created. Proper handling of an error with session creation allows you to try again with another sessonID. There should be similar possibilities for MSSQL, I am not aware of them as I am not handling sessions using Microsft server in my apps.
Enrico Zimuel
July 8th, 2010 at 7:47 am
Hi Piotr,
you are absolutely right. In the MS SQL table proposed in the post the session_id field is primary key so no collision are possible.
Of course we have to manage the error of a collision and try to generate a new random value for the ID until we found a free one.
Jerseys
July 14th, 2010 at 5:13 am
To use the sqlsrv extension ver. 1.1 you must have installed the Microsoft SQL Server 2008 Native Client. You can check the system requirements of the SQL Server Driver for PHP here.