DB/Mysql

From Ever changing code
< DB
Jump to navigation Jump to search

This is reference regarding mysql databases. It's worth to mention that MySQL open source project now is called MariaDB. These commands below are mainly tested with Amazon RDS instances.

Connect

mysql -h database-eu.example.com -u admin@database-eu -p
mysql -h database-eu.example.com -u admin@database-eu -pPassw0rd123
mysql -h database-eu.example.com -u admin@database-eu -pPassw0rd123 --ssl-mode=DISABLED # [1]
  • [1] ERROR 2026 (HY000): SSL connection error: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol when connecting from Ubuntu 20.04 to Aurora engine 5.6.mysql_aurora.1.22.2
References

Ops queries

Show process list

Note in the info column there will be the current SQL query running.

mysql> SHOW GLOBAL STATUS;
mysql> show full processlist;
+----+----------+--------------------+-------------+---------+------+----------------------+-----------------------+
| Id | User     | Host               | db          | Command | Time | State                | Info                  |
+----+----------+--------------------+-------------+---------+------+----------------------+-----------------------+
| 34 | rdsadmin | localhost          | NULL        | Sleep   |    0 | delayed send ok done | NULL                  |
| 35 | rdsadmin | localhost          | NULL        | Sleep   |    5 | cleaned up           | NULL                  |
| 36 | rdsadmin | localhost          | NULL        | Sleep   |  151 | delayed send ok done | NULL                  |
| 38 | root     | 10.10.11.10:35357  | core_db     | Sleep   |  260 | cleaned up           | NULL                  |
| 39 | root     | 10.10.11.10:35439  | core_db     | Sleep   |    1 | cleaned up           | NULL                  |
| 40 | root     | 10.10.11.10:35675  | NULL        | Query   |    0 | init                 | show full processlist |
+----+----------+--------------------+-------------+---------+------+----------------------+-----------------------+

Kill a process

In RDS you don't have access to all commands thus there is specific procedure to be called in:

kill 38                                # Mysql server
CALL mysql.rds_kill(38)                # RDS instance
CALL mysql.rds_kill_query($PROCESS_ID) # Aurora

Check version

mysql> SELECT VERSION();
+------------+
| VERSION()  |
+------------+
| 5.6.10-log |
+------------+

mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| aurora_version          | 1.17.7                       |
| innodb_version          | 1.2.10                       |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| version                 | 5.6.10-log                   |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+

Check current connections

watch -n1 "mysql -u root -pPASSWORD -te \"select id, command, host, time, left(info,60) from information_schema.processlist where info is not null or time > 300 order by time asc;\" 2>/dev/null"

Check a table size

SELECT COUNT(*) FROM `Table`; #count a table rows
SELECT table_name AS `Table`, round(((data_length + index_length) / 1024 / 1024), 2) `Size(MB)` FROM information_schema.TABLES WHERE table_schema = "$your_database";

Check size of all tables

SELECT 
     table_schema as `Database`, 
     table_name AS `Table`, 
     round(((data_length + index_length) / 1024 / 1024), 2) `Size(MB)` 
FROM information_schema.TABLES 
ORDER BY (data_length + index_length) DESC;

Watch database size

This is useful when loading data to a database.

RDS_HOSTNAME=localhost
RDS_PASS=***
DB=database1 # database name, watch all databases if empty
watch -d "mysql -h $RDS_HOSTNAME -u admin -p$RDS_PASS -e \"SELECT table_schema $DB, ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) DBSizeinMB  FROM information_schema.tables  GROUP BY table_schema;\""

+---------------------------+------------+
| table_schema              | DBSizeinMB |
+---------------------------+------------+
| information_schema        |        0.2 |
| mysql                     |        6.0 |
| performance_schema        |        0.0 |
| sys                       |        0.0 |
+---------------------------+------------+

mysql client - change the command line prompt

How to show the name of the current database in the MySQL prompt If you need the name of the currently selected database in your MySQL prompt, use the following lines in your MySQL my.cnf configuration file entry like this [mysql] prompt='mysql(\d)> ' Now, when you connect, the MySQL prompt will look like what’s shown below:

mysql((none))> use test;
#Database changed mysql(test)> 
mysql(test)> use mysql;
#Database changed mysql(mysql)>

Create a user

Show users

# Show users and their main set of privileges
SELECT user, host, password, select_priv, insert_priv, shutdown_priv, grant_priv FROM mysql.user

Create or delete a user

Note: If you use MySQL Workbench to see effect of the statements below, make sure to close and reopen the tab as the current state is read only on opening the tab.


Show users

SELECT * FROM mysql.user;


Mysql 5.7

CREATE USER           'new.user'@'localhost' IDENTIFIED BY 'password';
GRANT USAGE ON *.* TO 'new.user'@'%'         IDENTIFIED BY 'password';
DROP USER             'new.user'@'localhost';


Mysql 5.6. Notice usage lines, it creates a user without permissions if the user does not exist. It creates only '%' type of user.

GRANT USAGE ON *.* TO 'new.user'@'localhost';
GRANT USAGE ON *.* TO 'new.user'@'%';
DROP USER             'new.user'@'localhost';
DROP USER             'new.user'@'%';
CREATE USER           'new.user'@'%' IDENTIFIED BY 'password';

-- grant a user all privilages apart 'GRANT OPTION' on 'newdb' schema
GRANT ALL PRIVILEGES ON `newdb`.* TO 'new.user'@'%';

Grant a user privileges per tables and column

<syntaxhighlightjs lang="sql">

  1. MySQL 5.6

show grants for `username`;

  1. MySQL 5.7

SHOW GRANTS username; SELECT * FROM mysql.user; -- show users table and their privilages SELECT * FROM mysql.tables_priv WHERE user LIKE '%prav%'; -- show table privileges table SELECT * FROM mysql.columns_priv where user like '%praveen%'; -- show columns privileges table

  1. Grant permission to a specific table only

GRANT select ON mysql.general_log TO 'newuser'@'%'; GRANT type_of_permission ON db_name.table_name TO 'newuser'@'localhost';

  1. Grant permission to a specific column only, eg. grant `UPDATE` permission

GRANT UPDATE (col) ON `<db_name>`.<table_name> TO '<user>'@'%';

  1. Revoke table permission

REVOKE type_of_permission ON db_name.table_name FROM 'newuser'@'localhost';

  1. Once finalised the permissions for the users, always reload/save all the privileges

FLUSH PRIVILEGES;

-- RO GRANT SELECT, SHOW VIEW ON ... -- RW GRANT SELECT, SHOW VIEW, INSERT, UPDATE, DELETE ON ... </syntaxhighlightjs>


Show tables grants

mysql> select * from mysql.tables_priv;
+-----------+-------+------------+-------------+-------------------+---------------------+------------+-------------+
| Host      | Db    | User       | Table_name  | Grantor           | Timestamp           | Table_priv | Column_priv |
+-----------+-------+------------+-------------+-------------------+---------------------+------------+-------------+
| %         | mysql | bob        | general_log | root@10.10.11.10  | 0000-00-00 00:00:00 | Select     |             |
| %         | mysql | bob        | proc        | root@10.10.11.10  | 0000-00-00 00:00:00 | Select     |             |
| %         | mysql | bob        | slow_log    | root@10.10.11.10  | 0000-00-00 00:00:00 | Select     |             |
| %         | mysql | newuser1   | general_log | root@10.10.11.10  | 0000-00-00 00:00:00 | Select     |             |
| localhost | mysql | newuser1   | general_log | root@10.10.11.10  | 0000-00-00 00:00:00 | Select     |             |
+-----------+-------+------------+-------------+-------------------+---------------------+------------+-------------+

CPU stress

Running below on db.t3.small aurora takes around 2-5 minutes, you may loose the connection but it will continue running in the background.

DELIMITER $$
DROP PROCEDURE IF EXISTS StressCPU;
CREATE  PROCEDURE StressCPU()
BEGIN
  DECLARE counter INT DEFAULT 1;
  DECLARE max_counter INT DEFAULT 50000000;
  DECLARE val float8;
  WHILE counter <= max_counter DO
    SET val = POW(70,70);
    SET counter = counter + 1;
  END WHILE;
END$$

CALL StressCPU();

SHOW FULL PROCESSLIST;

AWS - Aurora logs

You can control MySQL logging by using the parameters in this list:

  • slow_query_log: To create the slow query log, set to 1. The default is 0.
  • general_log: To create the general log, set to 1. The default is 0.
  • long_query_time: To prevent fast-running queries from being logged in the slow query log, specify a value for the shortest query execution time to be logged, in seconds. The default is 10 seconds; the minimum is 0. If log_output = FILE, you can specify a floating point value that goes to microsecond resolution. If log_output = TABLE, you must specify an integer value with second resolution. Only queries whose execution time exceeds the long_query_time value are logged. For example, setting long_query_time to 0.1 prevents any query that runs for less than 100 milliseconds from being logged.
  • log_queries_not_using_indexes: To log all queries that do not use an index to the slow query log, set to 1. The default is 0. Queries that do not use an index are logged even if their execution time is less than the value of the long_query_time parameter.
  • log_output option: You can specify one of the following options for the log_output parameter.
    • TABLE (default)– Write general queries to the mysql.general_log table, and slow queries to the mysql.slow_log table.
    • FILE– Write both general and slow query logs to the file system. Log files are rotated hourly. Required to send logs to CloudWatch Log Group.
    • NONE– Disable logging.

Advanced auditing

  • QUERY_DCL – Similar to the QUERY event, but returns only data control language (DCL) queries (GRANT, REVOKE, and so on).
  • QUERY_DDL – Similar to the QUERY event, but returns only data definition language (DDL) queries (CREATE, ALTER, and so on).


Publish Aurora logs to CloudWatch Log Group:

  • log_output - needs to be set to FILE, the mysql.general_log will stop receiving new updates
  • will be created automatically
    • /aws/rds/cluster/<cluster_DB_identifier>/general | LogGroup
      • <db_instance_identifier>-<region> | LogStream
      • <db_instance_identifier>-<us-east-1a> | LogStream
      • <db_instance_identifier>-<us-east-1c2> | LogStream
  • can be created manually including Log Streams; use naming convention as above
  • Modify cluster by Exporting respective logs in the Log Export section; no reboot required


# Enable via Cluster Parameters in the Cluster Parameter Group
general_log     0     #disabled log
slow_log        1     #enabled log
long_query_time 10    #value in seconds, any query running for longer than time set will be logged to slow_log log
log_output      TABLE #redirect all logs to tables

# Read logs from a table
use mysql;
SELECT * FROM mysql.slow_log;
SELECT * FROM mysql.slow_log_backup;
SELECT * FROM mysql.general_log;
SELECT * FROM mysql.general_log_backup;
SELECT * FROM mysql.slow_log;
SELECT * FROM mysql.slow_log_backup;

#Rotate logs, will clear general_log and move data to general_log_backup table
#Running it twice will clear both tables
CALL mysql.rds_rotate_general_log;

#Check TABLE log size
SELECT COUNT(*) FROM `mysql.general_log`; #count a table rows
SELECT table_name AS `mysql.general_log`, round(((data_length + index_length) / 1024 / 1024), 2) `Size (MB)` FROM information_schema.TABLES WHERE table_schema = "mysql";

Align SQL inserts by a comma

cat inserts.sql | sed 's/`,/`@,/g' | sed "s/',/'@,/g" | sed "s/,'/@,'/g" | column -t -s "@" > inserts-aligned.sql
# accounts for `,
# accounts for ',
# accounts for ,'

SSL/TLS connections

Note: MySQL doesn't use raw TLS on the wire for its encrypted connections. Instead, it performs a protocol handshake in the MySQL layer to enable TLS before it starts to be used. That's similar to FTP or SMTP which use AUTH TLS and STARTTLS respectively to enable TLS, and that's what the -starttls argument in the s_client command does. curl doesn't support the MySQL protocol so it can't do this.


RDS MySQL can use SSL to encrypt connection. More info read here:

Commands

SELECT * FROM information_schema.SESSION_STATUS;

show variables like '%ssl%';
'have_openssl', 'YES'
'have_ssl', 'YES'        # <- db supports ssl
'ssl_ca', '/rdsdbdata/rds-metadata/ca-cert.pem'
'ssl_capath', ''
'ssl_cert', '/rdsdbdata/rds-metadata/server-cert.pem'
'ssl_cipher', 'EXP1024-RC4-SHA:EXP1024-DES-CBC-SHA:...:EXP-EDH-DSS-DES-CBC-SHA'
'ssl_crl', ''
'ssl_crlpath', ''
'ssl_key', '/rdsdbdata/rds-metadata/server-key.pem'


JDBC secure connection

Listed below is a code example showing how to communicate with a MySQL database using SSL and JDBC. The useSSL=true property is added to the JDBC URL to attempt to communicate via SSL. The requireSSL=true property can be added to only connect if the database server supports SSL. The verifyServerCerticate=false property is set to bypass certificate validation.

import java.sql.*;
public class TestMySQLSSL
{
	public static void main (String[] args)
	{
		Connection con = null;
		try
		{
			String url = "jdbc:mysql://127.0.0.1:3306/sample"+
				"?verifyServerCertificate=false"+
				"&useSSL=true"+
				"&requireSSL=true";
			String user = "testuser";
			String password = "testpass";
				
			Class dbDriver = Class.forName("com.mysql.jdbc.Driver");
			con = DriverManager.getConnection(url, user, password);
		}
		catch (Exception ex)
		{


Setting up wso2 to use SSL when connecting to MySQL DB


Import client and server certificates to the client-truststore of WSO2 server. In case of using AWS you need to import rds-ca-2019-root.

keytool -import -alias rds-ca-2019-root -file /etc/mysql-ssl/rds-ca-2019-root.pem -keystore repository/resources/security/client-truststore.jks
# In case of managing your own mysql instance, import a cert issued by eg. rds-ca-2019-root 
keytool -import -alias wso2qamysqlserver -file  /etc/mysql-ssl/client-cert.pem -keystore repository/resources/security/client-truststore.jks


JDBC string enforcing SSL requires additional parameters:

jdbc:mysql://10.10.10.10:3306/ds21_carbon?autoReconnect=true&amp;useSSL=true&amp;requireSSL=true


Datasource in master-datasources.xml would look like below. ds21_carbon it's database schema name.

<configuration>
    <url>jdbc:mysql://10.10.10.10:3306/ds21_carbon?autoReconnect=true&amp;useSSL=true&amp;requireSSL=true</url>
    <username>root</username>
    <defaultAutoCommit>false</defaultAutoCommit>
    <password>root</password>
    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
    <maxActive>80</maxActive>
    <maxWait>60000</maxWait>
    <minIdle>5</minIdle>
    <testOnBorrow>true</testOnBorrow>
    <validationQuery>SELECT 1</validationQuery>
    <validationInterval>30000</validationInterval>
</configuration>