MySQL Query with LARGE number of records gets Killed - mysql

I run the following query from my shell :
mysql -h my-host.net -u myuser -p -e "SELECT component_id, parent_component_id FROM myschema.components comp INNER JOIN my_second_schema.component_parents related_comp ON comp.id = related_comp.component_id ORDER BY component_id;" > /tmp/IT_component_parents.txt
The query runs for a LONG time and then gets KILLED.
However if I add LIMIT 1000, then the query runs till the end and output is written in file.
I further investigated and found (using COUNT(*)) that the total number of records that would be returned are 239553163.
Some information about my server is here:
MySQL 5.5.27
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+----------------------------+----------+
Here's STATE of the query as I monitored :
copying to tmp table on disk
sorting results
sending data
writing to net
sending data
writing to net
sending data
writing to net
sending data ...
KILLED
Any guesses what's wrong here ?

The mysql client probably runs out of memory.
Use the --quick option to not buffer results in memory.

What is wrong is that you are returning 239 553 163 rows of data! Don't be surprised it it takes a lot of time to process. Actually, the longest part might very well be sending the result set back to your client.
Reuduce the result set (do you really need all these rows?). Or try to output the data in smaller batches:
mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 0" >> dump.txt
mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 10000" >> dump.txt

Assuming you mean 8 hours when you say a long time, the value 28800 for your wait_timeout causes the connection to drop with no further activity in 28,800 seconds, i.e. 8 hours. If you can't optimize the statement to run in less than 8 hours, you should increase this value.
See this page for further information on the wait_timeout variable.
The interactive_timeout variable is used for interactive client connections, so if you run long queries from an interactive session, that's the one you need look at.

You may want to utilize OUTFILE mechanizm if you are going to dump large amounts of data. That or mysql_dump will be much more efficient (and OUTFILE got the benefit of not locking-down the table).

You said in a comment that your MySQL instance is on RDS. This means you can't be running the query from the same host, since you can't log into an RDS host. I guess you might be doing this query over the WAN from your local network.
You're most likely having trouble because of a slow network. Your process state frequently showing "writing to net" makes me think this is your bottleneck.
Your bottleneck might also be the sorting. Your sort is writing to a temp table, and that can take a long time for a result set that large. Can you skip the ORDER BY?
Even so, I wouldn't expect the query to be killed even if it runs for 3100 seconds or more. I wonder if your DBA has some periodic job killing long-running queries, like pt-kill. Ask your DBA.
To reduce network transfer time, you could try using the compression protocol. You can use the --compress or -C flags to the mysql client for this (see https://dev.mysql.com/doc/refman/5.7/en/mysql-command-options.html#option_mysql_compress)
On a slow network, compression can help. For example, read about some comparisons here: https://www.percona.com/blog/2007/12/20/large-result-sets-vs-compression-protocol/
Another alternative is to run the query from an EC2 spot instance running in the same AZ as your RDS instance. The network between those two instances will be a lot faster, so it won't delay your data transfer. Save the query output to a file on the EC2 spot instance.
Once the query result is saved on your EC2 instance, you can download it to your local machine, using scp or something, which should be more tolerant of slow networks.

Related

Increase MySQL max_connection on Lightsail (not RDS) database

I have a database created in Lightsail (not RDS, just Lightsail>Databases>Create database). I am trying to increase its max_connections number from 150 to 500 by connecting to it remotely, but I am getting the following error:
Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
Is there a way for me to achieve this on Lightsail?
Database instance info:
High availability MySQL database (8.0.11)
2 GB RAM
1 vCPU
80 GB SSD
It sound like you are attempting to set the parameter through SQL?
For lightsail databases, you need to follow these instructions and use AWS CLI: https://lightsail.aws.amazon.com/ls/docs/en_us/articles/amazon-lightsail-updating-database-parameters
(if I'm wrong, please let us know what command you are running to generate the error you are seeing above)
AWS RDS and lighsail wil automatically inject your proper amount of max_connections based on your memory installed. With 2 gigs, you get around 66*2=132
It will just overwhelm even RDS if you make too many connections, as they require more RAM for each one.
"parameterName": "max_connections",
"parameterValue": "{DBInstanceClassMemory/12582880}"
mysql> show variables like "max_connections";
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 66 |
+-----------------+-------+
# pip3 install awscli --upgrade --user
# .local/bin/aws lightsail get-relational-database-parameters --relational-database-name <your given name>
# .local/bin/aws lightsail update-relational-database-parameters --relational-database-name <your given name> --parameters "parameterName=explicit_defaults_for_timestamp,parameterValue=0,applyMethod=pending-reboot"
which is required for MySQL 5.7
OR for your situation
# .local/bin/aws lightsail update-relational-database-parameters --relational-database-name <your given name> --parameters "parameterName=max_connections,parameterValue=500,applyMethod=pending-reboot"
If your region is us-west-2a, then remove the "a" from the .aws/config
[default]
region = us-west-2
output = json

Slow write of database using `mysqldump `

I'm trying to automate a mysql dump of all databases from an Azure Database for MySQL Server. Current size of databases:
mysql> SELECT table_schema "DB Name", Round(Sum(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB"
FROM information_schema.tables GROUP BY table_schema;
+--------------------+---------------+
| DB Name | DB Size in MB |
+--------------------+---------------+
| db1 | 278.3 |
| db2 | 51.8 |
| information_schema | 0.2 |
| mysql | 8.9 |
| performance_schema | 0.0 |
| db3 | 43.3 |
| sys | 0.0 |
+--------------------+---------------+
7 rows in set (31.80 sec)
I have a python script, on a different VM, that calls mysqldump to dump all of these into a file. However, I'm running into an issue with db1. It is being dumped to a file but it is very slow, less than ~4MB in 30min. However db2 and db3 are dumped almost immediately, in seconds.
I have tried all of the following options and combinations to see if the write speed changes, but it doesn't:
--compress
--lock-tables (true / false)
--skip-lock-tables
--max-allowed-packet (512M)
--quick
--single-transaction
--opt
I'm currently not even using the script, just running the commands in a shell, with the same result.
mysqldump -h <host> -P <port> -u'<user>' -p'<password>' db1 > db1.sql
db1 has ~500 tables.
I understand that it is bigger than db2 and db3 but it's not by that much, and I'm wondering if anyone knows what could be the issue here?
EDIT
After these helpful answers and google research showed that the database is most likely fine, I run test by duplicating the db1 database on the server into a test database and then deleting tables one by one to decrease the size. And at around 50MB the writes became instant like the other databases. This leads me to believe that there is some throttling going on in Azure because the database is just fine and we will take it up with their support team. I have also found a lot of posts on google complaining about Azure database speeds in general.
In the meantime, I changed the script to ignore large databases. And we will try to move the databases to a SQL Server provided by Azure or a simple VM with a mysql server on it to see where we can get a better performance.
It's possible it's slow on the MySQL Server end, but it seems unlikely. You can open a second shell window, connect to MySQL and use SHOW PROCESSLIST or SHOW ENGINE INNODB STATUS to check for stuck queries or locks.
It's also possible it's having trouble writing the data to db1.sql, if you have very slow storage. But 4MB is 30min. is ridiculous. Make sure you're saving to storage local to the instance you're running mysqldump on. Don't save to remote storage. Also be careful if the storage volume to which you're writing the dump has other heavy I/O traffic saturating it, this could slow down writes.
Another way you can test for slow data writes is to try mysqldump ... > /dev/null and if that is fast, then it's a pretty good clue that the slowness is the fault of the disk writes.
Finally, there's a possibility that the network is causing the slowness. If saving the dump file to /dev/null is still slow, I'd suspect the network.
An answer in
https://serverfault.com/questions/233963/mysql-checking-permission-takes-a-long-time suggests that slowness in "checking permissions" might be caused by having too much data in the MySQL grant tables (e.g. mysql.user). If you have thousands of user credentials, this could be the cause. You can try eliminating these entries (and run FLUSH HOSTS afterwards).
Create a backup from your database first. After that, try this:
mysqlcheck
More info about this: mysqlcheck

Maraidb showing passwords in the log files

Looking at the mariadb logs, I am seeing all the passwords logged in as clear text like IDENTIFIED BY . Is there any option or way yo suppress this. This is a huge security risk.
Any help is appreciated.
MariaDB [(none)]> SHOW VARIABLES LIKE "%version%";
+-------------------------+-----------------------------------+
| Variable_name | Value |
+-------------------------+-----------------------------------+
| innodb_version | 5.5.41-MariaDB-37.0 |
| protocol_version | 10 |
| slave_type_conversions | |
| version | 5.5.42-MariaDB-wsrep |
| version_comment | MariaDB Server, wsrep_25.11.r4026 |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
+-------------------------+-----------------------------------+
If you use audit plug-in v1.2 or newer, then mariadb masks the passwords in certain queries. Specifically:
Since version 1.2.0, passwords have been replaced by asterisks in the logs for certain queries, including:
GRANT, CREATE USER, CREATE MASTER, CREATE SERVER, ALTER SERVER
Passwords given with the PASSWORD() and OLD_PASSWORD() functions in
DML statements will still be logged as plain text in queries, as will
key strings used with encrypt functions such as ENCODE() and
AES_ENCRYPT().
Furthermore, you can protect the log files via traditional means by restricting access rights, using file system level encryption. Really, only DBAs should have access to server logs and they can pretty much do anything in the db anyway.
The clear text password is not only logged in the MariaDB logs but it might be also logged in the .mysql_history file of the user that connected to MariaDB and performed some
CREATE/GRANT/etc.. IDENTIFIED BY 'some_cleartext_password'
You can find .mysql_history in /home/username or in /root if you connected as root.
Best way to avoid such things to happen is to replace the syntax
CREATE/GRANT/etc.. IDENTIFIED BY 'some_cleartext_password'
with
CREATE/GRANT/etc.. IDENTIFIED BY PASSWORD 'hashed_password'
You can calculate the hashed password either in your application that is calling MariaDB or by using the PASSWORD() function of MariaDB. For example:
SELECT PASSWORD('some_cleartext_password')
Do the above select on another MariaDB/MySQL server if you don't want the above query to be logged, in which case you will end-up with the same problem. :-)

EC2 Amazon Linux AMI MySQL CPU # 62% When Idle?

I am running MySQL on an Amazon Linux AMI. There is nothing connected to it. There are no connections and no other applications running that use MySQL. It is completely idle, but yet, top is reporting that mysql is using 62% of the CPU? Why is this happening and how do I fix it?
Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 97.8%id, 0.0%wa, 0.0%hi, 0.0%si, 1.7%st
Mem: 1738504k total, 390708k used, 1347796k free, 56888k buffers
Swap: 917500k total, 0k used, 917500k free, 229804k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2959 mysql 20 0 466m 39m 5244 S 62.2 2.3 4:00.67 mysqld
1 root 20 0 19252 1504 1212 S 0.0 0.1 0:00.20 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
There are no connections...
mysql> show processlist;
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+-------+------------------+
| 5 | root | localhost | NULL | Query | 0 | NULL | show processlist |
+----+------+-----------+------+---------+------+-------+------------------+
UPDATE:
My issue was definitely related to the Lead Second bug. Kudos to nico-ekito. Thanks!
The only thing I can think of is to inspect what mysqld is really doing using strace, as user root:
strace -p 2959
Normally, strace should block immediately and show you a call to select(), because mysqld should be waiting for connections.
The call should be something like:
select(SOCKETNO, [OTHER_FDs], NULL, NULL, NULL)
especially important is the fourth parameter, which is a timeout timeval. If NULL, it means that mysqld will sleep until someone connects. If not NULL, it means that mysqld will wait for the specified time and then do some maintenance work. A very small timeval might explain the CPU consumption.
I believe that MySQL always employs a NULL (infinite) timeout. It makes sense and this is how the mysqlds I'm able to reach now are behaving.
However, there might be some connection handling issues that prevent select from sleeping again. Check whether this behaviour appears as soon as mysqld starts, or after someone connects.
Closing out this question. My issue was indeed related to the Leap Second fiasco.

Unable to get multiple connection to MySql on Windows 7

I have installed MySql on windows 7 ... issue is i'm unable to get multiple connection to MySql .
If I connect to MySql through command line and at the same time open an other MySql command line client it goes into wait state, as soon as I disconnect the first one later one gets connected.
Because of above issues I'm unable to run tomcat in debug mode as it tries to get more than one connection to MySql in debug mode.
Previously I was using same version of MySql i.e. 5.1 on vista and it was working fine.
when connected with only one MySql Command line "show processlist" results
| 4 | root | localhost:49487 | NULL | Query | 0 | NULL | show processlist
1 row in set (0.00 sec)
and after connnecting with 2nd command line which hangs "show processlist" on the 1st window results
| 4 | root | localhost:49487 | NULL | Query | 0 | NULL | show processlist
| 5 | root | localhost:49518 | NULL | Sleep | 0 | NULL | NULL
2 rows in set (0.00 sec)
I entered following command through command line.
mysql -u root -h localhost -P 3306 -p
it asked me for password and got connected. Then I opened an other command prompt entered the same command it asked for password and hanged. I went back to the previous command line and closed it and the current one got connected. max_connection is 100 in my.ini file and show processlist reutns same result as above.
What is your 'max_connections' setting (show variables like '%max_connections%') and how many connections are currently 'live' on the server (show processlist)?
I'm guessing it's set very low (1 or 2) and between tomcat and your monitor connections you're exceeding the limit.
Raising it would be done via the mysql.ini/mysql.cnf file, wherever it's kept on Windows.
Are you connecting over the network? or a local file socket? You may be locking on the windows equivalent of mysql.sock - not sure if that behavior changed in Win7. Something like:
mysql -u root -h localhost -p 3306
and make sure that my.ini/my.cnf have networking enabled
After too many re installation of Windows I guess i have identified the root cause ... On every fresh installation MySql use to work fine but after a while I use to get stuck with this issue.
The cause was my voip messenger "Wizton" after installing it MySql work fine but when i restart my machine ... same Connection issue.
But wizton was working perfectly fine with Vista Business .. don't no what happens in Windows 7.