Self-Righting Db Connection

Hi,

I’ve had some issues recently on an application whereby I’ve been getting “MySQL server has gone away” messages. I’m not using persistent connections which I’ve heard PDO has a problem with under PHP 5.3, I believe this was wholly to do with time limits (a SOAP call to a remote server was taking a long time). I’ve increased the time limit, but was considering trying a more robust solution: Reconnect when the system finds that it has been disconnected. This would not only solve my problem but could also solve problems with temporary DB outages and similar.

My solution is simply to catch the exception, disconnect the CDbConnection, connect it again, and re-run the query. I’d also add a restartLimit variable to the Db Connection to avoid entering into an infinite loop. The following code is untested, but what do you think of my Repairable DB Connection Class?




class RDbConnection extends CDbConnection {

	public $repairLimit = 1;

	public function createCommand($query=null)

	{

		$this->setActive(true);

		return new RDbCommand($this,$query);

	}

	public function repair()

	{

		if($this->restartLimit === null || $this->restartLimit-- > 0) {

			$this->setActive(false);

			$this->setActive(true);

			return true;

		}

		return false;

	}

}

class RDbCommand extends CDbCommand {

	public function queryInternal($method,$mode,$params=array())

	{

		try {

			return parent::queryInternal($method,$mode,$params);

		} catch (Exception $e) {

			if(true/*Check the exception type*/ && $this->getConnection()->repair()) {

				parent::queryInternal($method,$mode,$params);

			} else {

				throw $e;

			}

		}


	}

}



So… What I’m missing is obviously a way to check the error and see if it is 100% definitely a “General error: 2006 MySQL server has gone away” error. I could just check for that text, but what if I was just trying to insert that text into the database and the CDbException was thrown for some other reason.

Note, I could have made the second "parent::queryInternal", after the repair, a "$this->queryInternal" instead… I figured that if the same query fails twice then the problem is with the query and so it should fail. Yes?

Anyhow, what do you think? Is it a good idea, or is it just going to put more load on a server when I should probably just let the system fail?

Hi Lilt,

Were you able to verify that your solution works as expected?

I am facing the same issue…and your solution looks good. Will certainly try it out.

Regards,

Kapil