MySQL administration¶
Getting started with MySQL Access Control system¶
MySQL implements a sophisticated access control and privilege system that allows you to create comprehensive access rules for handling client operations and effectively preventing unauthorized clients from accessing the database system.
The MySQL access control has two stages when a client connects to the server: - Connection verification: aclient, which connects to the MySQL database server, needs to have a valid username and password. In addition, the host from which the client connects has to match the host in the MySQL grant table. - Request verification: once a connection is established successfully, for each statement issued by the client, MySQL checks whether the client has sufficient privileges to execute that particular statement. mySQL has the ability to check a privilege at the database, table, and field levels.
There is a datbase named mysql
created automatically by MySQL installer. The mysql
database contains five main grant tables. You often manipulate these tables indirectly through the statements such as GRAND
and REVOKE
.
- user
- contains user account and global privilege columns. MySQL uses the user
table to either accept or reject a connection from a host. A privilege granted in the user
table is effective to all databases on the MySQL server.
- db
- contains database level privileges. MySQL uses the db
table to determine which database a user can access and from which host. A privilege granted a the database level in the db
table applies to the database and all objects belong to that database e.g. tables, triggers, views, stored procedures etc.
- table_priv
and columns_priv
- contains table-level and column-level privileges. A privilege granted in the table_priv
table applies to the table and it's columns while a privilege granted in columns_priv
table applies only to a specific column of a table.
procs_priv
contains stored functions and stored procedures privileges.
MySQL makes use of these tables to control the privileges of MySQL database server. Understanding tables is very important before you can implement you own flexible access control system.
Create user accounts using CREATE USER statement¶
In MySQL , you can specify not only who can connect to the database server but also from which host that the user connects. Therefore, a user account in MySQL consists of a username and a host name separated by the @
character.
For example, if the admin
user connects to the MySQL database server from localhost
, the user account is admin@localhost
.
The admin
user only can connect to the MySQL database server from the localhost
, not from a remote host. This makes the MySQL database server even more secure.
In addition, by combining the username and host, it is possible to setup multiple accounts with the same name but can connect from different hosts with different privileges.
MySQL stored the user accounts in the user
grants table of the mysql
database.
Creating user accounts using MySQL CREATE USER statement¶
MySQL provides CREATE USER
statement that allows you to create a new user account. The syntax of the CREATE USER
statement is as follows:
CREATE USER user_account IDENTIFIED BY password;
The user_acount
in the format 'username'@'hostname'
is followed by the CREATE USER
clause.
The password is specified in the IDENTIFIED BY
clause. The password must be in clear text. MySQL will encrypt the password before saving the user account into the user
table.
CREATE USER dbadmin@localhost
IDENTIFIED BY 'secret';
To view the privileges of a user account, you use the SHOW GRANTS
statements as follows:
SHOW GRANTS FOR dbadmin@localhost;
+---------------------------------------------+
| Grants for dbadmin@localhost |
+---------------------------------------------+
| GRANT USAGE ON *.* TO `dbadmin`@`localhost` |
+---------------------------------------------+
1 row in set (0.00 sec)
The . n the result shows that the dbadmin
user account can only login to the database server and has no other privileges. To grant permission to the user, you use the GRANT
statement.
Note that the part before the dot represents the database and the dot represents the table.
To allow a user to connect from any host, you use the percent (%) wildcard as shown in the example:
CREATE USER superadmin@'%'
IDENTIFIED BY 'secret';
The percent wildcard has the same effect as it is used in the LIKE
operator, e.g., to allow mysqladmin
user account to connect to the database server from any subdomain of the mysqltutorial.org
host, you use the percent wildcard %
as follows:
CREATE USER mysqladmin@'%.mysqltutorial.org'
IDENTIFIED by 'secret';
You can also use the underscode wilcard _
.
If you omit the hostname
part of the user account, MySQL will accept it and allow the user to connect from any host.
Change user password¶
Using UPDATE statement¶
The first way to change the password is to use the UPDATE
statement to update the user
table of the mysql
database. After executing the UPDATE
statement, you also need to execute the FLUSH PRIVILEGES
statement to reload privileges from the grant table in the mysql
database.
USE mysql;
UPDATE user
SET password = PASSWORD('dolphin')
WHERE user = 'dbadmin' AND
host = 'localhost';
FLUSH PRIVILEGES;
Note that from MySQL 5.7.6, the user table uses the authentication_string
column only to store the password. In addition, it removed the password column.
Therefore if you use MySQL 5.7.6+, you must use the authentication_string
column in the UPDATE
statement instead:
USE mysql;
UPDATE user
SET authentication_string = PASSWORD('dolphin')
WHERE user = 'dbadmin' AND
host = 'localhost';
FLUSH PRIVILEGES;
Notice that the PASSWORD()
function computes the hash value from plain text.
Change user password using the SET PASSWORD¶
SET PASSWORD FOR 'dbadmin'@'localhost' = PASSWORD('bigshark');
From version 5.7.6, MySQL deprecated this syintax and may remove it in the future releases. Instead, it uses the plaintet password as follows:
SET PASSWORD FOR 'dbadmin'@'localhost' = bigshark;
Change mysql user password using ALTER USER¶
ALTER USER dbadmin@localhost IDENTIFIED BY 'lit
In case you want to reset the password of the MySQL root
account, you need to force the MySQL database server to stop and restart without using grant table validation.
Use GRANT statement to grant privileges to a user¶
After creating a new user account, the user doesnt have any privileges. To grant privileges to a user account, you use the GRANT
statement:
GRANT privilege,[privilege],.. ON privilege_level
TO user [IDENTIFIED BY password]
[REQUIRE tsl_option]
[WITH [GRANT_OPTION | resource_option]];
- First, specify one or more privileges after the
GRANT
keyword. If you grant the user multiple privileges, each privilege is separated by a comma. - Next, specify the
privilege_level
that determines the level at which the privileges apply. MySQL supports global (*.*
), database (database.*
), table (database.table
) and columns levels. If you use column privilege level, you must specify one or a list of comma-separated column after each privilege. - Then, place the user that you want to grant privileges. If user already exists, the
GRANT
statement modifies its privilege. Otherwise, theGRANT
statement creates a new user. The optional clauseIDENTIFIED BY
allows you set a new password for the user. - After that, you specify whether the user has to connect to the database server over a secure connection such as SSL, X059, etc.
- Finally, the optional
WITH GRANT
option clause allows you to grant other users or remove from other users the privileges that you possess. In addition, you can use theWITH
clause to allocate MySQL database server's resource e.g., to set how many connections or statements that the user can use per hour. This is very helpful in the shared environments such as MySQL shared hosting.
Notice that in order to use the GRANT
statement, you must have the GRANT OPTION
privilege and the privileges that you are granting. If the read_only
system variable is enabled, you need to have the SUPER
privilege to execute the GRANT
statement.
CREATE USER super@localhost IDENTIFIED BY 'dolphin';
GRANT ALL ON *.* TO 'super'@'localhost' WITH GRANT OPTION;
CREATE USER auditor@localhost IDENTIFIED BY 'whale';
GRANT ALL ON classicmodels.* TO auditor@localhost;
CREATE USER rfc IDENTIFIED BY 'shark';
GRANT SELECT, UPDATE, DELETE ON classicmodels.* TO rfc;
The following table illustrates all permissible privileges that you can use the GRANT
and REVOKE
statement:
Privilege | Meaning | Level | |||||
Global | Database | Table | Column | Procedure | Proxy | ||
ALL [PRIVILEGES] | Grant all privileges at specified access level except GRANT OPTION | ||||||
ALTER | Allow user to use of ALTER TABLE statement | X | X | X | |||
ALTER ROUTINE | Allow user to alter or drop stored routine | X | X | X | |||
CREATE | Allow user to create database and table | X | X | X | |||
CREATE ROUTINE | Allow user to create stored routine | X | X | ||||
CREATE TABLESPACE | Allow user to create, alter or drop tablespaces and log file groups | X | |||||
CREATE TEMPORARY TABLES | Allow user to create temporary table by using CREATE TEMPORARY TABLE | X | X | ||||
CREATE USER | Allow user to use the CREATE USER, DROP USER, RENAME USER, and REVOKE ALL PRIVILEGES statements. | X | |||||
CREATE VIEW | Allow user to create or modify view. | X | X | X | |||
DELETE | Allow user to use DELETE | X | X | X | |||
DROP | Allow user to drop database, table and view | X | X | X | |||
EVENT | Enable use of events for the Event Scheduler. | X | X | ||||
EXECUTE | Allow user to execute stored routines | X | X | X | |||
FILE | Allow user to read any file in the database directory. | X | |||||
GRANT OPTION | Allow user to have privileges to grant or revoke privileges from other accounts. | X | X | X | X | X | |
INDEX | Allow user to create or remove indexes. | X | X | X | |||
INSERT | Allow user to use INSERT statement | X | X | X | X | ||
LOCK TABLES | Allow user to use LOCK TABLES on tables for which you have the SELECT privilege | X | X | ||||
PROCESS | Allow user to see all processes with SHOW PROCESSLIST statement. | X | |||||
PROXY | Enable user proxying. | ||||||
REFERENCES | Allow user to create foreign key | X | X | X | X | ||
RELOAD | Allow user to use FLUSH operations | X | |||||
REPLICATION CLIENT | Allow user to query to see where master or slave servers are | X | |||||
REPLICATION SLAVE | Allow the user to use replicate slaves to read binary log events from the master. | X | |||||
SELECT | Allow user to use SELECT statement | X | X | X | X | ||
SHOW DATABASES | Allow user to show all databases | X | |||||
SHOW VIEW | Allow user to use SHOW CREATE VIEW statement | X | X | X | |||
SHUTDOWN | Allow user to use mysqladmin shutdown command | X | |||||
SUPER | Allow user to use other administrative operations such as CHANGE MASTER TO, KILL, PURGE BINARY LOGS, SET GLOBAL, and mysqladmin command | X | |||||
TRIGGER | Allow user to use TRIGGER operations. | X | X | X | |||
UPDATE | Allow user to use UPDATE statement | X | X | X | X | ||
USAGE | Equivalent to “no privileges” |
Revoking privileges from users using MySQL REVOKE¶
REVOKE privilege_type [(column_list)]
[, priv_type [(column_list)]]...
ON [object_type] privilege_level
FROM user [, user]..
Revoke all privileges from a user
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user]…
Revoke proxy user
REVOKE PROXY ON user FROM user [, user]...
View grants
SHOW GRANTS FOR user;
CREATE USER IF EXISTS rfc IDENTIFIED BY 'dolphin';
GRANT SELECT, UPDATE, DELETE ON classicmodels.* TO rfc;
REVOKE UPDATE, DELETE ON classicmodels.* FROM rfc;
MySQL Roles¶
Typically, you have a number of users with the same set of privileges. Previously the only way to grant and revoke privileges to multiple users is to change privileges of each user individually, which is time-consuming.
To make it easier, MySQL provided a new object called role that is named collection of privileges.
If you want to grant the same set of privileges to multiple users you should do as follows: 1. Create a new role 2. Grant privileges to the role 3. Grant the role to the users
In case you want to change the privileges of the users, you need to change the privileges of the granted role only. The changes will take effect to all users to which the role granted.
CREATE ROLE crm_dev, crm_read, crm_write;
GRANT ALL ON crm.* TO crm_dev;
GRANT SELECT ON crm.* TO crm_read;
GRANT INSERT, UPDATE, DELETE ON crm.* TO crm_write;
-- developer user
CREATE USER crm_dev1@localhost IDENTIFIED BY 'Secure$1782';
-- read access user
CREATE USER crm_read1@localhost IDENTIFIED BY 'Secure$5432';
-- read/write users
CREATE USER crm_write1@localhost IDENTIFIED BY 'Secure$9075';
CREATE USER crm_write2@localhost IDENTIFIED BY 'Secure$3452';
GRANT crm_dev TO crm_dev1@localhost;
GRANT crm_read TO crm_read1@localhost;
GRANT crm_read, crm_write TO crm_write1@localhost, crm_write2@localhost;
Set default role
SET DEFAULT ROLE ALL TO crm_read1@localhost;
REVOKE INSERT, UPDATE, DELETE ON crm.* FROM crm_write;
GRANT INSERT, UPDATE, DELETE ON crm.* FOR crm_write;
DROP ROLE role_name, role_name, ...;
DROP ROLE crm_read, crm_write;
Copy privileges from one user to another
GRANT crm_dev1@localhost TO crm_dev2@localhost;
Setting active roles¶
A user account can modify the current user's effective privileges within the current session by specifying which granted role is active.
The following statement set the active role to NONE
, meaning no active role.
SET ROLE NONE;
To set active roles to all granted role, you use:
SET ROLE ALL;
To set active roles to default roles that set by the SET DEFAULT ROLE
statement, you use:
SET ROLE DEFAULT;
To set active named roles you use:
SET ROLE granted_role_1, granted_role_2;
````
## Remove user accounts using DROP USER statement
```sql
DROP USER dbadmin@mysqltutorial.org;
If the user has an active session, you should kill the session before using DROP USER
.
It can be done by finding the process id with SHOW PROCESSLIST
and using the KILL
command.
Maintaining MySQL database tables¶
MySQL provides several useful statements that allow you to maintain database tables effectively. Those statements enable you to analyze, optimize, check and repair database tables.
Analyze table statement¶
MySQL query optimizer is an important component of the MySQL server that creates an optimal query execution plan for a query. For a particular query, the query optimizer uses the stored key distribution and other factors to decide the order in which tables should be joined when you performing the join, and which index should be used for a specific table.
However, the key distributions can be sometimes inaccurate e.g., after you have done a lot of data changes in the table including insert, delete or update. If the key distribution is not accurate, the query optimizer may pick a bad query execution plan that may cause a severe performance issue.
To solve this problem you can run the ANALYZE TABLE
statement for the table e.g., the following stateement analyzes the payments table:
ANALYZE TABLE payments;
If there is no change to the table since the ANALYZE TABLE statement ran, MySQL will not analyze the table again. If you run the statement again, it will say it is already up to date.
Optimize table statement¶
While working with the database, you do a log of changes surch as inser, update and delete data in the table that may cause the physical storage of the table fragmented. As a result the performance of database server is degraded.
MySQL provides you wih a statement that allows you to optimize the table to avoid this defragmenting problem. The following illustrates how to optimize a table:
OPTIMIZE TABLE table_name;
It is recommended that you execute this statement for the tables that are updated frequently.
Check table statement¶
Something wrong can happen to the database server e.g., the server was shut down unexpectedly, error while writing data to the hard disk, etc. These situations could make the database operate incorrectly and in the worst case, it can be crashed.
MySQL allows you to check the integrity of database tables by using the CHECK TABLE
statement. The following illustrates the syntax of the CHECK TABLE
statement:
CHECK TABLE table_name;
The CHECK TABLE
statement checks both table and its indexes. This statement only detects problems in a database table but it does not repair them. To repair the table, you use REPAIR TABLE
statement.
Repair table statement¶
The REPAIR TABLE
statement allows you to repair some errors occurred in database tables. MySQL does not guarantee that the REPAIR TABLE
statement can repair all errors that the tables may have.
REPAIR TABLE table_name
Backup databases using mysqldump tool¶
mysqldump -u [username] –p[password] [database_name] > [dump_file.sql]
Backup structure only
mysqldump -u [username] –p[password] –no-data [database_name] > [dump_file.sql]
Backup multiple databases into a single file
mysqldump -u [username] –p[password] [dbname1,dbname2,…] > [dump_file.sql]
mysqldump -u [username] –p[password] –all-database > [dump_file.sql]
Show databases: list all databases in MySQL¶
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| classicmodels |
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
6 rows in set (0.00 sec)
SHOW DATABASES LIKE '%schema';
+--------------------+
| Database (%schema) |
+--------------------+
| information_schema |
| performance_schema |
+--------------------+
2 rows in set (0.00 sec)
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name LIKE '%schema' OR
schema_name LIKE '%s';
+--------------------+
| SCHEMA_NAME |
+--------------------+
| information_schema |
| performance_schema |
| sys |
| classicmodels |
+--------------------+
4 rows in set (0.00 sec)
Show tables: List tables in database¶
+--------------------+
| SCHEMA_NAME |
+--------------------+
| information_schema |
| performance_schema |
| sys |
| classicmodels |
+--------------------+
4 rows in set (0.00 sec)
Include table type (base table or view)
> SHOW FULL TABLES
+-------------------------+------------+
| Tables_in_classicmodels | Table_type |
+-------------------------+------------+
| contacts | VIEW |
| customers | BASE TABLE |
| employees | BASE TABLE |
| offices | BASE TABLE |
| orderdetails | BASE TABLE |
| orders | BASE TABLE |
| payments | BASE TABLE |
| productlines | BASE TABLE |
| products | BASE TABLE |
+-------------------------+------------+
9 rows in set (0.00 sec)
> SHOW TABLES LIKE 'p%';
+------------------------------+
| Tables_in_classicmodels (p%) |
+------------------------------+
| payments |
| productlines |
| products |
+------------------------------+
3 rows in set (0.00 sec)
> SHOW FULL TABLES WHERE table_type = 'VIEW';
+-------------------------+------------+
| Tables_in_classicmodels | Table_type |
+-------------------------+------------+
| contacts | VIEW |
+-------------------------+------------+
1 row in set (0.00 sec)
Show columns and describe¶
mysql> DESCRIBE orders;
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| orderNumber | int(11) | NO | PRI | NULL | |
| orderDate | date | NO | | NULL | |
| requiredDate | date | NO | | NULL | |
| shippedDate | date | YES | | NULL | |
| status | varchar(15) | NO | | NULL | |
| comments | text | YES | | NULL | |
| customerNumber | int(11) | NO | MUL | NULL | |
+----------------+-------------+------+-----+---------+-------+
7 rows in set (0.01 sec)
SHOW COLUMNS FROM table_name;
SHOW COLUMNS FROM database_name.table_name;
SHOW COLUMNS FROM table_name IN database_name;
SHOW FULL COLUMNS FROM table_name;
mysql> SHOW FULL COLUMNS FROM payments \G;
*************************** 1. row ***************************
Field: customerNumber
Type: int(11)
Collation: NULL
Null: NO
Key: PRI
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
*************************** 2. row ***************************
Field: checkNumber
Type: varchar(50)
Collation: latin1_swedish_ci
Null: NO
Key: PRI
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
*************************** 3. row ***************************
Field: paymentDate
Type: date
Collation: NULL
Null: NO
Key:
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
*************************** 4. row ***************************
Field: amount
Type: decimal(10,2)
Collation: NULL
Null: NO
Key:
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment:
4 rows in set (0.01 sec)
mysql> SHOW COLUMNS FROM payments LIKE 'c%';
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| customerNumber | int(11) | NO | PRI | NULL | |
| checkNumber | varchar(50) | NO | PRI | NULL | |
+----------------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
List all users in server¶
SELECT user from mysql.user
Describe user
DESC user;
Show current user
mysql> SELECT user();
+-----------------+
| user() |
+-----------------+
| local@localhost |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT current_user();
+----------------+
| current_user() |
+----------------+
| local@localhost |
+----------------+
1 row in set (0.00 sec)
Show current logged users
SELECT
user,
host,
db,
command
FROM
information_schema.processlist;
+-------+-----------------+---------------+---------+
| user | host | db | command |
+-------+-----------------+---------------+---------+
| local | localhost:50591 | classicmodels | Sleep |
| root | localhost:50557 | NULL | Query |
+-------+-----------------+---------------+---------+
2 rows in set (0.00 sec)
Show processlist¶
Sometimes you may get "too many connections" error returned by the server. To find out the reasons you can use SHOW PROCESSLIST
command and use the KILL
statement to kill the idle threads.
SHOW [FULL] PROCESSLIST;
mysql>SHOW PROCESSLIST;
+----+-----------------+-----------------+---------------+---------+------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------------+---------------+---------+------+------------------------+------------------+
| 4 | event_scheduler | localhost | NULL | Daemon | 2246 | Waiting on empty queue | NULL |
| 14 | root | localhost:50924 | NULL | Query | 0 | starting | SHOW PROCESSLIST |
| 15 | car | localhost:50933 | classicmodels | Sleep | 2 | | NULL |
+----+-----------------+-----------------+---------------+---------+------+------------------------+------------------+
3 rows in set (0.00 sec)
id
- the client process idusder
- the username associated with the threadhost
- the host to which the client is connecteddb
- the default database if one selected otherwiseNULL
.command
- the command typetime
- the number of seconds that the current thread has been in its current statestate
- the thread state which represents an action, event, or state that indicates what thread is executing.info
the statement is executed, orNULL
if it is not executing any statement. If you do not use theFULL
keyword in theSHOW PROCESSLIST
command, then only the first 100 characters of each statement are returned in the info column.