Enable alerts for MySQL long running queries - mysql

My application is loading very slow. After doing some research I got to know that MySQL is causing this slowness. I have around 15-20 users that access this server. After preliminary investigation (googling and stackoverflow), I found out that they were some queries running at the time and those were the culprit. It’s annoying to run query every now and then to look out for the queries running for a long time. Is there a workaround for this and also get email/SMS alerts for it. How can I enable email/SMS alerts to look over those queries

execute below commands on mysql from admin/root user-
slow_query_log = ON;
long_query_time = 2;
Now get slow query log file path from belowcommand-
SHOW VARIABLES LIKE 'slow_query_log_file';
Now go to your mysql db machine and check logged slow queries and optimize them.
Note: By this you can get slow queries even without restart mysql service but for better do these entries in your conf file so that you can get slow logs even after service restart.

Related

Does my sql query continue executing after i been disconnected due to long operation?

If I run a SQL query in MySQL workbench and the connections time out after 30 seconds because it is taking a long time. Does my Query continue executing on the MySQL server even though I am disconnected?
For example, if I am doing an update and the update loops over a billion records. Does the MySQL server disconnect me first then it finishes the query after? Or does it disconnect me and terminate the query?
It does. As Mustafa mentioned, you can see the query still running if you look at "Administration tab" --> Management --> Client Connections.
Also good to remember that you can change the 30sec cap to longer, shorter or none.
Yes, MySQL Workbench can disconnect and the query keeps running. This has been reported as a bug, but it's in the "Verified" state, which means it is not fixed: https://bugs.mysql.com/bug.php?id=78809
See also this related SO thread: MySQL Query running even after losing connection
If you have a long-running query that needs to do a bulk update, you may need to change the MySQL Session timeout options in the MySQL Workbench preferences. Alternatively, don't use MySQL Workbench for long-running jobs, use the mysql command line tool.

Lost connection to MySQL server during query on random simple queries

FINAL UPDATE: We fixed this problem by finding a way to accomplish our goals without forking. But forking was the cause of the problem.
---Original Post---
I'm running a ruby on rails stack, our mysql server is separate, but housed at the same site as our app servers. (we've tried swapping it out for a different mysql server with double the specs, but no improvement was seen.
during business hours we get a handful of these from no particular query.
ActiveRecord::StatementInvalid: Mysql2::Error: Lost connection to MySQL server during query
most of the queries that fail are really simple, and there seems to be no pattern between one query and another. This all started when I upgraded from Rails 4.1 to 4.2.
I'm at a loss as to what to try. Our database server is less than 5% CPU throughout the day. I do get bug reports from users who have random interactions fail due to this, so it's not queries that have been running for hours or anything like that, of course when they retry the exact same thing it works.
Our servers are configured by cloud66.
So in short: our mysql server is going away for some reason, but it's not because of lack of resources, it's also a brand new server as we migrated from another server when this problem started.
this also happens to me on localhost while developing features sometimes, so I don't believe it's a load issue.
We're running the following:
ruby 2.2.5
rails 4.2.6
mysql2 0.4.8
UPDATE: per the first answer below I increased our max_connections variable to 500 last night, and confirmed the increase via
show global variables like 'max_connections';
I'm still getting dropped connection, the first one today was dropped only a few minutes ago....
ActiveRecord::StatementInvalid: Mysql2::Error: Lost connection to MySQL server during query
I ran select * from information_schema.processlist; and I got 36 rows back. Does this mean my app servers were running 36 connections at that moment? or can a process be multiple connections?
UPDATE: I just set net_read_timeout = 60 (it was 30 before) I'll see if that helps
UPDATE: It didn't help, I'm still looking for a solution...
Heres my Database.yml with credentials removed.
production:
adapter: mysql2
encoding: utf8
host: localhost
database:
username:
password:
port: 3306
reconnect: true
The connection to MySQL can be disrupted by a number of means, but I would recommend revisiting Mario Carrion's answer since it's a very wise answer.
It seems likely that connection is disrupted because it's being shared with the other processes, causing communication protocol errors...
...this could easily happen if the connection pool is process bound, which I believe it is, in ActiveRecord, meaning that the same connection could be "checked-out" a number of times simultaneously in different processes.
The solution is that database connections must be established only AFTER the fork statement in the application server.
I'm not sure which server you're using, but if you're using a warmup feature - don't.
If you're running any database calls before the first network request - don't.
Either of these actions could potentially initialize the connection pool before forking occurs, causing the MySQL connection pool to be shared between processes while the locking system isn't.
I'm not saying this is the only possible reason for the issue, as stated by #sloth-jr, there are other options... but most of them seem less likely according to your description.
Sidenote:
I ran select * from information_schema.processlist; and I got 36 rows back. Does this mean my app servers were running 36 connections at that moment? or can a process be multiple connections?
Each process could hold a number of connections. In your case, you might have up to 500X36 connections. (see edit)
In general, the number of connections in the pool can often be the same as the number of threads in each process (it shouldn't be less than the number of thread, or contention will slow you down). Sometimes it's good to add a few more depending on your application.
EDIT:
I apologize for ignoring the fact that the process count was referencing the MySQL data and not the application data.
The process count you showed is the MySQL server data, which seems to use a thread per connection IO scheme. The "Process" data actually counts active connections and not actual processes or threads (although it should translate to the number of threads as well).
This means that out of possible 500 connections per application processes (i.e., if you're using 8 processes for your application, that would be 8X500=4,000 allowed connections) your application only opened 36 connections so far.
This indicates a timeout error. It's usually a general resource or connection error.
I would check your MySQL config for max connections on MySQL console:
show global variables like 'max_connections';
And ensure the number of pooled connections used by Rails database.yml is less than that:
pool: 10
Note that database.yml reflects number of connections that will be pooled by a single Rails process. If you have multiple processes or other servers like Sidekiq, you'll need to add them together.
Increase max_connections if necessary in your MySQL server config (my.cnf), assuming your kit can handle it.
[mysqld]
max_connections = 100
Note other things might be blocking too, e.g. open files, but looking at connections is a good starting point.
You can also monitor active queries:
select * from information_schema.processlist;
as well as monitoring the MySQL slow log.
One issue may be a long-running update command. If you have a slow-running command that affects a lot of records (e.g. a whole table), it might be blocking even the simplest queries. This means you could see random queries timeout, but if you check MySQL status, the real cause is another long-running query.
Things you did not mention but you should take a look:
Are you using unicorn? If so, are your reconnecting and disconnecting in your after_fork and before_fork?
Is reconnect: true set in your database.yml configuration?
Well,at first glance this sounds like your webserver is keeping the mysql sessions open and sometimes a user runs into a timeout. Try disabling the keep mysql sessions alive.
It will be a hog but you only use 5% ...
other tipps:
Enable the mysql "Slow Query Log" and take a look.
write a short script which pulls and logs the mysql processlist every minute and cross check the log with timeouts
look at the pool size in your db connection or set one!
http://guides.rubyonrails.org/configuring.html#database-pooling
should be equal to the max-connections mysql likes to have!
Good luck!
Find out if your database is limited in terms of multiple connections. Because normally a SQL database is supposed to have more than one active connection.
(Contact your network provider)
Would you mind posting some of your queries? The MySQL documentation has this to say about it:
https://dev.mysql.com/doc/refman/5.7/en/error-lost-connection.html
TL;DR:
Network problems; are any of your boxes renewing leases
periodically, or experiencing other network connection errors
(netstat / ss), firewall timeouts, etc. Not sure how managed your
hosts are by cloud66....
Query timed out. This can happen if you've got commands backed up
behind blocking statements (eg, alters/locking backups on MyISAM
tables). How simple are your queries? No cartesian products in-play?
EXPLAIN query could help.
Exceeding MAX_PACKET_SIZE. Are you storing pictures, video content, etc.?
There are lots of possibilities here, and without more information, will be difficult to pinpoint this.
Would look first at mysql_error.log, then work your way from the DB server back to your application.
UPDATE: this didn't work.
Heres the solution, special thanks to #Myst for pointing out that forking can cause issues, I had no idea to look at this particular code. As the errors seemed random because we forked in this fashion in several places.
It turns out that when I was forking processes, rails was using the same database connection for all forked processes, This created a situation where when one of the processes (the parent process?) terminated the database connection, the remaining process would have its connection interrupted.
The solution was to change this code:
def recalculate_completion
Process.fork do
if self.course
self.course.user_groups.includes(user:[:events]).each do |ug|
ug.recalculate_completion
end
end
end
end
into this code:
def recalculate_completion
ActiveRecord::Base.remove_connection
Process.fork do
ActiveRecord::Base.establish_connection
if self.course
self.course.user_groups.includes(user:[:events]).each do |ug|
ug.recalculate_completion
end
end
ActiveRecord::Base.remove_connection
end
ActiveRecord::Base.establish_connection
end
Making this change stopped the errors from our servers and everything appears to be working well now. If anyone has any more info as to why this worked I would be happy to hear it, as I would like to have a deeper understanding of this.
Edit: it turns out this didn't work either.... we still got dropped connections but not as often.
If you have query cache enabled, please reset it and it should work.
RESET QUERY CACHE;

What is the purpose of the `KILL QUERY` command?

I am beginner to MySQL and SQL and I am learning these technologies from MySQL and MyISAM websites.
I am learning the KILL command now and have learned how to use KILL CONNECTION. But when I come to learn KILL QUERY from MySQL and MyISAM websites where they simply provided information about KILL QUERY that they terminate query that the specified connection id is executing.
Other user (not me) executes INSERT and DELETE queries but when i have used KILL QUERY by getting the connection id of other user via SHOW PROCESSLIST command, it says
Query OK, 0 rows affected (0.01 sec)
But nothing happen to other user.
I just want to know that what is the exact use of this command. What is the purpose of this KILL QUERY command. Can anyone tell me?
Some useful pointers:
How can I stop a running MySQL query?
MySQL Kill query
How to kill all processes for a Specific user
MySQL Manaul - Kill
You need to have some clarity here KILL will kill the connection, but KILL QUERY will only kill that query and will leave that connection intact.
Really, if you are using KILL QUERY on another users command, this can only really be noticable if their query is running for longer than your Kill Query command, so if it's a slow query, because [most] queries will execute and close within a fraction of a second, so by the time you've KILLed the other users query, their query may well have completed and closed anyway.
I suspect this is what you are seeing, that you're trying to kill a query that closes and is finished before the kill command can execute.
Killing queries seems (from literature) only useful for slow and long running queries, and why this is so should be obvious from the above.
Edit:
(I had this ready to post on my original answer and then took it out as being irrelevant, but seems to be more relevant now due to comments!)
From the MySQL Manual:
Note
You cannot use KILL with the Embedded MySQL Server library because the embedded server merely runs inside the threads of the host application. It does not create any connection threads of its own.
So to answer your question in the comment, I think that you may be running MySQL embedded so your kill calls will not function.

MySQL long_query_time value

I'm debugging a MySQL 5.1.61 database, and I have the long_query_time set in the my.cnf file to 10. Slow queries are being logged to a database table.
However, it's logging queries that take a fraction of a second.
In fact, my queries being logged are so fast, the query_time field in mysql shows "00:00:00" for every query logged. Even when I had them logging to a file, they showed query times in the range of "Query_time: 0.004763"
I know that my configuration file is being read, because all my other changes have worked.
From all the documentation I've read, long_query_time should be seconds. Is there something else I need to do for that setting to stick?
Do those queries have indexes? If not, then that's probably why they're being logged.
Before MySQL 4.1, if you also use --log-long-format when logging slow queries, queries that are not using indexes are logged as well. Starting with MySQL 4.1, logging of queries not using indexes for row lookups is enabled using the --log-queries-not-using-indexes option instead. The --log-long-format is deprecated as of MySQL 4.1, when --log-short-format was introduced, which causes less information to be logged. (The long log format is the default setting since version 4.1.) (>>)
I believe you just forgot to restart your Mysql after editing 'my.cnf' file?
sudo /etc/init.d/mysqld restart
or
sudo service mysql restart

mysql loggin slow queries

I ran the mysqltuner script recently and i noticed around 5000 joins done without indexes, this has to be reduced to a small value.
There is an option that allows us to log these queries in mysql
i have added the following lines under [mysqld] section of my.cnf
log-queries-not-using-indexes
log_slow_queries=/var/log/mysqld.slow.log
But the logs still remains empty, how can i get the logging to work in order to optimize those queries
Did you restart MySQL after doing this?
sudo service mysql restart
If you didn't, it won't log anything. I've also wondered myself if there's a delay in when it actually logs queries. Give it time, the logs will show up.