MySQL connection failing on same query. Trying to reconnect with default user - mysql

I am getting the following error on the same query:
Warning: mysql_query(): Access denied for user 'www-data'#'localhost' (using password: NO)
The error only occurs on the first try from any particular IP. After I refresh the page, the script runs fine. To be more specific, I will run it from a browser in one location, and it will error. If I refresh the page, the problem is fixed. That is until I try from another location.
From what I gather, its losing the connection to the database server and trying to reconnect with the default username. What's confusing me is that it fails on the same query each time. Let's call this query_X. Multiple queries run before query_X including selects, inserts, and updates. Query_X looks like this:
UPDATE game_users
SET status_cd=$tmp_status,
expire_date=date_add('$currentExpire', interval $l_license_duration_days day)
WHERE game_user_id=$l_game_user_id
As an example, the variables being passed are:
$tmp_status = 1;
$currentExpire = '2011-12-05';
$l_license_duration_days = 30;
$l_game_user_id = 1;
What is it about this query that makes the connection fail, and why does refreshing the page fix the problem?
Fyi, I'm using persistent connect.
Edit: I just tried again from an ip that I tried last night. And I received the error again. That is on the first run of the script. After I ran the page a second time, it worked fine.
Edit: It will also error the first time it's run on a particular browser, even if it is on the same IP, i.e. it will error once on firefox and then be fine, error on chrome once and then be fine, etc.
Edit: I've narrowed it down to a mail() function that was happening just before query_X. I still don't know why the mail function is closing the mySQL connection. I've decided to put the mail function (which works properly and sends the email) at the end of the php file, where I would close the connection anyways. It's a hack, but I've spent too much time on this already.

It looks like you closed the connection before some call to mysql_query(). The message of access denied should happen on the mysql_connect() phase.
Are you sure the error is in the query and not in the connect / close functions?

Related

MYSQL Select db & Select table issue. Configuration confusion [duplicate]

In my local/development environment, the MySQLi query is performing OK. However, when I upload it on my web host environment, I get this error:
Fatal error: Call to a member function bind_param() on a non-object in...
Here is the code:
global $mysqli;
$stmt = $mysqli->prepare("SELECT id, description FROM tbl_page_answer_category WHERE cur_own_id = ?");
$stmt->bind_param('i', $cur_id);
$stmt->execute();
$stmt->bind_result($uid, $desc);
To check my query, I tried to execute the query via control panel phpMyAdmin and the result is OK.
TL;DR
Always have mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); in your mysqli connection code and always check the PHP errors.
Always replace every PHP variable in the SQL query with a question mark, and execute the query using prepared statement. It will help to avoid syntax errors of all sorts.
Explanation
Sometimes your MySQLi code produces an error like mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given..., Call to a member function bind_param()... or similar. Or even without any error, but the query doesn't work all the same. It means that your query failed to execute.
Every time a query fails, MySQL has an error message that explains the reason. In the older PHP versions such errors weren't transferred to PHP, and all you'd get is a cryptic error message mentioned above. Hence it is very important to configure PHP and MySQLi to report MySQL errors to you. And once you get the error message, fixing it will be a piece of cake.
How to get the error message in MySQLi
First of all, always have this line before MySQLi connect in all your environments:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
After that, all MySQL errors will be transferred into PHP exceptions. An uncaught exception, in turn, makes a PHP fatal error. Thus, in case of a MySQL error, you'll get a conventional PHP error. That will instantly make you aware of the error cause. And the stack trace will lead you to the exact spot where the error occurred.
How to get the error message from PHP
Here is a gist of my article on PHP error reporting:
Reporting errors on a development and live servers must be different. On the development server it is convenient to have errors shown on-screen, but on a live server error messages must be logged instead, so you could find them in the error log later.
Therefore, you must set corresponding configuration options to the following values:
On a development server
error_reporting should be set to E_ALL value;
log_errors should be set to 1 (it is convenient to have logs on a development PC too)
display_errors should be set to 1
On a production server
error_reporting should be set to E_ALL value;
log_errors should be set to 1
display_errors should be set to 0
After that, when MySQL query fails, you will get a PHP error that explains the reason. On a live server, in order to get the error message, you'll have to check the error log.
In case of AJAX call, on a dev server open DevTools (F12), then Network tab. Then initiate the request which result you want to see, and it will appear in the Network tab. Click on it and then the Response tab. There you will see the exact output. On a live server check the error log.
How to actually use it
Just remove any code that checks for the error manually, all those or die(), if ($result), try..catch and such. Simply write your database interaction code right away:
$stmt = $this->con->prepare("INSERT INTO table(name, quantity) VALUES (?,?)");
$stmt->bind_param("si", $name, $quantity);
$stmt->execute();
Again, without any conditions around. If an error occurs, it will be treated like any other error in your code. For example, on a development PC it will just appear on-screen, while on a live site it will be logged for the programmer, whereas for the user's convenience you could use an error handler (but that's a different story which is off topic for MySQLi, but you may read about it in the article linked above).
What to do with the error message you get
First of all you have to locate the problem query. The error message contains the file name and the line number of the exact spot where the error occurred. For the simple code that's enough, but if your code is using functions or classes you may need to follow the stack trace to locate the problem query.
After getting the error message, you have to read and comprehend it. It sounds too obvious if not condescending, but learners often overlook the fact that the error message is not just an alarm signal, but it actually contains a detailed explanation of the problem. And all you need is to read the error message and fix the issue.
Say, if it says that a particular table doesn't exist, you have to check spelling, typos, and letter case. Also you have to make sure that your PHP script connects to a correct database
Or, if it says there is an error in the SQL syntax, then you have to examine your SQL. And the problem spot is right before the query part cited in the error message.
If you don't understand the error message, try to google it. And when browsing the results, stick to answers that explain the error rather than bluntly give the solution. A solution may not work in your particular case, but the explanation will help you to understand the problem and make you able to fix the issue by yourself.
You have to also trust the error message. If it says that number of tokens doesn't match the number of bound variables then it is so. The same goes for the absent tables or columns. Given the choice, whether it's your own mistake or the error message is wrong, always stick to the former. Again it sounds condescending, but hundreds of questions on this very site prove this advise extremely useful.
A list of things you should never ever do in regard of error reporting
Never use an error suppression operator (#)! It makes a programmer unable read the error message and therefore unable to fix the error
Do not use die() or echo or any other function to print the error message on the screen unconditionally. PHP can report errors by itself and do it the right way depends on the environment - so just leave it for PHP.
Do not add a condition to test the query result manually (like if($result)). With error exceptions enabled such condition will just be useless.
Do not use the try..catch operator for echoing the error message. This operator should be used to perform some error handling, like a transaction rollback. But never use it just to report errors - as we learned above, PHP can already do it, the right way.
P.S.
Sometimes there is no error, but no results either. Then it means, there is no data in the database to match your criteria. In this case you have to admit this fact, even if you can swear the data and the criteria are all right. They are not. You have to check them again.
I've got an article that can help in this matter, How to debug database interactions. Although it is written for PDO, the principle is the same. Just follow those instructions step by step and either have your problem solved or have an answerable question for Stack Overflow.

Previously working Google Sheets App Script is now throwing the "Failed to establish a database connection" error for MySQL DB

I've been using Google Sheets App Script successfully the past 4 months that is connected to a MySQL 5.7 DB hosted remotely on a VPS (this script connected to my DB successfully earlier today as well). All of a sudden this afternoon my requests are returning "Failed to establish a database connection. Check connection string, username and password." The database connection still works just fine remotely on my computer using MySQL Workbench.
Additional details:
The credentials didn't change (I confirmed with a new connection test)
I have Chrome V8 Runtime disabled since that does not work well at all
I double checked the Google Server IPs to whitelist and noticed 1 server that's either new or I missed the first time, either way all provided IPs are currently whitelisted
I'm connecting using this syntax: var conn = Jdbc.getConnection(url, user, pwd);
I saw some previous comments from a month ago that some people were able to add these parameters successfully: var conn = Jdbc.getConnection(url+'?verifyServerCertificate=false&useSSL=true&requireSSL=true', user, pwd);
However I just get this: Error Invalid argument: _serverSslCertificate
Any further steps or tips to get this connected successfully again is appreciated, thanks!
Austin, you just made my day... Same thing, my MySQL connections stopped working all of a sudden yesterday. Spent hours trying to fix it. The '?useSSL=false' worked like charm.
Thank you, thank you, thank you
I found a solution.
Seems a change on Google now requires you to explicitly set SSL to false. (previously if you let it omitted it would default to off)
?useSSL=false
So you need to update your connection string to something like this simple example.
function myFunction() {
var conn = Jdbc.getConnection("jdbc:mysql://35.214.129.151:3306/dbiyrogncria1r?useSSL=false", "uyxfedtljijfy8", "rnqgnyrs2dthb");
Logger.log(conn);
conn.close();
}
Apparently it's just working again.... must have been a service blip. What's strange is it started working again after I decided to just try var conn = Jdbc.getConnection(url+'?useSSL=false', user, pwd); since I saw some other comments mention that. Seems like an awful solution, but it started working again after I did that, but has continued to work even after I reverted back to just var conn = Jdbc.getConnection(url, user, pwd);
Follow-up questions, are there any good alternatives to Google Sheets with App Script like usage? I'm getting really tired of Google's awful support - would rather pay for a product than to hear "you get what you pay for" with awful support.
EDIT: After this started working again yesterday by itself, the issue came back. I have now confirmed today that switching to var conn = Jdbc.getConnection(url+'?useSSL=false', user, pwd); has solved my connection issue, but that is not an ideal fix by any means at all. Google must be messing with some network settings on the Apps Script side and it's causing issues.

Google Cloud SQL No Response

We are running a Sails.js API on Google Container Engine with a Cloud SQL database and recently we've been finding some of our endpoints have been stalling, never sending a response.
I had a health check monitoring /v1/status and it registered 100% uptime when I had the following simple response;
status: function( req, res ){
res.ok('Welcome to the API');
}
As soon as we added a database query, the endpoint started timing out. It doesn't happen all the time, but seemingly at random intervals, sometimes for hours on end. This is what we have changed the query to;
status: function( req, res ){
Email.findOne({ value: "someone#example.com" }).then(function( email ){
res.ok('Welcome to the API');
}).fail(function(err){
res.serverError(err);
});
}
Rather suspiciously, this all works fine in our staging and development environments, it's only when the code is deployed in production that the timeout occurs and it only occurs some of the time. The only thing that changes between staging and production is the database we are connecting to and the load on the server.
As I mentioned earlier we are using Google Cloud SQL and the Sails-MySQL adapter. We have the following error stacks from the production server;
AdapterError: Invalid connection name specified
at getConnectionObject (/app/node_modules/sails-mysql/lib/adapter.js:1182:35)
at spawnConnection (/app/node_modules/sails-mysql/lib/adapter.js:1097:7)
at Object.module.exports.adapter.find (/app/node_modules/sails-mysql/lib/adapter.js:801:16)
at module.exports.find (/app/node_modules/sails/node_modules/waterline/lib/waterline/adapter/dql.js:120:13)
at module.exports.findOne (/app/node_modules/sails/node_modules/waterline/lib/waterline/adapter/dql.js:163:10)
at _runOperation (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:408:29)
at run (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:69:8)
at bound.module.exports.findOne (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/basic.js:78:16)
at bound [as findOne] (/app/node_modules/sails/node_modules/lodash/dist/lodash.js:729:21)
at Deferred.exec (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/deferred.js:501:16)
at tryCatcher (/app/node_modules/sails/node_modules/waterline/node_modules/bluebird/js/main/util.js:26:23)
at ret (eval at <anonymous> (/app/node_modules/sails/node_modules/waterline/node_modules/bluebird/js/main/promisify.js:163:12), <anonymous>:13:39)
at Deferred.toPromise (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/deferred.js:510:61)
at Deferred.then (/app/node_modules/sails/node_modules/waterline/lib/waterline/query/deferred.js:521:15)
at Strategy._verify (/app/api/services/passport.js:31:7)
at Strategy.authenticate (/app/node_modules/passport-local/lib/strategy.js:90:12)
at attempt (/app/node_modules/passport/lib/middleware/authenticate.js:341:16)
at authenticate (/app/node_modules/passport/lib/middleware/authenticate.js:342:7)
at Object.AuthController.login (/app/api/controllers/AuthController.js:119:5)
at bound (/app/node_modules/sails/node_modules/lodash/dist/lodash.js:729:21)
at routeTargetFnWrapper (/app/node_modules/sails/lib/router/bind.js:179:5)
at callbacks (/app/node_modules/sails/node_modules/express/lib/router/index.js:164:37)
Error (E_UNKNOWN) :: Encountered an unexpected error :
Could not connect to MySQL: Error: Pool is closed.
at afterwards (/app/node_modules/sails-mysql/lib/connections/spawn.js:72:13)
at /app/node_modules/sails-mysql/lib/connections/spawn.js:40:7
at process._tickDomainCallback (node.js:381:11)
Looking at the errors alone, I'd be tempted to say that we have something misconfigured. But the fact that it works some of the time (and has previously been working fine!) leads me to believe that there's some other black magic at work here. Our Cloud SQL instance is D0 (though we've tried upping the size to D4) and our activation policy is "Always On".
EDIT: I had seen others complain about Google Cloud SQL eg. this SO post and I was suspicious but we have since moved our database to Amazon RDS and we are still seeing the same issues, so it must be a problem with sails and the mysql adapter.
This issue is leading to hours of downtime a day, we need it resolved, any help is much appreciated!
This appears to be a sails issue, and not necessarily related to Cloud SQL.
Is there any way the QPS limit for Google Cloud SQL is being reached? See here: https://cloud.google.com/sql/faq#sizeqps
Why is my database instance sometimes slow to respond?
In order to minimize the amount you are charged for instances on per use billing plans, by default your instance becomes passive if it is not accessed for 15 minutes. The next time it is accessed there will be a short delay while it is activated. You can change this behavior by configuring the activation policy of the instance. For an example, see Editing an Instance Using the Cloud SDK.
It might be related to your policy setting. If you set it to ON_DEMAND, the instance will sleep to save your budget so that the first query to activate the instance is slow. This might cause the timeout.
https://cloud.google.com/sql/faq?hl=en

Node js mysql ending connection

i read a lot of topic on stack overflow and original docs of node-mysql but nowhere it is clearly described how to handle connections.
i create connection in the very beginning of my script with .createConnection(params)everything works fine i do my last operation with db and naturally im closing it by .end() method the problem starts here
when another user connects my server instead of creating new connection -which i wrote in the very beginning as i told- gives me an error Cannot enqueue Query after invoking quit
the point here i dont understand is i ended connection in previous users section end thi sis new user and script is called from the beginning
why an already ended connection cannot be re-connected is this a bug or am i doing something wrong
I found out the same connection cannot be used twice so i simply added a callback inside connection#end() and if theres no error i set my connection variable to null simply something like this
var connection =connection?connection:mysql.createConnection(dbParams);
connection.connect(
function(err){
if(err)console.log("cannot connect due to",err);
else console.log("connected");
})
//something happens here with db
connection.end(
function(err){
if(!err)connection=null;
else console.log(err)
});
And now everything works perfect

GCE: ERROR The resource <name> already exists (but it doesn't)

I am not sure if this is a bug or an error on my side.
I created and instance on GCE and then proceeded to delete it. The deletion failed with message:
The resource 'projects/[PROJECT]/zones/[ZONE]/instances/[INSTANCE]'
was not found
Please note that this is an automated process that runs a couple times per day, so there wasn't a typo inside the commands.
Nevertheless, the instance was deleted.
Now, every time I try to create an instance with the same name, I get:
NAME ZONE MACHINE_TYPE INTERNAL_IP EXTERNAL_IP STATUS
ERROR: (gcloud.compute.instances.create) Some requests did not succeed:
- The resource 'projects/[PROJECT]/zones/[ZONE]/instances/[INSTANCE]' already exists
But I can't see the instance or its disk anywhere in the Developers Console, neither can I delete it from the command line since I get a resource not found.
I believe this is just a browser cache/cookies issue, where your cache still recognizes the resource name as existing when the resource is already deleted. Clearing the browser cache and cookies or using private browsing/incognito mode should do the trick.
Opening
https://cloud.google.com/appengine/docs/admin-api/reference/rest/v1/apps/repair
in a browser, entering the project ID + submitting has fixed a problem with the same error message for me.