0% found this document useful (0 votes)
35 views

MySQL and MariaDB Chatsheet For DBA Queries-3

Jsjhsjsjsjjsjsjbbbhbcghhj

Uploaded by

ROHIT SELVAM6
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views

MySQL and MariaDB Chatsheet For DBA Queries-3

Jsjhsjsjsjjsjsjbbbhbcghhj

Uploaded by

ROHIT SELVAM6
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

MySQL / MariaDB SQL Queries

This document belongs to complete DB SQL Queries .

Database Size
Table Size
All Objectes Rows count
SHOW Commands with few Parameters
Index Related
Processlist and Queries
Killing the process / Sessions by using concatination Script
MySQL Users information SQL Queries
CHARSET and COLLATIONS
Troubleshooting Locks and Waits
InnoDB related DB Queries
Performance_schema Related Database Queries
WATCH Commands
Top Queries for Security Checking in MySQL
Connections
InnoDB Table Fragmentation and Defragmentation, Free Space, Within MySQL Server
Notes
Types of fragmentation
Free space
Combined defragmentation for all causes
Fragmentation within the shared tablespace, mainly if not using innodb_file_per_table
Fragmentation within the filesystem when using innodb_file_per_table
Encryption Queries
MySQL Transaction Reporting
Report latest query for transactions active longer than 1 second
Report transaction summary
Report transaction history
Report basic metrics for committed transactions
All tables rows count by using Store Procedure

Database Size
Description SQL Statement - Queries

Database Size by DB wise SELECT table_schema AS "Database", ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024,
2) AS "Size (GB)" FROM information_schema.TABLES GROUP BY table_schema;

All Databases together in SELECT table_schema "DB Name",ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024 , 1)
Single Column "DB Size in GB" FROM information_schema.tables;

Table Size
Description SQL Statement - Queries
Table Size in SELECT table_name AS Table Name , ROUND(((data_length + index_length) / 1024 / 1024 / 1024), 2) AS Size
given Daatabase in GB FROM information_schema.tables WHERE table_schema = 'your_database_name' ORDER BY
Name (data_length + index_length) DESC;

All Objectes Rows count


Description SQL Statement - Queries

Views Count SELECT count(*) from information_schema.views;

Stored Procedure Count SELECT count(*) from information_schema.routines where routine_type='procedure';

SELECT COUNT(*), ROUTINE_NAME FROM information_schema.ROUTINES WHERE


ROUTINE_TYPE='PROCEDURE' GROUP BY ROUTINE_NAME;

SELECT ROUTINE_SCHEMA,ROUTINE_NAME,ROUTINE_TYPE from information_schema.ROUTINES


where ROUTINE_TYPE='PROCEDURE';

Events Count SELECT count(*) from information_schema.events;

Total Number of Tables SELECT count(*) AS TOTAL_NUMBER_OF_TABLES FROM INFORMATION_SCHEMA.TABLES;

Triggers Count SELECT count(*) from information_schema.triggers;

Functions Count SELECT COUNT(*), ROUTINE_NAME FROM information_schema.ROUTINES WHERE


ROUTINE_TYPE = 'FUNCTION' and ROUTINE_SCHEMA = '<DBNAME>' GROUP BY ROUTINE_NAME;

Table Count SELECT IFNULL(table_schema,'Total') "Database",Table_Count FROM (SELECT COUNT(1)


Table_Count,table_schema FROM information_schema.tables WHERE table_schema NOT IN
('information_schema','mysql') GROUP BY table_schema WITH ROLLUP) A ORDER BY Table_Count;

SELECT TABLE_NAME, SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE


TABLE_SCHEMA = '<DBNAME>' GROUP BY TABLE_NAME;

Mysql Show All Schema SELECT OBJECT_TYPE,OBJECT_SCHEMA,OBJECT_NAME FROM (SELECT 'TABLE' AS


Objects OBJECT_TYPE,TABLE_NAME AS OBJECT_NAME,TABLE_SCHEMA AS OBJECT_SCHEMA FROM
information_schema.TABLES UNION SELECT 'VIEW' AS OBJECT_TYPE,TABLE_NAME AS
OBJECT_NAME,TABLE_SCHEMA AS OBJECT_SCHEMA FROM information_schema.VIEWS UNION
SELECT 'INDEX[Type:Name:Table]' AS OBJECT_TYPE,CONCAT (CONSTRAINT_TYPE,' :
',CONSTRAINT_NAME,' : ',TABLE_NAME) AS OBJECT_NAME,TABLE_SCHEMA AS
OBJECT_SCHEMA FROM information_schema.TABLE_CONSTRAINTS UNION
SELECT ROUTINE_TYPE AS OBJECT_TYPE,ROUTINE_NAME AS
OBJECT_NAME,ROUTINE_SCHEMA AS OBJECT_SCHEMA FROM information_schema.ROUTINES
UNION SELECT 'TRIGGER[Schema:Object]' AS OBJECT_TYPE,CONCAT (TRIGGER_NAME,' :
',EVENT_OBJECT_SCHEMA,' : ',EVENT_OBJECT_TABLE) AS OBJECT_NAME,TRIGGER_SCHEMA
AS OBJECT_SCHEMA FROM information_schema.triggers) R WHERE R.OBJECT_SCHEMA =
'<DBNAME>';

Or

SELECT DB,OBJECT,COUNT(OBJECT_NAME) as cnt from


(
SELECT COUNT(),TABLE_TYPE FROM information_schema.TABLES WHERE
TABLE_SCHEMA='<dbname>' GROUP BY TABLE_TYPE union all
SELECT COUNT(),TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA =
'<dbname>' GROUP BY TABLE_NAME union all
SELECT COUNT() FROM information_schema.ROUTINES WHERE ROUTINE_TYPE='PROCEDURE'
and ROUTINE_SCHEMA = '<dbname>' union all
SELECT COUNT() FROM information_schema.ROUTINES WHERE ROUTINE_TYPE='FUNCTION' and
ROUTINE_SCHEMA = '<dbname>' union all
SELECT COUNT() FROM information_schema.EVENTS WHERE EVENT_SCHEMA= '<dbname>' union
all
SELECT COUNT() FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA='<dbname>'
) FINAL GROUP BY DB,OBJECT;

Get the report - List of (1)


Objectes along with count
set @table_Schema='<dbname>';
of each object [ Table .
View . Stored Procedure , select db, object, sum(cnt) as cnt from (
Trgger , Functions ] select @table_schema as db, 'tables' as object, count(table_name) as cnt from
information_schema.tables where table_schema = @table_schema and table_type = 'BASE TABLE'
union all
select @table_schema as db, 'views' as object, count(table_name) as cnt from
information_schema.tables where table_schema = @table_schema and table_type != 'BASE TABLE'
union all
select @table_schema as db, 'routine' as object, count(routine_name) as cnt from
information_schema.routines where routine_schema = @table_schema
union all
select @table_schema as db, 'trigger' as object, count(trigger_name) as cnt from
information_schema.triggers where TRIGGER_SCHEMA = @table_schema
) final group by db, object;

Or

SELECT 'TABLE' AS DB, TABLE_TYPE AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name


FROM information_schema.TABLES
WHERE TABLE_SCHEMA='<dbname'
GROUP BY TABLE_TYPE
UNION ALL
SELECT 'VIEW' AS DB, TABLE_NAME AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = '<dbname'
GROUP BY TABLE_NAME
UNION ALL
SELECT 'PROCEDURE' AS DB, 'PROCEDURE' AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name
FROM information_schema.ROUTINES
WHERE ROUTINE_TYPE='PROCEDURE' AND ROUTINE_SCHEMA = '<dbname'
UNION ALL
SELECT 'FUNCTION' AS DB, 'FUNCTION' AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name
FROM information_schema.ROUTINES
WHERE ROUTINE_TYPE='FUNCTION' AND ROUTINE_SCHEMA = '<dbname'
UNION ALL
SELECT 'EVENT' AS DB, 'EVENT' AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA= '<dbname'
UNION ALL
SELECT 'TRIGGER' AS DB, 'TRIGGER' AS OBJECT, COUNT() AS cnt, '<dbname' AS DB_name
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA='<dbname';

Or

SELECT
CASE
WHEN table_type IS NOT NULL THEN 'TABLE'
WHEN routine_type = 'PROCEDURE' THEN 'PROCEDURE'
WHEN routine_type = 'FUNCTION' THEN 'FUNCTION'
WHEN event_type IS NOT NULL THEN 'EVENT'
WHEN trigger_type IS NOT NULL THEN 'TRIGGER'
END AS DB,
COALESCE(table_type, routine_type, event_type, trigger_type) AS OBJECT,
COUNT(*) AS cnt,
'<dbname>' AS DB_name
FROM (
SELECT TABLE_TYPE AS table_type, NULL AS routine_type, NULL AS event_type, NULL AS
trigger_type
FROM information_schema.TABLES
WHERE TABLE_SCHEMA='<dbname>'
UNION ALL
SELECT NULL, ROUTINE_TYPE, NULL, NULL
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA='<dbname>'
UNION ALL
SELECT NULL, NULL, 'EVENT', NULL
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA='<dbname>'
UNION ALL
SELECT NULL, NULL, NULL, 'TRIGGER'
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA='<dbname>'
) AS combined_data
GROUP BY COALESCE(table_type, routine_type, event_type, trigger_type);

1 Note : - MariaDB has some functions that are not present in MySQL, like JSON_DETAILED, which is called JSON_PRET
2 in MySQL 8.0.
3
4 The list of those functions is present in MariaDB’s documentation, however check it twice as some information
5 regarding MySQL 8.0 is sometimes outdated, especially on this page, (like invisible columns, virtual columns,
6 wait, intersect, except, …).
7
8 This is not a blocking factor for migration, unless these functions are present in the default values of columns
9 But of course, if your application uses some of these functions, it may be necessary to modify it to use the
10 appropriate one in MySQL 8.0.
11
12 To illustrate this, let’s use the ADD_MONTHS function.
13
14 First let’s see if we have this function as default for some columns:
15
16 SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS WHERE COLUMN_NAME LIKE 'ADD_MONTHS%';
17 +------------+-------------+
18 | TABLE_NAME | COLUMN_NAME |
19 +------------+-------------+
20 | date1 | ADD_MONTHS |
21 +------------+-------------+
22 1 row in set (0.06 sec)
23
24 Great !…. But I’m sure I’ve created a table with that specific function as default. This is what I did:
25
26 ALTER TABLE t6 ADD COLUMN future DATETIME DEFAULT (ADD_MONTHS(NOW(), 2));
27
28 In fact, several functions are acting like aliases. If we check the output of SHOW CREATE TABLE statement,
29 we can see that the function is translated:
30
31 SHOW CREATE TABLE t6\G
32 *************************** 1. row ***************************
33 Table: t6
34 Create Table: CREATE TABLE t6 (
35 id int(11) NOT NULL DEFAULT nextval(mydatabase.s3),
36 b int(11) DEFAULT NULL,
37 future datetime DEFAULT (current_timestamp() + interval 2 month),
38 PRIMARY KEY (id)
39 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
40 1 row in set (0.000 sec)

SHOW Commands with few Parameters


SQL Statement - Queries

SELECT VERSION(); SHOW VARIABLES LIKE 'lower_case_table_names'; SHOW VARIABLES LIKE '%char%'; SHOW
VARIABLES LIKE '%collat%'; SHOW DATABASES;

show variables like '%slow_query%'; show variables like 'log_bin_trust_function_creators'; show variables like 'long_query_time';

SELECT SYSDATE() as Current_Date_And_Time ;

Index Related
Description SQL Statement - Queries

Index Count SELECT COUNT(*), INDEX_NAME FROM information_schema.STATISTICS WHERE


TABLE_SCHEMA = '<DBNAME>' GROUP BY INDEX_NAME;

Duplicate index checking SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, group_concat(INDEX_NAME) duplic8_UK,


COLUMN_NAMES FROM (SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME,
GROUP_CONCAT(COLUMN_NAME ORDER BY COLUMN_NAME SEPARATOR ',') AS
COLUMN_NAMES
FROM information_schema.STATISTICS WHERE NON_UNIQUE = 0 AND
INDEX_NAME!='PRIMARY' AND INDEX_TYPE = 'BTREE' GROUP BY TABLE_SCHEMA,
TABLE_NAME, INDEX_NAME) X group by TABLE_SCHEMA, TABLE_NAME, COLUMN_NAMES
having count(*)> 1;

Find tables without PK SELECT t.table_schema,t.table_name,t.engine FROM information_schema.tables t JOIN


information_schema.columns c ON t.table_schema=c.table_schema AND
t.table_name=c.table_name WHERE t.table_schema NOT IN ('mysql', ‘information_schema', ‘sys',
‘performance_schema') AND t.table_type = ‘BASE TABLE' GROUP BY
t.table_schema,t.table_name, t.engine HAVING SUM(IF(column_key IN ('PRI','UNI'), 1,0)) = 0;

Find tables with non-integer SELECT table_schema, table_name, column_name, data_type, character_maximum_length FROM
PK’s information_schema.columns WHERE column_key IN ('PRI','UNI')
AND ordinal_position=1 AND data_type NOT IN ('tinyint', 'smallint', 'mediumint', 'int', 'bigint',
'timestamp', 'datetime') AND table_schema NOT IN ('mysql', 'information_schema', 'sys',
'performance_schema');

Find tables and indexes with The overall performance improvement gained by optimizing a single part of a system, is limited by the
the most latency fraction of time that the improved part is actually used -

SELECT * FROM sys.schema_table_statistics WHERE table_schema='test' AND table_schema NOT


IN ('mysql', 'information_schema', 'sys', 'performance_schema');

SELECT * FROM sys.schema_index_statistics WHERE table_schema='test' AND table_schema


NOT IN ('mysql', 'information_schema', 'sys', 'performance_schema');

Find tables whose indexes > SELECT table_schema, table_name, index_length, data_length, index_length/data_length AS
data by 50% index_to_data_ratio FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'information_schema', 'sys', 'performance_schema') AND
INDEX_LENGTH > DATA_LENGTH*1.5;

Find tables with duplicate SELECT table_schema,table_name,redundant_index_name AS redundant_index,


indexes redundant_index_columns AS redundant_columns, dominant_index_name AS
covered_by_index,sql_drop_index FROM sys.schema_redundant_indexes WHERE table_schema
NOT IN ('mysql', 'information_schema', 'sys', 'performance_schema');

Find unused indexes SELECT * FROM sys.schema_unused_indexes WHERE object_schema NOT IN ('mysql',
‘information_schema', ‘sys', ‘performance_schema’);

Calculating the Index Size → Table size (data + index)

SELECT table_schema "database", sum(data_length + index_length)/1024/1024 "size in MB" FROM


information_schema.TABLES where table_schema='<dbname>' GROUP BY table_schema;

→ individual index size (before/after analyze table)

Before analyze table

SELECT database_name, index_name, sum(ROUND(stat_value * @@innodb_page_size / 1024 /


1024, 2)) size_in_mb from mysql.innodb_index_stats wHERE database_name ='<dbname>' AND
stat_name = 'size' and table_name like 'node%' group by database_name, index_name order by
size_in_mb desc;

After analyze table (analyze table command: “ analyze table <tablename> for all; “ )

SELECT database_name, index_name, sum(ROUND(stat_value * @@innodb_page_size / 1024 /


1024, 2)) size_in_mb from mysql.innodb_index_stats wHERE database_name ='dv_repo' AND
stat_name = 'size' and table_name like 'node%' group by database_name, index_name order by
size_in_mb desc;

SELECT database_name, sum(ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2))


size_in_mb from mysql.innodb_index_stats WHERE database_name ='<dbname>' AND stat_name =
'size' and table_name like 'node%';

SELECT database_name, sum(ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2))


size_in_mb from mysql.innodb_index_stats WHERE database_name ='<dbname>' AND stat_name =
'size' and table_name like 'node%';

Table size from OS command

mysql@mariadb-test01 0 15:39:19 /mysql/data/dv_repo $ pwd


/mysql/data/dv_repo

mysql@mariadb-test01 0 15:44:11 /mysql/data/dv_repo $ du -ch node* |grep total


116G total

Getting the index related SELECT distinct table_name, index_name, column_name from information_schema.statistics where
information by providing the table_schema = '<dbname>' and index_name not like 'SYS%' and index_name != 'PRIMARY' order
given DB name by 1, 2, seq_in_index;

Processlist and Queries


Description SQL Statement - Queries

Count of Current Processlist SELECT count(*) from information_schema.processlist;

List of Users , Host , DB count from current Processlist SELECT USER,HOST, DB,COUNT(*) from information_schema.processlist
group by user, db order by 4;

List of Users , Host , DB , Queries count from current SELECT id,HOST,PROGRESS,user,time,substr(info, 1, 100) FROM
Processlist information_schema.processlist where command != 'Sleep' order by time;

Display FULL Current processlist SHOW FULL PROCESSLIST; SHOW PROCESSLIST;

Display all list of Current Process SELECT * FROM information_schema.processlist;

Display number of connections for each user SELECT USER, COUNT(*) FROM information_schema.processlist GROUP
BY USER ;

Display number of connections for each host SELECT HOST, COUNT(*) FROM information_schema.processlist GROUP
BY HOST;

Display root user activity SELECT * FROM information_schema.processlist WHERE USER = 'root';

Display processes associated with SELECT queries SELECT * FROM information_schema.processlist WHERE INFO LIKE
'SELECT %';

Display average query time for each database SELECT DB, AVG(TIME) FROM information_schema.processlist GROUP BY
DB;

Stop/Kill Queries using the Transaction IDs taken from CALL mysql.rds_kill(processID);
the PROCESS LIST commands

Killing the process / Sessions by using concatination Script


1 You have 2 option , either you can restart the MariaDB service which in turn will remove these thread or
2 alternate option is to kill then either one by one or you can use below query to do the same in bulk.
3
4 # mysql -u<user> -p<password> -e "select concat('KILL ',id,';') into outfile '/tmp/sleep_processes.txt'
5 from information_schema.processlist where Command = 'Sleep' and USER not in ('system user', monitor_user)"
6
7 Note: List out all the USER in above query which you don't want to kill , make sure none of the system_user or
8 replication user defined should get killed , better you can add them in above query in section "....USER not in
9 ('system user', 'monitor_user', '......','...........')""
10
11 Run the generated sleep_processes.txt output with in MariaDB server , it will kill all of the sleeping threads.
12
13 # mysql -u<user> -p<password> -e "source /tmp/sleep_processes.txt;"
14
15 For example :-
16
17 # mysql -u root -pxxxx -e "select concat('KILL ',id,';') into outfile '/tmp/sleep_processes.txt' from
18 information_schema.processlist where Command = 'Sleep' and USER not in ('system user', 'monitor_user')"
19
20 ls -ltrh
21 -rw-rw-rw- 1 mysql mysql 19 Apr 27 05:03 sleep_processes.txt
22
23 # cat sleep_processes.txt
24 KILL 104;
25 KILL 93;
26
27 You can randomly verify the above thread id with in MariaDB server to cross check none of the valid user get
28 killed .
29
30 [root@gcn_01 tmp]# mysql -u root -pxxxxxx
31 MariaDB [(none)]> show processlist;
32 +-----+-------------+-----------------------+------+---------+---------+--------------------+------------------+
33 | Id | User | Host | db | Command | Time | State | Info |
34 +-----+-------------+-----------------------+------+---------+---------+--------------------+------------------+
35 | 1 | system user | | NULL | Sleep | 2075783 | wsrep aborter idle | NULL |
36 | 2 | system user | | NULL | Sleep | 2075783 | closing tables | NULL |
37 | 93 | maxmon_gc | 192.168.140.100:37858 | NULL | Sleep | 0 | | NULL |
38 | 104 | app_user | 192.168.140.156:37156 | NULL | Sleep | 47 | | NULL |
39 | 108 | root | localhost | NULL | Query | 0 | starting | show processlist |
40 +-----+-------------+-----------------------+------+---------+---------+--------------------+------------------+
41 5 rows in set (0.000 sec)

MySQL Users information SQL Queries


Description SQL Statement - Queries

Display the MySQL Database users SELECT USER,HOST FROM mysql.user;

CHARSET and COLLATIONS


Description SQL Statement - Queries

To display each database CHARSET SELECT SCHEMA_NAME 'database', default_character_set_name 'charset',


and COLLATION details DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA;

Troubleshooting Locks and Waits


Description SQL Statement - Queries
Troubleshooting Locks SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; → MySQL 5.7 DB


Version

SELECT * FROM performance_schema.data_locks; → MySQL 8 DB Version

Troubleshooting Lock Waits SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; → MySQL


5.7 DB Version

SELECT * FROM performance_schema.data_lock_waits; → MySQL 8 DB Version

Find Waiting Transactions and the Locks SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query
blocking the resource required waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query FROM information_schema.innodb_lock_waits w INNER
[ MySQL 5.7 DB Version ]
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN
information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

Find Waiting Transactions and the Locks SELECT r.trx_id waiting_trx_id,r.trx_mysql_thread_id waiting_thread,r.trx_query
blocking the resource required waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query FROM performance_schema.data_lock_waits w INNER
[ MySQL 8 DB Version ]
JOIN information_schema.innodb_trx b ON b.trx_id =
w.blocking_engine_transaction_id INNER JOIN information_schema.innodb_trx r ON
r.trx_id = w.requesting_engine_transaction_id;

Mariadb lock scripts SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query


waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query FROM information_schema.innodb_lock_waits w INNER
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN
information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id\G

InnoDB related DB Queries


Description SQL Statement - Queries

Find tables not using InnoDB SELECT t.table_schema,t.table_name,t.engine FROM


information_schema.tables t WHERE t.table_schema NOT IN ('mysql',
'information_schema', 'sys', 'performance_schema') AND t.engine <> 'InnoDB'
AND t.table_type = 'BASE TABLE';

Or based on the amount of data in tables retrieved from Information Schema:

SELECT 'Sum_index_length' as '', IFNULL(SUM(INDEX_LENGTH),0) from


information_schema.TABLES where ENGINE='InnoDB';
SELECT 'Sum_data_length' as '', IFNULL(SUM(DATA_LENGTH),0) from
information_schema.TABLES where ENGINE='InnoDB';

Or based also on the physical tablespace file:

SELECT FILE_SIZE FROM


INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ..

Query that you can use to verify the Storage Engines SELECT COUNT(*) as '# TABLES', CONCAT(ROUND(sum(data_length) / (
actually used on your database 1024 * 1024 * 1024 ), 2), 'G') DATA,CONCAT(ROUND(sum(index_length) / (
1024 * 1024 * 1024 ), 2), 'G') INDEXES,CONCAT(sum(ROUND(( data_length
+ index_length ) / ( 1024 * 1024 * 1024 ), 2)), 'G') 'TOTAL SIZE', ENGINE
FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN
('mysql', 'information_schema', 'performance_schema', 'sys') GROUP BY
engine;

Display the Storage Engines other than MyISAM and SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE FROM
InnoDB information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql',
'information_schema', 'performance_schema', 'sys') AND engine NOT IN
('MyISAM','InnoDB');

Note :- If we see any Engine = aria or any other Engines , from above
command ,

There are two ways to fix this, either we modify the engine directly on the
MariaDB server (recommended), or we modify the engine when loading the
data on MySQL 8.0.

Recommended way:

ALTER TABLE mydatabase.t4 ENGINE=InnoDB;

I will illustrate the dump in the next part without first changing the storage
engine to InnoDB, but be aware that sometimes there may be limitations
related to the size of the rows, it also depends on the character set used.

Performance_schema Related Database Queries


Description SQL Statement - Queries

The MySQL DBA has also access to the disk space select * from health_block_device order by timestamp desc limit 10;
usage via the SQL interface using
Performance_Schema. In MySQL Database Service,
Performance_Schema provides some extra tables that
are part of the Health Monitor:

Using performance_schema you can also find the size SELECT format_bytes(sum(data_length)) DATA_SIZE,
of your dataset and the space used on disk: format_bytes(sum(index_length)) INDEX_SIZE,
format_bytes(sum(data_length+index_length)) TOTAL_SIZE,
format_bytes(sum(data_free)) DATA_FREE, format_bytes(sum(FILE_SIZE))
FILE_SIZE, format_bytes((sum(FILE_SIZE)/10 - (sum(data_length)/10 +
sum(index_length)/10))*10) WASTED_SIZE FROM
information_schema.TABLES as t JOIN
information_schema.INNODB_TABLESPACES as it ON it.name =
concat(table_schema,"/",table_name) ORDER BY (data_length +
index_length);

In the result of the previous SQL statement, we can SELECT NAME, TABLE_ROWS, format_bytes(data_length) DATA_SIZE,
see in the last column (WASTED_SIZE) that there are format_bytes(index_length) INDEX_SIZE,
almost 650MB of wasted disk space. This column format_bytes(data_length+index_length) TOTAL_SIZE,
represents gaps in tablespaces. Let’s find out for format_bytes(data_free) DATA_FREE, format_bytes(FILE_SIZE) FILE_SIZE,
which tables and how to recover it: format_bytes((FILE_SIZE/10 - (data_length/10 + index_length/10))*10)
WASTED_SIZE FROM information_schema.TABLES as t JOIN
information_schema.INNODB_TABLESPACES as it ON it.name =
Disk Space Utilization concat(table_schema,"/",table_name) ORDER BY (data_length +
index_length) desc LIMIT 10;

set information_schema_stats_expiry=0;
SELECT NAME, TABLE_ROWS, format_bytes(data_length) DATA_SIZE,
format_bytes(index_length) INDEX_SIZE,
format_bytes(data_length+index_length) TOTAL_SIZE,
format_bytes(data_free) DATA_FREE, format_bytes(FILE_SIZE) FILE_SIZE,
format_bytes((FILE_SIZE/10 - (data_length/10 + index_length/10))*10)
WASTED_SIZE FROM information_schema.TABLES as t JOIN
information_schema.INNODB_TABLESPACES as it ON it.name =
concat(table_schema,"/",table_name) ORDER BY (data_length +
index_length) desc LIMIT 10;

Performance Schema feature of MySQL to fetch the SELECT QUERY_ID, SUM(IO_READ_REQUESTS) AS


most I/O utilized queries. Here's an example query TOTAL_READ_REQUESTS, SUM(IO_READ_BYTES) AS
that will show the top 10 queries by I/O utilization: TOTAL_READ_BYTES, SUM(IO_WRITE_REQUESTS) AS
TOTAL_WRITE_REQUESTS, SUM(IO_WRITE_BYTES) AS
TOTAL_WRITE_BYTES, SUM(IO_MISC_REQUESTS) AS
TOTAL_MISC_REQUESTS, SUM(IO_PENDING) AS TOTAL_PENDING
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT LIKE '%YOUR_SEARCH_STRING%' GROUP BY
QUERY_ID ORDER BY TOTAL_READ_REQUESTS +
TOTAL_WRITE_REQUESTS DESC LIMIT 10;

In this query, you can replace YOUR_SEARCH_STRING with a keyword or


part of a query that you want to search for. This will return the top 10 queries
that match the search string based on their I/O utilization.

Note that in order for this query to work, you need to have the Performance
Schema enabled in your MySQL installation, and you need to have the
appropriate privileges to access the performance_schema database.

WATCH Commands
1 watch -n 1 'mysql --defaults-file=/etc/my.cnf -h 127.0.0.1 -P 6032 -t -e "select b.weight, c.* from
2 stats_mysql_connection_pool c left JOIN runtime_mysql_servers b ON c.hostgroup=b.hostgroup_id and
3 c.srv_host=b.hostname and c.srv_port = b.port where hostgroup in( 50,52,70,71) order by hostgroup,
4 srv_host desc;" -e " select srv_host,command,avg(time_ms), count(ThreadID) from stats_mysql_processlist
5 group by srv_host,command;" -e "select * from stats_mysql_users;";
6 mysql --defaults-file=~/.my.cnf -h 127.0.0.1 -P 6032 -t -e "select * from stats_mysql_global "|egrep -i
7 "(mirror|memory|stmt|processor)"'
8
9 +--------+-----------+--------------------------------------------------------------------------+----------+----
10 | weight | hostgroup | srv_host | srv_port | STA
11 +--------+-----------+--------------------------------------------------------------------------+----------+----
12 | 1000 | 70 | proxysqltestdb.c7wzm8xxmrze.eu-central-1.rds.amazonaws.com | 3306 | ONL
13 | 1000 | 71 | proxysqltestdb2.c7wzm8xxmrze.eu-central-1.rds.amazonaws.com | 3306 | ONL
14 | 1000 | 71 | proxysqltestdb.c7wzm8xxmrze.eu-central-1.rds.amazonaws.com | 3306 | ONL
15 | 1 | 71 | proxysqltestdb-eu-central-1b.c7wzm8xxmrze.eu-central-1.rds.amazonaws.com | 3306 | ONLI
16 +--------+-----------+--------------------------------------------------------------------------+----------+----
17 +----------+----------------------+--------------------------+
18 | username | frontend_connections | frontend_max_connections |
19 +----------+----------------------+--------------------------+
20 | m8_test | 0 | 10000 |
21 +----------+----------------------+--------------------------+
22 | Query_Processor_time_nsec | 0 |
23 | Com_backend_stmt_prepare | 0 |
24 | Com_backend_stmt_execute | 0 |
25 | Com_backend_stmt_close | 0 |
26 | Com_frontend_stmt_prepare | 0 |
27 | Com_frontend_stmt_execute | 0 |
28 | Com_frontend_stmt_close | 0 |
29 | Mirror_concurrency | 0 |
30 | Mirror_queue_length | 0 |
31 | SQLite3_memory_bytes | 2652288 |
32 | ConnPool_memory_bytes | 712720 |
33 | Stmt_Client_Active_Total | 0 |
34 | Stmt_Client_Active_Unique | 0 |
35 | Stmt_Server_Active_Total | 0 |
36 | Stmt_Server_Active_Unique | 0 |
37 | Stmt_Max_Stmt_id | 1 |
38 | Stmt_Cached | 0 |
39 | Query_Cache_Memory_bytes | 0 |
40
41 Reference Links :-
42
43 https://www.tusacentral.com/joomla/index.php/mysql-blogs/199-how-to-implement-proxysql-with-aws-aurora
44 https://www.tusacentral.com/joomla/index.php/mysql-blogs/168-how-to-mess-up-your-data
45 -using-one-command-in-mysqlgalera

Top Queries for Security Checking in MySQL


Description SQL Statement - Queries

MySQL Uptime SELECT VARIABLE_VALUE AS Uptime_seconds, NOW() AS "Now", NOW() - INTERVAL


VARIABLE_VALUE SECOND AS "Up since", DATEDIFF(NOW(), NOW() - INTERVAL
VARIABLE_VALUE SECOND) AS "Uptime_days" FROM performance_schema.session_status WHERE
VARIABLE_NAME = 'Uptime';

SELECT TIME_FORMAT(SEC_TO_TIME(VARIABLE_VALUE ),'%Hh %im') as Uptime from


performance_schema.global_status where VARIABLE_NAME='Uptime';

SELECT TIME_FORMAT(SEC_TO_TIME(VARIABLE_VALUE ),'%Hh %im') as Uptime from


information_schema.GLOBAL_STATUS where VARIABLE_NAME='Uptime';

Find the Tables without SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND
Primary Key table_name NOT IN ( SELECT DISTINCT table_name FROM information_schema.statistics WHERE
index_name = 'PRIMARY');

SELECT t.table_schema,t.table_name,t.engine FROM information_schema.tables t JOIN


information_schema.columns c ON t.table_schema=c.table_schema AND t.table_name=c.table_name
WHERE t.table_schema NOT IN ('mysql', ‘information_schema', ‘sys', ‘performance_schema') AND
t.table_type = ‘BASE TABLE' GROUP BY t.table_schema,t.table_name, t.engine HAVING
SUM(IF(column_key IN ('PRI','UNI'), 1,0)) = 0;

Top 10 Large Tables SELECT table_name AS TABLE_NAME round(((data_length + index_length) / 1024 / 1024), 2)
Table_Size_MB FROM information_schema.TABLES WHERE
table_schema = "<your_database_name>” ORDER BY (data_length + index_length) DESC LIMIT 10
;

Top 10 Fragmented Tables SELECT table_name AS Table_Name, round((data_free / 1024 / 1024), 20 Free_Space_MB FROM
information_schema.TABLES WHERE table_schema =”<your_database_name>" AND data_free > 0
ORDER BY data_free DESC LIMIT 10;
Duplicate Index SELECT GROUP_CONCAT(DISTINCT(index_name) SEPARATOR ', ') AS Duplicate_Indexes FROM
information_schema.statistics WHERE table_schema = '<Your_database_name>' AND non_unique = 0
GROUP BY table_name, index_name HAVING COUNT(*) > 1;

Or

SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, group_concat(INDEX_NAME) duplic8_UK,


COLUMN_NAMES FROM (SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME,
GROUP_CONCAT(COLUMN_NAME ORDER BY COLUMN_NAME SEPARATOR ',') AS
COLUMN_NAMES
FROM information_schema.STATISTICS WHERE NON_UNIQUE = 0 AND INDEX_NAME!='PRIMARY'
AND INDEX_TYPE = 'BTREE' GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME) X group
by TABLE_SCHEMA, TABLE_NAME, COLUMN_NAMES having count(*)> 1;

Or

SELECT table_schema,table_name,redundant_index_name AS redundant_index,


redundant_index_columns AS redundant_columns, dominant_index_name AS
covered_by_index,sql_drop_index FROM sys.schema_redundant_indexes WHERE table_schema NOT
IN ('mysql', 'information_schema', 'sys', 'performance_schema');

Reference Link :- Take This Unique Quiz About Duplicate Indexes In MySQL | pt-duplicate-key-chec
ker

Connections
Description SQL Statement - Queries

Checking the Secure The first thing we can check is that all our clients encrypt their connection to the MySQL server.
Connections
We use again Performance_Schema to retrieve the relevant information:

select connection_type, substring_index(substring_index(name,"/",2),"/",-1) name,sbt.variable_value AS


tls_version, t2.variable_value AS cipher,processlist_user AS user, processlist_host AS host from
performance_schema.status_by_thread AS sbt join performance_schema.threads AS t on t.thread_id =
sbt.thread_id join performance_schema.status_by_thread AS t2 on t2.thread_id = t.thread_id where
sbt.variable_name = 'Ssl_version' and t2.variable_name = 'Ssl_cipher' order by connection_type, tls_version;

Note :- If we want to force the user to use encrypted connections to our MySQL DB system, we modify the
user like this:

alter user fred require ssl;

Failed Connections As a DBA, you also need to verify who is trying to connect unsuccessfully to your database server. It could be
a user without the right credentials, using a non supported TLS or cipher version or eventually a malicious
person/program.

Plugin Installation :- [ https://blogs.oracle.com/mysql/post/mysql-connection-control ]

Let’s test the plugin to show how it works.

The plugin library is connection_control.so that is installed in the plugin directory. On Oracle Linux/RedHat
Enterprise/CentOS/Fedora the default path, if MySQL Server was installed via RPM, is:
/usr/lib64/mysql/plugin/connection_control.so.

It’s possible to install the plugin in my.cnf, see the manual, but we will see how to use it interactively:

INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';


INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.s
Once installed, the plugin can be listed from Information_Schema:

SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE


PLUGIN_NAME LIKE 'connection%';

Now, let’s configure the plugin. We will set the threshold of consecutive failed connection tentative to 4 and
add a minimum of 1,5 seconds:

SET GLOBAL connection_control_failed_connections_threshold = 4;


SET GLOBAL connection_control_min_connection_delay = 1500

If there are failed login attempts, we will be able to list them in Information_Schema using the table
connection_control_failed_login_attempts, for the moment it’s still empty:

select * from information_schema.connection_control_failed_login_attempts;


Empty set (0.0003 sec)

Verify the failed select * from information_schema.connection_control_failed_login_attempts;


attempts from the
select logged, data from performance_schema.error_log where error_code in ('MY-010926', 'MY-010914')
information_schema.c
order by logged desc limit 10;
onnection_control_fail
ed_loin_attempts select * from performance_schema.global_variables where variable_name like 'connection_control%';
table:
In Performance_Schema, there is a table providing us some useful summary: host_cache:

select ip, count_ssl_errors, count_handshake_errors, count_authentication_errors from host_cache;

memory tracking The current global memory consumption (including background threads and admin) can be returned by the
following query:

SELECT format_bytes(variable_value) global_connection_memory FROM


performance_schema.global_status WHERE variable_name='Global_connection_memory';

Error Logging select * from (select * from performance_schema.error_log order by logged desc limit 10) a order by logged\G

select subsystem, count(*) from performance_schema.error_log group by subsystem order by subsystem;

select prio, count(*) from performance_schema.error_log group by prio order by prio;

The error log provides a lot of information about how healthy is your system, about health monitor, InnoDB,
replication, authentication failures, etc…

For example, we can see the disk usage (see the previous post) in the error_log table too:

select * from error_log where subsystem="Health" and data like 'DISK:%' order by logged desc limit 4\G

select * from performance_schema.global_variables where variable_name like 'log_error%';

select * from performance_schema.global_status where variable_name in


('rapid_resize_status','rapid_service_status','rapid_cluster_ready_number');

select * from (select * from performance_schema.error_log order by logged desc limit 10) a order by logged\G

1 Testing for Failed Connections :-


2 --------------------------------
3
4 Let’s test our settings by trying to connect to our MySQL Server using MySQL Shell and an invalid password.
5 We will try 10 times in a row and only display the real time spent by the command (the connection attempt):
6
7 $ TIMEFORMAT=%R
8 $ for i in `seq 1 10`
9 do
10 time mysql mysql://fred:[email protected] 2>&1 >/dev/null | grep meh
11 done
12 0.747
13 0.749
14 0.731
15 0.735
16 2.265
17 2.753
18 3.744
19 4.757
20 5.750
21 6.741
22
23 It’s obvious that after the 4th attempt the response time kept increasing.
24 We can verify the status variable Connection_control_delay_generated, that contains the number of times the
25 server added a delay to its response to a failed connection attempt:
26
27 show global status like 'connection_control_%';
28 +------------------------------------+-------+
29 | Variable_name | Value |
30 +------------------------------------+-------+
31 | Connection_control_delay_generated | 6 |
32 +------------------------------------+-------+
33
34 And this time the connection_control_failed_login_attempts table is not empty:
35
36 select * from information_schema.connection_control_failed_login_attempts;
37 +------------+-----------------+
38 | USERHOST | FAILED_ATTEMPTS |
39 +------------+-----------------+
40 | 'fred'@'%' | 10 |
41 +------------+-----------------+
42 1 row in set (0.0007 sec)
43
44 To reset those counters, you just have to assign again a value to the variable
45 connection_control_failed_connections_threshold:
46
47 SET GLOBAL connection_control_failed_connections_threshold = 4;
48 Query OK, 0 rows affected (0.0001 sec)
49
50 select * from information_schema.connection_control_failed_login_attempts;
51 Empty set (0.0007 sec
52
53 show global status like 'connection_control_%';
54 +------------------------------------+-------+
55 | Variable_name | Value |
56 +------------------------------------+-------+
57 | Connection_control_delay_generated | 0 |
58 +------------------------------------+-------+
59
60 Now we can also test without using MySQL Shell or any other MySQL protocol aware client:
61
62 $ for i in `seq 1 10`
63 do
64 time echo meh | nc 127.0.0.3 3306 2>&1 >/dev/null | grep meh
65 done
66 0.027
67 0.024
68 0.023
69 0.022
70 1.526
71 2.032
72 3.028
73 4.027
74 5.032
75 6.065
76
77 We can see that the response time is also increased even if there was no real MySQL authentication attempt.
78 We can see that the info is also available:
79
80 <span style="white-space: normal">select * from information_schema.connection_control_failed_login_attempts;
81 </span>
82
83 +----------------+-----------------+
84 | USERHOST | FAILED_ATTEMPTS |
85 +----------------+-----------------+
86 | ''@'localhost' | 10 |
87 +----------------+-----------------+
88 1 row in set (0.0006 sec)
89
90 show global status like 'connection_control_%';
91 +------------------------------------+-------+
92 | Variable_name | Value |
93 +------------------------------------+-------+
94 | Connection_control_delay_generated | 6 |
95 +------------------------------------+-------+
96 1 row in set (0.0021 sec)
97
98 Conclusion
99
100 MySQL Connection Control can be very useful in some environments to avoid or limit the inconvenience of a
101 brute force attack or inappropriate TCP connections.
102
103 In MySQL HeatWave Database Service on Oracle Cloud Infrastructure, Connection Control Plugin is enabled by
104 default.
105
106 These are the values used:
107
108 show global variables like 'connection_control_%';
109 +-------------------------------------------------+-------+
110 | Variable_name | Value |
111 +-------------------------------------------------+-------+
112 | connection_control_failed_connections_threshold | 3 |
113 | connection_control_max_connection_delay | 10000 |
114 | connection_control_min_connection_delay | 1000 |
115 +-------------------------------------------------+-------+

InnoDB Table Fragmentation and Defragmentation, Free Space, Within


MySQL Server

Notes
1
2 --> It is not necessary for the proper functioning of MySQL or InnoDB to do any defragmentation.
3 --> It is solely a possible performance or free space effect.
4 --> Usually it is just a waste of time and resources to even consider it. But not always.
5 --> There can be significant benefits for table or index scans.
6 --> The first defragmentation of a table will normally take much more time than later ones when the bulk of the
7 table is already defragmented.
8
9 --> From MySQL 5.6.17 OPTIMIZE TABLE, ALTER TABLE FORCE or ALTER TABLE ENGINE=INNODB for a table that is already
10 InnoDB will use online DDL to allow DML during the operation if possible.
11 --> This makes it far more practical to carry out the internal defragmentation since you can just use
12 OPTIMIZE TABLE and then perform filesystem defragmentation.
13 --> This is the preferred way if you are using a suitable version of the server. You should still try to
14 carry out the operation at a low load time because the disk I/O will slow the server significantly.
15 --> Ensure that innodb_online_alter_log_max_size is large enough to hold all DML on the table during the
16 online operation.
17 --> Use innodb_sort_buffer_size to improve the speed of index rebuilding during the operation; the default
18 of 1M is quite small and some tens or hundreds of megabytes can be useful for larger indexes to reduce the
19 number of sort merge passes used.
20 --> The non-blocking inplace method will not be used if old_alter_table is on, the table contains fulltext index
21 skip-new is enabled and you are using OPTIMIZE TABLE or if you use COPY to force a copy instead of inplace;
22 in these cases the instructions below may be more suitable and you cannot carry out the operation without
23 blocking all DML during it.

Types of fragmentation
There are several things that may be called fragmentation that can be of interest. There is no single definition of the word fragmentation that
applies to InnoDB since the term is used to refer to many different things.

Free space

Sometimes people think of fragmentation as free space that could be reused. Mostly you should ignore this but sometimes it is of use to try
to make the free space available to the filesystem or other tables. Any rebuilding of a table will do this, a null ALTER TABLE, say. If you want
to check the free space you can do queries like

1 SELECT table_schema, table_name, data_free / 1024 / 1024 AS data_free_in_MB FROM information_schema.tables WHERE
2 engine LIKE 'InnoDB' AND data_free > 5000*1024*1024;

This will return tables with more than five thousand megabytes of reported fee data space. It requires MySQL 5.1.21 or later. Freeing disk
space can be useful for many reasons so this can be more useful than other things that are called fragmentation.

Combined defragmentation for all causes

1
2 --> From version 5.6.17 and later OPTIMIZE TABLE will use online DDL with algorithm=inplace to leave the table
3 modifiable during the operation. You should still try to carry out the task at a low load time.
4 --> Before 5.6.17, if you want to reduce all of the types of fragmentation and are using innodb_file_per_table
5 you can do this:
6
7 1. Optional, defragment within the filesystem using a filesystem defragmentation tool or copying the *.ibd files
8 somewhere and back to the original place.
9 2. ALTER TABLE tablename DROP INDEX index1, DROP INDEX index2 etc. to drop all of the non-unique secondary index
10 Skip this if not using MySQL 5.5 or later.
11 3. ALTER TABLE tablename ENGINE = InnoDB or OPTIMIZE TABLE tablename or in MySQL 5.5 and later ALTER TABLE
12 tablename FORCE to rebuild the clustered index and data rows.
13 4. ALTER TABLE tablename ADD INDEX index1 and its details, ADD INDEX index2 and its details etc. to add back the
14 dropped indexes. Skip this if not using MySQL 5.5 or later.
15 5. Optional, there may now be some filesystem fragmentation, consider whether it is worth using a filesystem
16 defragmentation tool.
17
18 You should not expect to be able to have the server in production service when you do this work. It is extremely
19 diskintensive and makes very heavy use of the buffer pool so performance for other work will be severely
20 impacted unless the tables are small.
21
22 If a table is changed after this work the fragmentation will gradually return. The effect will be greatest for
23 secondary indexes or for a clustered/primary index where rows are not inserted in primary key order.
24
25 A clustered/primary index will remain well defragmented for existing data if new data is added sequentially and
26 no deletes or updates are done.
27
28 There is no specific schedule for doing this work. You can schedule all or some of it based on your observation
29 of the rates at which each individual table becomes fragmented enough to make a difference. It is normal for
30 different tables and indexes to be affected at different rates and to benefit to different degrees.

Fragmentation within the shared tablespace, mainly if not using innodb_file_per_table

1 If not using innodb_file_per_table (manual), space is allocated within the shared tablespace: the ibdata1 file
2 and others you may have allocated. Any ALTER TABLE operation with COPY algorithm will reduce this fragmentation.
3
4 It can be quite significant for performance when doing table scans. This cannot affect you for a table that is
5 using innodb_file_per_table, except that the undo log can cause the file to grow and that can sometimes cause a
6 little fragmentation.
7
8 If doing this defragmenting you should do the smaller tables before the larger ones because a copy of the table
9 is made within the shared tablespace. That copy will increase the shared tablespace size. If you do the small
10 tables first, the space freed by rebuilding them will be available to later tables and this will reduce the
11 amount of growth or possibly eliminate it.
12
13 Alternatively, if no foreign keys will be affected, you could alter the table to MyISAM and back to InnoDB.
14 The conversion to MyISAM will free the space within the shared tablespace and the conversion back to InnoDB
15 will be able to reuse that space, usually preventing growth. If you want to use the MyISAM method use:
16
17 1. ALTER TABLE tablename ENGINE=MyISAM;
18 2. ALTER TABLE tablename ENGINE=InnoDB;

Fragmentation within the filesystem when using innodb_file_per_table

1 This is the most serious form and can cause significant performance issues, most visible when dropping a table.
2 To check the amount of fragmentation use filefrag on Linux, chkdsk on Windows with FAT32 or the defragmentation
3 tool in other Windows filesystems. If you find that you have fragmented tables the best way to defragment them
4 without using a defragmentation tool is to:
5
6 1. Shut down mysqld
7 2. Make a copy of the *.ibd file.
8 3. Delete the original *.ibd file.
9 4. Move the copied file to the location of the original
10
11 The *.ibd files are located in the sub-directory that normally has the same name as the database the table
12 belongs to. If you do have a defragmentation tool, it is better to use that.
13
14 This is likely to be much faster than the other steps and is likely to deliver the greatest benefit
15 if there is significant filesystem fragmentation.

Encryption Queries
1 SELECT NAME, CURRENT_KEY_VERSION from information_schema.INNODB_TABLESPACES_ENCRYPTION;
2
3 To see, which users are using an encrypted connection, run the following query
4 --------------------------------------------------------------------------------
5
6 Note :- performance_schema variable should be turned "ON"
7
8 SELECT sbt.variable_value AS tls_version, t2.variable_value AS cipher, processlist_user AS user,
9 processlist_host AS host FROM performance_schema.status_by_thread AS sbt JOIN
10 performance_schema.threads AS t ON t.thread_id = sbt.thread_id JOIN
11 performance_schema.status_by_thread AS t2 ON t2.thread_id = t.thread_id WHERE
12 sbt.variable_name = 'Ssl_version' and t2.variable_name = 'Ssl_cipher' ORDER BY tls_version;

MySQL Transaction Reporting

Report latest query for transactions active longer than 1 second


1 --
2 -- Example 8-2. Report latest query for transactions active longer than 1 second
3 --
4
5 SELECT
6 ROUND(trx.timer_wait/1000000000000,3) AS trx_runtime,
7 trx.thread_id AS thread_id,
8 trx.event_id AS trx_event_id,
9 trx.isolation_level,
10 trx.autocommit,
11 stm.current_schema AS db,
12 stm.sql_text AS query,
13 stm.rows_examined AS rows_examined,
14 stm.rows_affected AS rows_affected,
15 stm.rows_sent AS rows_sent,
16 IF(stm.end_event_id IS NULL, 'running', 'done') AS exec_state,
17 ROUND(stm.timer_wait/1000000000000,3) AS exec_time
18 FROM
19 performance_schema.events_transactions_current trx
20 JOIN performance_schema.events_statements_current stm USING (thread_id)
21 WHERE
22 trx.state = 'ACTIVE'
23 AND trx.timer_wait > 1000000000000 * 1\G

Report transaction summary


1 --
2 -- Example 8-3. Report transaction summary
3 --
4
5 SELECT
6 trx.thread_id AS thread_id,
7 MAX(trx.event_id) AS trx_event_id,
8 MAX(ROUND(trx.timer_wait/1000000000000,3)) AS trx_runtime,
9 SUM(ROUND(stm.timer_wait/1000000000000,3)) AS exec_time,
10 SUM(stm.rows_examined) AS rows_examined,
11 SUM(stm.rows_affected) AS rows_affected,
12 SUM(stm.rows_sent) AS rows_sent
13 FROM
14 performance_schema.events_transactions_current trx
15 JOIN performance_schema.events_statements_history stm
16 ON stm.thread_id = trx.thread_id AND stm.nesting_event_id = trx.event_id
17 WHERE
18 stm.event_name LIKE 'statement/sql/%'
19 AND trx.state = 'ACTIVE'
20 AND trx.timer_wait > 1000000000000 * 1
21 GROUP BY trx.thread_id\G

Report transaction history


1 --
2 -- Example 8-4. Report transaction history
3 --
4
5 SELECT
6 stm.rows_examined AS rows_examined,
7 stm.rows_affected AS rows_affected,
8 stm.rows_sent AS rows_sent,
9 ROUND(stm.timer_wait/1000000000000,3) AS exec_time,
10 stm.sql_text AS query
11 FROM
12 performance_schema.events_statements_history stm
13 WHERE
14 stm.thread_id = 0
15 AND stm.nesting_event_id = 0
16 ORDER BY stm.event_id;

Report basic metrics for committed transactions


1 --
2 -- Example 8-5. Report basic metrics for committed transactions
3 --
4
5 SELECT
6 ROUND(MAX(trx.timer_wait)/1000000000,3) AS trx_time,
7 ROUND(SUM(stm.timer_end-stm.timer_start)/1000000000,3) AS query_time,
8 ROUND((MAX(trx.timer_wait)-SUM(stm.timer_end-stm.timer_start))/1000000000, 3)
9 AS idle_time,
10 COUNT(stm.event_id)-1 AS query_count,
11 SUM(stm.rows_examined) AS rows_examined,
12 SUM(stm.rows_affected) AS rows_affected,
13 SUM(stm.rows_sent) AS rows_sent
14 FROM
15 performance_schema.events_transactions_history trx
16 JOIN performance_schema.events_statements_history stm
17 ON stm.nesting_event_id = trx.event_id
18 WHERE
19 trx.state = 'COMMITTED'
20 AND trx.nesting_event_id IS NOT NULL
21 GROUP BY
22 trx.thread_id, trx.event_id;
All tables rows count by using Store Procedure
1 mysql> use test;
2 Database changed
3
4 mysql> DELIMITER $$
5 mysql> CREATE PROCEDURE `COUNT_ROWS_COUNTS_BY_TABLE`(dbName varchar(128))
6 BEGIN
7 DECLARE done INT DEFAULT 0;
8 DECLARE TNAME CHAR(255);
9 DECLARE table_names CURSOR for
10 SELECT CONCAT("`", TABLE_SCHEMA, "`.`", table_name, "`") FROM INFORMATION_SCHEMA.TABLES where
11 TABLE_SCHEMA = dbName;
12 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
13 OPEN table_names;
14 DROP TABLE IF EXISTS TABLES_ROWS_COUNTS;
15 CREATE TEMPORARY TABLE TABLES_ROWS_COUNTS
16 (
17 TABLE_NAME CHAR(255),
18 RECORD_COUNT INT
19 ) ENGINE = MEMORY;
20
21 WHILE done = 0 DO
22 FETCH NEXT FROM table_names INTO TNAME;
23 IF done = 0 THEN
24 SET @SQL_TXT = CONCAT("INSERT INTO TABLES_ROWS_COUNTS(SELECT '" , TNAME , "' AS TABLE_NAME, COUNT(*) AS
25 RECORD_COUNT FROM ", TNAME, ")");
26 PREPARE stmt_name FROM @SQL_TXT;
27 EXECUTE stmt_name;
28 DEALLOCATE PREPARE stmt_name;
29 END IF;
30 END WHILE;
31 CLOSE table_names;
32
33 SELECT * FROM TABLES_ROWS_COUNTS;
34 SELECT SUM(RECORD_COUNT) AS TOTAL_DATABASE_RECORD_CT FROM TABLES_ROWS_COUNTS;
35 END$$
36 DELIMITER ;
37 Query OK, 0 rows affected (0.01 sec)
38
39 mysql> show procedure status LIKE 'COUNT_ROWS_COUNTS_BY_TABLE';
40
41 mysql> use test;
42 Database changed
43
44 mysql> call COUNT_ROWS_COUNTS_BY_TABLE('mrsdb');
45 +-------------------------------------+--------------+
46 | TABLE_NAME | RECORD_COUNT |
47 +-------------------------------------+--------------+
48 | `mrsdb`.`mri_container` | 6979 |
49 | `mrsdb`.`mri_cp_s_bg_attr_def` | 0 |
50 | `mrsdb`.`mri_cr_folder` | 6048 |
51 | `mrsdb`.`mri_cr_p_app_project` | 7 |
52 | `mrsdb`.`mri_cr_p_app_spec` | 0 |
53 | `mrsdb`.`mri_cr_p_application` | 0 |
54 | `mrsdb`.`mri_cr_p_data_obj_config` | 4 |
55 ...

You might also like