View information about MySQL databases

To view information about MySQL databases and their tables, we first connect to the MySQL console, for example, as root:

mysql -u root

Or so, if you need to enter a password:

mysql -u root -p

Let’s see a list of existing databases:

SHOW DATABASES;

You can select a database like this:

USE dbname;

See which database is currently selected:

SELECT DATABASE();

To see which tables the selected database contains:

SHOW TABLES;

Example of viewing the contents of the specified table:

SELECT * FROM tablename LIMIT 25;

To view the structure of a particular table, execute the command:

DESCRIBE tablename;

Where Field is the name of the column, Type is the data type, Null – determines whether the column can contain NULL values, Key – whether the column is indexed, Default – determines the default value for the column.

To see information about the indexes of the table, you can do this:

SHOW INDEX FROM tablename;

View information about the table, the encoding, its type (ENGINES), etc. you can use:

SHOW CREATE TABLE tablename;

To see what types the server supports, you can do this:

SHOW ENGINES;

Executing a SQL query from a script in Linux

It was necessary recently to write a script that executes a sql query into the MySQL database.
Example content:

# Description, here I wrote for others that the script is added to the crontab, so that it is not moved
mysql -u USER -pPASSWORD -h 127.0.0.1 -e "UPDATE nika_system.abon SET otkl=0 WHERE depozit > '10' AND (otkl='-1' OR otkl='-2');";

In order for the script to run automatically, open the crontab file in any text editor (in the nano editor CTRL+X for the output and y/n for saving or canceling the changes):

sudo nano /etc/crontab

Add the following line to it:

0 9 * * * root /home/nika/scripts/reset_credit_nika.sh > /dev/null 2>&1

Now every day at 9 am the script will be executed.

Here is an example of daily automatic output of data from a sql table into a text file:

#!/bin/bash
mysql -u USER -pPASSWORD -h 192.168.1.1 -s -N -e "SELECT id FROM nika_system.abon WHERE tarif=109;";

In /etc/crontab we add:

0 8 * * * root /scripts/freektb.sh > /srv/samba/dir/mirazh/$(date +%Y-%m-%d).txt

For security reasons, it’s better not to specify the password in scripts, see my article – Connecting to MySQL from localhost without entering a password

IPTables rules for MySQL

If iptables locks all incoming connections (INPUT DROP) and to add external access to MySQL, you need to add rules:

iptables -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT

To access only a particular network, for example 10.0.0.0/24:

iptables -A INPUT -s 10.0.0.0/24 -p tcp -m tcp --dport 3306 -j ACCEPT

To remove a rule, we’ll specify the same command, replacing -A with -D, for example:

iptables -D INPUT -p tcp -m tcp --dport 3306 -j ACCEPT

To view the list of rules, use the command:

sudo iptables -nvL

I note that in order to open external access, you also need to comment out the line “bind-address = 127.0.0.1” in the my.cnf configuration file.

If by default INPUT ACCEPT, we first specify which IPs are allowed access, and only the last rule is blocked by all the others:

/sbin/iptables -A INPUT -s 127.0.0.1 -p tcp --destination-port 3306 -j ACCEPT
/sbin/iptables -A INPUT -s 192.168.1.5 -p tcp --destination-port 3306 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 3306 -j DROP

For example, using nmap, you can check locally and externally whether the access is filtered:

nmap -p 3306 localhost
nmap -p 3306 192.168.1.5

See also:
Configuring IPTables
Other my articles about MySQL

Solution of the error “Using unique option prefix pass instead of password is deprecated …”

I noticed some errors coming to the root mail with the subject and the text:

Cron /usr/bin/test -x /usr/local/cpanel/scripts/update_db_cache && /usr/local/cpanel/scripts/update_db_cache
Warning: Using unique option prefix pass instead of password is deprecated and will be removed in a future release. Please use the full name instead.

The problem lies in the file ~ / .my.cnf, that is /root/.my.cnf in my case.

In which the parameter “pass” is obsolete and must be changed to a new “password”.

For example, that’s how it was when the error occurred:

[client]
user=root
pass=password

Changed to password and the error disappeared:

[client]
user=root
password=password

See also:
Connecting to MySQL from localhost without entering a password

Change max_connections in MySQL

Normally, the parameter max_connections in MySQL is set to 151 and allowed for one connection more, that is, there may be 152 connections.
If there are more connections, there will be a “too many connections” error.
On an example I use MySQL 5.5.54.

To increase the value, we connect to MySQL:

mysql -u root -p

Let’s see a list of current connections:

show processlist;
SHOW FULL PROCESSLIST\G
show status where `variable_name` = 'Threads_connected';

Let’s see the current value of max_connections:

show variables like "max_connections";

If you need to increase it without restarting MySQL (it will work before restarting MySQL):

set global max_connections = 300;

So that after the restart of MySQL the value of max_connections is preserved, in the configuration file /etc/mysql/my.cnf, in the [mysqld] section we specify it:

max_connections = 300

How to fix error “Table ‘name’ is marked as crashed and last (automatic?) repair failed”

Once in the FreeRADIUS logs I noticed a MySQL error:

Table ‘./radius/radacct’ is marked as crashed and last (automatic?) repair failed

As it turned out, the radacct table was damaged, since the data there were not particularly important, then the entire table was cleaned.
You can clean up via phpMyAdmin or SQL query:

truncate table TableName

A bit later for the experiment I decided to break the whole database, took another large table in general from another application, about 8 gigabytes in size and 80 million lines.
I applied to it SQL query to clean up old rows before the date specified in the query and rebooted at that moment MySQL, the request was interrupted, the database was left intact, executed the request to optimize the database and again rebooted MySQL, eventually got a corrupted database and a similar error:

#144 – Table ‘name’ is marked as crashed and last (automatic?) repair failed

To restore the database, you must stop the MySQL server (if the table is not used, then you can not stop it):

sudo service mysql stop

Let’s move to the directory with the database:

cd /var/lib/mysql/$DATABASE_NAME

Execute the command to restore the specified table:

myisamchk -r -o -f -v $TABLE_NAME

Upon completion, if you stopped the MySQL server, then run it:

sudo service mysql start

Similarly, on the test, also to speed up the process, the table was restored by copying it to another more powerful server, namely three files /var/lib/mysql/$DATABASE_NAME/ ($TABLE_NAME.MYD, $TABLE_NAME.MYI, $TABLE_NAME.frm).

How to change MySQL database encoding and its tables

Here is an example of changing the MySQL encoding of a database and tables.
Before any actions on important data it is necessary to make a backup copy, for example:

mysqldump -u USER -h localhost -p BASE | gzip -c > backup_base_`date +%Y-%m-%d`.sql.gz

For the test, we will connect to MySQL and create a couple of new databases without specifying the encoding and specifying:

mysql -u root -p
CREATE DATABASE test_db1;
CREATE DATABASE test_db2 CHARACTER SET utf8 COLLATE utf8_general_ci;

Create a test table in the first database and see its encoding:

USE test_db1;

CREATE TABLE users (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50),
reg_date TIMESTAMP
);

show table status like 'users';

Create a test table in the second database and see its encoding:

USE test_db2;

CREATE TABLE users (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50),
reg_date TIMESTAMP
);

show table status;

Let’s also look at the encoding of both databases:

SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = "test_db1";
SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = "test_db2";

To see the encoding of a column in a specific table, you can do this:

SELECT character_set_name FROM information_schema.`COLUMNS`
WHERE table_schema = "test_db1"
AND table_name = "users"
AND column_name = "firstname";

In my case, the table in the first database was encoded with latin1_swedish_ci, since it is standard, and in the second one utf8_general_ci, since I specified it beforehand.

You can see the table of possible encodings by such requests:

show collation;
show collation like 'utf8%';
show collation like 'latin1%';

View existing databases as follows:

show databases;

View existing tables in the database:

USE test_db1;
show tables;

Now we change the encoding of the first database and its tables to utf8 and immediately check:

ALTER DATABASE `test_db1` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE test_db1;
ALTER TABLE `test_db1`.`users` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
show table status;

If you need to change the encoding in a sql file, open it in the Notepad ++ editor, for example, convert it to UTF-8/without BOM, and if the encoding in SET NAMES is specified at the beginning of the file, change it there, then you can import the file into the database.

How to create a MySQL user and configure access rights

To create a user, we first connect to the MySQL server console:

mysql

Let’s see what users are:

select * from mysql.user;
select user,host from mysql.user;

Create a user (where localhost is specified from where the user can connect, you can specify the IP address, localhost – from the local machine where the MySQL server itself, or % from any addresses):

CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';

If you intend to connect not only locally, you need to comment out the line in my.cnf:

#bind-address = 127.0.0.1

And restart the MySQL server:

sudo service mysql restart

After that, I recommend restricting access to MySQL using IPTables.
See also – Configuring IPTables

To assign the newly created user unlimited permissions to a specific database, execute the following command:

GRANT ALL PRIVILEGES ON database_name.* TO 'user'@'localhost';

If necessary on all bases:

GRANT ALL PRIVILEGES ON *.* TO 'user'@'localhost';

You can specify specific access rights:

GRANT SELECT ON database_name.* TO 'user'@'localhost';
GRANT SELECT, INSERT ON database_name.table_name TO user@192.168.1.5;

If you want to create a new database:

CREATE DATABASE database_name;

For the changes to take effect, execute:

FLUSH PRIVILEGES;

You can delete the user as follows:

DROP USER 'user'@'localhost';

Example of viewing privileges:

SHOW GRANTS FOR 'user'@'localhost';
SHOW GRANTS;
SELECT * FROM information_schema.user_privileges;