How PHPMyAdmin get query statics? - mysql

Dear friends: I'm developing a php server monitor for a client. One of the monitor's sections is related to MySQL.
In PHPmyadmin the section Server Status > Status queries show an amount of queries. I thought that was extracted from the "SHOW STATUS" mysql command. But... Differs!
When i go in PHPmyadmin to the section Server Status > Server Status Variables, the system displays the same values that "Status Queries" section.
But when i get the results of "SHOW STATUS" command, the values is not the same".
My English level is too poor to explain the case correctly. So, I will show an example:
In Server Status > Status Queries i can see, in the table:
Sentences | # | per hour| %
---------------------------------
select | 365 | 51.4 |25.29
set option | 266 | 37.4 |18.43
When i go to Server Status > Server Status Variables, i can see:
Variable | Value | Description
---------------------------------
Com select | 365 | Blah Blah....
Com set Option | 266 | Blah Blah....
But if i run "SHOW STATUS", i obtain:
Variable | Value
-----------------------------
com_select | 1
com_set_Option | 2
And, in this point, my brain explode....
Can do you enlighten me?
PD: Again, Sorry if my English is too poor...

Use:
SHOW GLOBAL STATUS;
To get the server status values as shown in PhpMyAdmin
With a GLOBAL modifier, the statement displays the global status values. A global status variable may represent status for some aspect of the server itself (for example, Aborted_connects), or the aggregated status over all connections to MySQL (for example, Bytes_received and Bytes_sent). If a variable has no global value, the session value is displayed.
With a SESSION modifier, the statement displays the status variable values for the current connection. If a variable has no session value, the global value is displayed. LOCAL is a synonym for SESSION.
If no modifier is present, the default is SESSION.

Related

Monitoring progress of a SQL script with many UPDATEs in MariaDB

I'm running a script with several million update statements like this:
UPDATE data SET value = 0.9234 WHERE fId = 47616 AND modDate = '2018-09-24' AND valueDate = '2007-09-01' AND last_updated < '2018-10-01';
fId, modDate and valueDate are the 3 components of the data table's composite primary key.
I initially ran this with AUTOCOMMIT=1 but I figured it would speed up if I set AUTOCOMMIT=0 and wrapped the transactions into blocks of 25.
In autocommit mode, I used SHOW PROCESSLIST and I'd see the UPDATE statement in the output, so from the fId foreign key, I could tell how far the script had progressed.
However without autocommit, watching it running now, I haven't seen anything with SHOW PROCESSLIST, just this:
610257 schema_owner_2 201.177.12.57:53673 mydb Sleep 0 NULL 0.000
611020 schema_owner_1 201.177.12.57:58904 mydb Query 0 init show processlist 0.000
The Sleep status makes me paranoid that other users on the system are blocking the updates, but if I run SHOW OPEN TABLES I'm not sure whether there's a problem:
MariaDB [mydb]> SHOW OPEN TABLES;
+----------+----------------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+----------------+--------+-------------+
| mydb | data | 2 | 0 |
| mydb | forecast | 1 | 0 |
| mydb | modification | 0 | 0 |
| mydb | data3 | 0 | 0 |
+----------+----------------+--------+-------------+
Is my script going to wait forever? Should I go back to using autocommit mode? Is there any way to see how far it's progressed? I guess I can inspect the data for the updates but that would be laborious to put together.
Check for progress by actually checking the data.
I assume you are doing COMMIT?
It is reasonable to see nothing -- each UPDATE will take very few milliseconds; there will be Sleep time between UPDATEs.
Time being 0 is your clue that it is progressing.
There won't necessarily be any clue in the PROCESSLIST of how far it has gotten.
You could add SELECT SLEEP(1), $fid; in the loop, where $fid (or whatever) is the last UPDATEd row id. That would slow down the progress by 1 second per 25 rows, so maybe you should do groups of 100 or 500.

monitoring MySQL slave status

I'm using Nagios with the mysql_check_health pugin to monitor my MySQL databases. I need to be able to return a numeric value to my plugin from an sql query to tell me if the replicated database is up and running.
so here is what I have...
SHOW GLOBAL STATUS like 'slave_running'
will return:
Variable_name Value
Slave_running OFF/ON
I need to retrun a numeric value from a simple query for the plugin, anyone have any ideas... my thought was to return 3-LENGTH(Slave_running) that would == 1 for ON 0 for off but having trouble using the return values in that way.
The global status variable will be accessible in the information_schema.GLOBAL_STATUS table, from which you can query just the value. That makes it easy to conditionally convert it to a 0 or 1 based on the ON/OFF state.
For example:
> SELECT VARIABLE_VALUE
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME = 'slave_running';
+----------------+
| VARIABLE_VALUE |
+----------------+
| ON |
+----------------+
So to convert that into a zero or one, there are a few possibilities. MySQL will treat booleans as 0 or 1, so you can just compare it = 'ON'
Wrapping the above in a subquery (since it returns one value) and comparing to 'ON':
> SELECT (
'ON' = (SELECT VARIABLE_VALUE
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME = 'slave_running')
) AS state;
+-------+
| state |
+-------+
| 1 |
+-------+
Or a similar expression formatted as a CASE:
> SELECT CASE WHEN (
SELECT VARIABLE_VALUE
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME = 'slave_running') = 'ON' THEN 1
ELSE 0 END AS state;
+-------+
| state |
+-------+
| 1 |
+-------+
In both of the above, I aliased the result as 'state', but you could use any column alias name to read output, replacing AS state accordingly.
What's already out there?
I couldn't help but wonder if there was already a Nagios plugin built for this purpose, and found this as a possibility.
I would strongly consider using:
SHOW SLAVE STATUS
As your informational query. This gives you a few more key fields to monitor on.
From this, you might consider alarming on the following fields:
Slave_IO_Running: Yes / No (tells you if binary log feed from master is working)
Slave_SQL_Running: Yes / No (tells you if slave's SQL execution thread is runing)
Seconds_Behind_Master: INT value (you should set appropriate low value here to alarm off of)
The Slave_running global status is OK for determining overall state (that value is only 'On' when both IO thread and SQL thread on slave are running), but may not give you what you want in terms of more granular monitoring. For example, an interruption in the IO thread may be considered a higher severity event than the SQL thread breaking (and may have totally different recovery scenarios). The Seconds_Behind_Master may also be key to monitor, as you might have both IO and SQL threads happily running, while not realizing that the slave can't keep up for some reason.
If you need to convert to INT value results for slave status values, you could do something like:
SELECT
(CASE WHEN a.Slave_IO_Running = 'Yes' THEN 1 ELSE 0 END)
AS Slave_IO_Running,
(CASE WHEN a.Slave_SQL_Running = 'Yes' THEN 1 ELSE 0 END)
AS Slave_SQL_Running,
a.Seconds_Behind_Master AS Seconds_Behind_Master
FROM (SHOW SLAVE STATUS) AS a

How to kill MySQL connections

I'm building a website with MySQL. I'm using TOAD for MySQL and suddenly I can't connect to the database as I'm getting an error:
"Too many connections"
Is there any way in Toad for MySQL to view existing connections to be able to kill them or simple close all connections all together?
No, there is no built-in MySQL command for that. There are various tools and scripts that support it, you can kill some connections manually or restart the server (but that will be slower).
Use SHOW PROCESSLIST to view all connections, and KILL the process ID's you want to kill.
You could edit the timeout setting to have the MySQL daemon kill the inactive processes itself, or raise the connection count. You can even limit the amount of connections per username, so that if the process keeps misbehaving, the only affected process is the process itself and no other clients on your database get locked out.
If you can't connect yourself anymore to the server, you should know that MySQL always reserves 1 extra connection for a user with the SUPER privilege. Unless your offending process is for some reason using a username with that privilege...
Then after you can access your database again, you should fix the process (website) that's spawning that many connections.
mysql> SHOW PROCESSLIST;
+-----+------+-----------------+------+---------+------+-------+---------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+------+-----------------+------+---------+------+-------+----------------+
| 143 | root | localhost:61179 | cds | Query | 0 | init | SHOW PROCESSLIST |
| 192 | root | localhost:53793 | cds | Sleep | 4 | | NULL |
+-----+------+-----------------+------+---------+------+-------+----------------+
2 rows in set (0.00 sec)
mysql> KILL 192;
Query OK, 0 rows affected (0.00 sec)
USER 192 :
mysql> SELECT * FROM exept;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> SELECT * FROM exept;
ERROR 2013 (HY000): Lost connection to MySQL server during query
While you can't kill all open connections with a single command, you can create a set of queries to do that for you if there are too many to do by hand.
This example will create a series of KILL <pid>; queries for all some_user's connections from 192.168.1.1 to my_db.
SELECT
CONCAT('KILL ', id, ';')
FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE `User` = 'some_user'
AND `Host` = '192.168.1.1'
AND `db` = 'my_db';
I would recommend checking the connections to show the maximum thread connection is
show variables like "max_connections";
sample
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 13 |
+-----------------+-------+
1 row in set
Then increase it by example
set global max_connections = 500;
In MySQL Workbench:
Left-hand side navigator > Management > Client Connections
It gives you the option to kill queries and connections.
Note: this is not TOAD like the OP asked, but MySQL Workbench users like me may end up here
As above mentioned, there is no special command to do it. However, if all those connection are inactive, using 'flush tables;' is able to release all those connection which are not active.

How to see full query from SHOW PROCESSLIST?

When I issue SHOW PROCESSLIST query, only the first 100 characters of the running SQL query are returned in the info column.
Is it possible to change MySQL config or issue a different kind of request to see complete query (the queries I'm looking at are longer than 100 characters)
SHOW FULL PROCESSLIST
If you don't use FULL, "only the first 100 characters of each statement are shown in the Info field".
When using phpMyAdmin, you should also click on the "Full texts" option ("← T →" on top left corner of a results table) to see untruncated results.
Show Processlist fetches the information from another table. Here is how you can pull the data and look at 'INFO' column which contains the whole query :
select * from INFORMATION_SCHEMA.PROCESSLIST where db = 'somedb';
You can add any condition or ignore based on your requirement.
The output of the query is resulted as :
+-------+------+-----------------+--------+---------+------+-----------+----------------------------------------------------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+-------+------+-----------------+--------+---------+------+-----------+----------------------------------------------------------+
| 5 | ssss | localhost:41060 | somedb | Sleep | 3 | | NULL |
| 58169 | root | localhost | somedb | Query | 0 | executing | select * from sometable where tblColumnName = 'someName' |
See full query from SHOW PROCESSLIST :
SHOW FULL PROCESSLIST;
Or
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
I just read in the MySQL documentation that SHOW FULL PROCESSLIST by default only lists the threads from your current user connection.
Quote from the MySQL SHOW FULL PROCESSLIST documentation:
If you have the PROCESS privilege, you can see all threads.
So you can enable the Process_priv column in your mysql.user table. Remember to execute FLUSH PRIVILEGES afterwards :)
If one want to keep getting updated processes (on the example, 2 seconds) on a shell session without having to manually interact with it use:
watch -n 2 'mysql -h 127.0.0.1 -P 3306 -u some_user -psome_pass some_database -e "show full processlist;"'
The only bad thing about the show [full] processlist is that you can't filter the output result. On the other hand, issuing the SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST open possibilities to remove from the output anything you don't want to see:
SELECT * from INFORMATION_SCHEMA.PROCESSLIST
WHERE DB = 'somedatabase'
AND COMMAND <> 'Sleep'
AND HOST NOT LIKE '10.164.25.133%' \G
SHOW FULL PROCESSLIST
This shows the full processlist with more info.

Profile Stored procedures in MySQL

I am working with MySQL and using stored procedures. I have a profiling tool that I am using to profile the code that communicates with MySQL through the stored procedures and I was wondering if there was a tool or capability within MySQL client to profile stored procedure executions. What I have in mind is something that's similar to running queries with profiling turned on. I am using MySQL 5.0.41 on Windows XP.
Thanks in advance.
There is a wonderfully detailed article about such profiling: http://mablomy.blogspot.com/2015/03/profiling-stored-procedures-in-mysql-57.html
As of MySQL 5.7, you can use performance_schema to get informations about the duration of every statement in a stored procedure. Simply:
1) Activate the profiling (use "NO" afterward if you want to disable it)
UPDATE performance_schema.setup_consumers SET ENABLED="YES"
WHERE NAME = "events_statements_history_long";
2) Run the procedure
CALL test('with parameters', '{"if": "needed"}');
3) Query the performance schema to get the overall event informations
SELECT event_id,sql_text,
CONCAT(TIMER_WAIT/1000000000,"ms") AS time
FROM performance_schema.events_statements_history_long
WHERE event_name="statement/sql/call_procedure";
| event_id | sql_text | time |
|2432 | CALL test(...) | 1726.4098ms |
4) Get the detailed informations of the event you want to profile
SELECT EVENT_NAME, SQL_TEXT,
CONCAT(TIMER_WAIT/1000000000,"ms") AS time
FROM performance_schema.events_statements_history_long
WHERE nesting_event_id=2432 ORDER BY event_id;
| EVENT_NAME | SQL_TEXT | time |
| statement/sp/stmt | ... 1 query of the procedure ... | 4.6718ms |
| statement/sp/stmt | ... another query of the procedure ... | 4.6718ms |
| statement/sp/stmt | ... another etc ... | 4.6718ms |
This way, you can tell which query takes the longest time in your procedure call.
I don't know any tool that would turn this resultset into a KCachegrind friendly file or so.
Note that this should not be activated on production server (might be a performance issue, a data size bump, and since performance_schema.events_statements_history_long holds the procedure's parameters values, then it might be a security issue [if procedure's parameter is a final user email or password for instance])
You can turn on the slow query logging within MySQL.
Take a look at this other SO question:
MYSQL Slow Query
Depending on which version, you may actually be able to set the value to zero, so every single query in the DB is shown in the slow query log.
See here for additional details:
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_long_query_time