Here is the problem
There is a script that after X amount of time (unknown amount between 5 and 40 minutes) throws the following error: MySQL server has gone away which Kohana turns into a Database_Exception 2006 As a result some of the information is not saved to the DB.
Here is what I think might work
class Model_Bar extends ORM {
protected $_belongs_to = array(
'foo' => array()
);
public function save(){ //Extends the save method
try {
$result = parent::save(); //Try parent save
} catch (Database_Exception $e) { //Catch exception
if ($e->getCode() == 2006) { //If exception code == 2006 then DB has gone away
mysqli_ping(); //Try to refresh DB link
$result = parent::save(); //Try parent save again
} else { //Exception code != 2006
throw new Exception($e); //Throw new DB exception
}
}
return $result; // Return the result from parent::save()
}
}
The Question: How can I refresh the link to the DB in Kohana's ORM?
More Info:
Using Kohana 3.0.8
Possible solution (I dont know how to try it in Kohana)
Thanks!
That's a problem of either
Reached the MYSQL configured timeout
Exceeded packet size
Loss of packets
If you are executing a long insert, like a bulk insert, if your DB isn't configured for that, no change in your code will have any effect. You may try to reconfigure your MYSQL instance, then rule out the MYSQL blame, then after you try to amend your code (which I doubt is the source of the problem). Retrying saving won't help much, but to make the DB even busier.
Another thing, if you are using a proxy (like HAProxy), check the timeouts on that as well.
Related
I am trying to use Firebird 2.1 with Yii (using plugin http://www.yiiframework.com/extension/yii2-firebird/) but I have problems doing insert (save) commands, the error message is:
SQLSTATE[HY000]: General error: -502 Cursor is not open
I have found that Yii generates insert statement with returning clause, e.g.:
INSERT INTO CONTRACTS (contract_no) VALUES (10002) RETURNING contract_no
And I guess that the problem is the following: Yii tries to read results from this insert command but there are problems with Yii-Firebird plugin which closes cursors immediately after pdoStatement->execute. The exception is generated in yii/db/Command.php file function protected function queryInternal($method, $fetchMode = null) whose code reads:
$this->pdoStatement->execute();
if ($method === '') {
$result = new DataReader($this);
} else {
if ($fetchMode === null) {
$fetchMode = $this->fetchMode;
}
try {
$result = call_user_func_array([$this->pdoStatement, $method], (array) $fetchMode);
$this->pdoStatement->closeCursor();
} catch (Exception $ex) {
Yii::trace('Fetch error', 'yii\db\Command::query');
}
}
I have the following questions:
Does anyone uses Firebird with Yii, what the experience is?
How to explain code:
call_user_func_array([$this->pdoStatement, $method], (array) $fetchMode);
and where to correct it? I guess that this method should be overriden in Yii-Firebird plugin with the aim to check whether the cursor is open and, if necessary, open the cursor?
Answer for the first question.
With the YII2 I use "edgardmessias/yii2-firebird": "^0.7.1", extension for Firebird 2.1.1883.
I found that it better to work not with ActiveDataProvider, but with
$dataProvider = new ArrayDataProvider([
in the SearchModel. That way are not so much errors while searching with relation.
But main problem is case sensitive search. I always needed to write in the search field same letters what record have, Big or small.
I have a question regarding PHP's way to handle exceptions and Laravel 5.
Here's a snippet of what I'm trying to accomplish
try
{
//set up webservices
saveData();
} catch(exception $e)
{
Log:error('stuff went bananas')
}
saveData(){
//record stuff through DB with eloquent
//in case some data is missing connect to a second DB
try
{
connect()
query to get data
}catch(exception $e)
{
//log error again
}
In other words, I'm calling webservices that receive data. I'm then inserting these into my own DB inside the Model.
At this stage I'm trying to see if I know the user ID that I just received. In case I don't I have to connect to a second database to request that same user.
There are two issues though
the second database I'm trying to connect isn't likely to be up
it will often not hold the information I need (I have to try again the next day)
There's nothing I can do against these issues. But what I want is for my code to try and connect, and in case it fails, log the errors and keep moving inserting the data.
Thanks in advance.
I am using redis as a cache to help with application performance regarding data that has a high cost of generation. Currently we only have one redis instance running and I have observed that if redis is not available - then 500 error is being returned.
Given that I am caching - I would rather continue processing if redis is down and render that page with the data omitted.
I have tested using a basic php try - catch block - but it I have not been able to trap the exception.
public function redisAction()
{
try {
$redis = $this->container->get('snc_redis.default');
$val = $redis->get('foo:bar');
} catch (Exception $e ) {
$response = new Response('Oops ');
return $response;
}
....
}
Is there any other approaches I can take - I am also investigating the sncredis bundle to see if it can be addressed there.
Given you did not include use Exception on top of your class you will need to add a leading backslash ... otherwise PHP will try to catch Your\Current\Namespace\Exception which doesn't exist.
catch (\Exception $e ) {
// ...
}
But I'm not sure if redis throws an exception if the requested key does not exist (actually I don't think so).
You could use the exists() method to check if the key exists instead.
if ($redis->exists("foo:bar")) {
return new Response('Oops');
}
I am running a php gearman worker which establishes the connection to the database. However, the problem is that after around 8 hours, the mysql connection disconnects, and my worker crashes. So, I wanted to disconnect and make a new connection to the database again.
I am using CDbConnection to connect to the database in Yii, and was expecting "setActive(false)" to do the trick for me. Here below I am "explicitly disconnecting" and the making a db query....expecting my query to throw an exception, but I am surprised to see that "setActive" makes no impact at all and my query goes successfully.
//if it fails then reconnect to the database
Yii::app()->db->setActive(false);
try {
$model = MyModel::model()->findByPk(10);
var_dump($model);
} catch (exception $e) {
echo "got exception -- ".$e->getMessage()."\n";
Yii::app()->db->setActive(false);
Yii::app()->db->setActive(true);
// I also tried Yii::app()->db->active = true/false
$model = MyModel::model()->findByPk(10);
var_dump($model);
}
How do I disconnect and reconnect to my database with CdbConnection?
Try looking in the trace log, I'm pretty sure it actually closes the connection, but then reopens it in CDbConnection->createCommand() when you execute a query.
I've got a web application that is used by a company for logging their employees' work.
A lot of people are often logged in at once.
The application runs on a shared host.
I sometimes receive...
Warning: mysql_connect() [function.mysql-connect]: Too many connections
Which then lets further errors cascade... like errors with mysql_select_db(), mysql_error(), mysql_errnon() and finally the uncaught Database_Eexception.
When I run my main request, I wrap it in a try and capture any exception and display a not found page. This is because usually my controllers throw exceptions if a resource is not found (though the route may be valid) e.g. http://example.com/products/30 is a valid route, but product #30 doesn't exist.
What is the best way to handle the too many connections? Ideally I'd like to capture that exception separately, then display a nice page that informs the employee to try again in 5 minutes.
The code that runs my main request in application/bootstrap.php looks like this...
$request = Request::instance();
try {
$request->execute();
} catch (Exception $e) {
if (Kohana::$environment === Kohana::DEVELOPMENT) throw $e;
// Log the error
Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
// Create a 404 response
$request->status = 404;
$request->response = Request::factory(Route::get('catch_all')->uri(array('path' => 'errors/404')))->execute();
}
$request->send_headers();
echo $request->response;
Thanks for any help!
I just created such file to handle all the errors:
<?php
class Kohana extends Kohana_Core
{
/**
* Redirect to custom exception_handler
*/
public static function exception_handler(Exception $e)
{
if (Kohana::DEVELOPMENT === Kohana::$environment)
{
// Pass to Kohana if we're in the development environment
parent::exception_handler($e);
}
else
{
Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
// Default route
$route = Route::url('default', array('controller' => 'error', 'action' => '404'));
// Error sub-request.
echo Request::factory($route)
->execute()
->send_headers()
->response;
}
}
}
For now it is just a sketch, but it could give you some ideas.
ps: my bootstrap is not modified
In /etc/my.cnf under the [mysqld] section add:
max_connections = 500
Then either executeSET GLOBAL max_connections = 500; in MySQL or restart MySQL.
You might want to begin by checking to see what your MySQL system property max_connections is currently set to, and see how that compares usage requirements. If you don't have a good handle on usage requirements then you could do worse than instrument your code to log data about simultaneous connections; or your a live database profiling tool to monitor this.
You could also look to see if your code is hogging connections for too long (ie. unnecessarily) and correct this. Perhaps investigate connection pooling.