I'm working with Wordpress and PHP. We had an issue in which our w writer db became our reader r db during a fail over in the database cluster. This cause the production site to break. Currently, I'm trying to prevent the site from crashing do to this.
I get the following error from WP Engine when the database is trying to insert data into a table:
WordPress database error INSERT command denied to user
'readonly'#'xx.xxx.xx.xx' for table 'responses' for query INSERT INTO
responses (uid, data) VALUES
The error is raise from the following function:
<?php
namespace StatCollector;
function drools_request($data, $uid) {
try {
$db = _get_db();
$insertion = $db->insert("requests", [
"uid" => $uid,
"data" => json_encode($data),
]);
if($insertion === false) {
throw new \Exception('Error writing to the database: ' . $db->last_error);
}
}
catch(\Exception $e)
{
echo 'Error writing to the database: ', $e->getMessage(), "\n";
}
}
When the database become --read-only this shouldn't stop the site to work. Why isn't error handling working in this case. Does this mean that to error handle this I need to catch an Error? Why isn't the error handling working here?
[Not sure this works, but it is too long for a comment]
You didn't mention your back-end database, so I bet it is MySQL because you mentioned Wordpress.
You can try to instruct mysql to throw exceptions, like this:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
class.mysqli-sql-exception
I wouldn't advice to do that in the core of wordpress itself, but you can try calling it before executing your try/catch.
Edit: Some people advice MYSQLI_REPORT_ALL instead of MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT. Give it a try and see what works best in your situation.
Related
Pretty new to laravel, so I'm not exactly sure how it handles errors and how best to catch them.
I'm using a 3rd party game server connection library that can query game servers in order to pull data such as players, current map etc..
This library is called Steam Condenser : https://github.com/koraktor/steam-condenser
I have imported this using composer in my project and all seems to be working fine, however I'm having trouble with catching exceptions that are thrown by the library.
One example is where the game server you are querying is offline.
Here is my code:
public function show($server_name)
{
try{
SteamSocket::setTimeout(3000);
$server = server::associatedServer($server_name);
$server_info = new SourceServer($server->server_ip);
$server_info->rconAuth($server->server_rcon);
$players = $server_info->getPlayers();
$total_players = count($players);
$more_info = $server_info->getServerInfo();
$maps = $server_info->rconExec('maps *');
preg_match_all("/(?<=fs\)).*?(?=\.bsp)/", $maps, $map_list);
}catch(SocketException $e){
dd("error");
}
return view('server', compact('server', 'server_info', 'total_players', 'players', 'more_info', 'map_list'));
}
If the server is offline, it will throw a SocketException, which I try to catch, however this never seems to happen. I then get the error page with the trace.
This causes a bit of a problem as I wish to simply tell the end user that the server is offline, however I cannot do this if I can't catch this error.
Is there something wrong with my try/catch? Does laravel handle catching errors in this way? Is this an issue with the 3rd party library?
A couple things:
Does the trace lead to the SocketException or to a different error? It's possible that a different error is being caught before the SocketException can be thrown.
Your catch statement is catching SocketException. Are you importing the full namespace at the top of your PHP file? use SteamCondenser\Exceptions\SocketException;
Also for debugging purposes, you could do an exception "catch all" and dump the type of exception:
try {
...
}catch(\Exception $e){
dd(get_class($e));
}
If you still get the stack trace after trying the above code, then an error is being thrown before the try/catch block starts.
I am trying to check if a database is connected in Laravel.
I've looked around the documentation and can't find anything. The closest thing I've found is this, but this doesn't solve my problem.
I have three instances of MySQL that are set up on different machines. Below is a simplified version of what I am trying to achieve.
If database 1 is connected, save data to it
If database 1 is not connected, check if database 2 is connected
If database 2 is connected save data to it
If database 2 is not connected, check if database 3 is connected
If database 3 is connected, save data to it
To be clear, is there a way to check that a database is connected in Laravel 5.1?
Try just getting the underlying PDO instance. If that fails, then Laravel was unable to connect to the database!
use Illuminate\Support\Facades\DB;
// Test database connection
try {
DB::connection()->getPdo();
} catch (\Exception $e) {
die("Could not connect to the database. Please check your configuration. error:" . $e );
}
You can use alexw's solution with the Artisan. Run following commands in the command line.
php artisan tinker
DB::connection()->getPdo();
If connection is OK, you should see
CONNECTION_STATUS: "Connection OK; waiting to send.",
near the end of the response.
You can use this, in a controller method or in an inline function of a route:
use Illuminate\Support\Facades\DB;
//....
try {
DB::connection()->getPdo();
if(DB::connection()->getDatabaseName()){
echo "Yes! Successfully connected to the DB: " . DB::connection()->getDatabaseName();
}else{
die("Could not find the database. Please check your configuration.");
}
} catch (\Exception $e) {
die("Could not open connection to database server. Please check your configuration.");
}
You can also run this:
php artisan migrate:status
It makes a db connection connection to get migrations from migrations table. It'll throw an exception if the connection fails.
You can use this query for checking database connection in laravel:
use Illuminate\Support\Facades\DB;
// ...
$pdo = DB::connection()->getPdo();
if($pdo)
{
echo "Connected successfully to database ".DB::connection()->getDatabaseName();
} else {
echo "You are not connected to database";
}
For more information, you can check out this page https://laravel.com/docs/5.0/database.
I don't know if this worked in that version of laravel, but at least on newer ones you can run
php artisan db
and if your app can access the database then you should see a cli repl for it, for postgres you will see a psql instance
Another Approach:
When Laravel tries to connect to database, if the connection fails or if it finds any errors it will return a PDOException error. We can catch this error and redirect the action
Add the following code in the app/filtes.php file.
App::error(function(PDOException $exception)
{
Log::error("Error connecting to database: ".$exception->getMessage());
return "Error connecting to database";
});
Hope this is helpful.
A lot of tutorials and books I have been over and read have used the die() method to catch an exception when interacting with a local MySQL database
For example:
mysql_connect($dbhost, $dbuser, $dbpass)or die(mysql_error());
Would a try/catch block be more beneficial over the die() method or is that just the standard way that exception handling works with db connections?
or die() is an extremely primitive way to "handle" errors and only for examples or debugging at best. In practice, it depends on how you handle your errors. You may want to return false from a function call or you may want to throw your own exception instead; e.g.:
if (!$con = mysql_connect(..)) {
throw new DatabaseConnectionError(mysql_error());
}
try..catch will do exactly nothing with mysql, since mysql never throws any exceptions. It only ever returns false on failure.
You will have to have your own error handling strategy. You'll probably want to log errors and display a user friendly error page instead of cryptic error messages. mysql is not concerned with that part. It only gives you a way to check whether an operation was successful or not (check if it returns false); what you do with this information is up to you. die kills the entire application and at least doesn't allow the problem to propagate further; but it certainly does not display any user friendly error pages.
Having said all this, mysql is old and deprecated. If you'd use something newer like PDO instead, it can properly throw exceptions itself.
The mysql_connect method does not throw exceptions and thus die() is used by many applications to terminate when there is no connection available.
You can use the solution mentioned here: how to use throw exception in mysql database connect
Included for completeness:
try
{
if ($db = mysqli_connect($hostname_db, $username_db, $password_db))
{
//do something
}
else
{
throw new Exception('Unable to connect');
}
}
catch(Exception $e)
{
echo $e->getMessage();
}
Alternatively use the new and more OOP styled database access: http://php.net/manual/en/book.pdo.php
The reason a lot of applications uses die is from the fact that they are so reliant on the database that continuing without a connection is utterly fruitless.
Edit As mentioned in the comments, the code example above is for illustrational purposes. Catching right after throwing is pointless.
First of all I don't have any database and I write code in migrations to create database, table and data, I want to check if database not exist then auto create new database have name in db connect and try catch this connect if error.
public function up()
{
try {
\DBUtil::create_database('database_name', 'utf8_general_ci', true);
// the true flag adds a IF NOT EXISTS
} catch(\Database_Exception $e) {
echo $e->getMessage();
}
}
try code but give error "Unknown database database_name" when I run "php oil refine migrate" in commandline
Can I try catch custom exception this error?
1049!
Fuel\Core\Database_Exception [ 1049 ]:
SQLSTATE[HY000] [1049] Unknown database 'database_name'
Creating a database is not something that is usually done by migrations as it would tie you in to using the same DB name all the time, if you are deploying multiple sites on the same server or have a similar scenario this becomes a big problem.
It's generally assumed that the database itself has been created as part of the set-up, either manual or automatic, so is available for PHP to connect to.
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.