MySQL笔记 - 用户管理

MySQL笔记 – 用户管理

tags: 数据库 MySQL 用户管理

学习目标

MySQL是一个多用户数据库,具有功能强大的访问控制系统,可以为不同用户指定允许的权限。

MySQL用户可以分为普通用户和root用户。root用户是超级管理员,拥有所有权限,包括创建用户、删除用户和修改用户的密码等管理权限;普通用户只有被授予的各种权限。

用户管理包括管理用户账户、权限等。

1. 权限表

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在MySQL数据库中,由MySQL_install_db脚本初始化。

存储账户权限信息表主要有:userhostdbtables_privcolumns_privprocs_priv。本节主要介绍这些表的内容和作用。

1.1 user表

user表是MySQL中最重要的一个权限表,记录允许连接到服务器的账号信息,这里的权限是全局的。

执行mysql> describe mysql.user;命令得到如下显示表信息:

FieldTypeNullKeyDefaultExtra
Hostchar(60)NOPRI
Userchar(32)NOPRI
Select_privenum(‘N’,’Y’)NON
Insert_privenum(‘N’,’Y’)NON
Update_privenum(‘N’,’Y’)NON
Delete_privenum(‘N’,’Y’)NON
Create_privenum(‘N’,’Y’)NON
Drop_privenum(‘N’,’Y’)NON
Reload_privenum(‘N’,’Y’)NON
Shutdown_privenum(‘N’,’Y’)NON
Process_privenum(‘N’,’Y’)NON
File_privenum(‘N’,’Y’)NON
Grant_privenum(‘N’,’Y’)NON
References_privenum(‘N’,’Y’)NON
Index_privenum(‘N’,’Y’)NON
Alter_privenum(‘N’,’Y’)NON
Show_db_privenum(‘N’,’Y’)NON
Super_privenum(‘N’,’Y’)NON
Create_tmp_table_privenum(‘N’,’Y’)NON
Lock_tables_privenum(‘N’,’Y’)NON
Execute_privenum(‘N’,’Y’)NON
Repl_slave_privenum(‘N’,’Y’)NON
Repl_client_privenum(‘N’,’Y’)NON
Create_view_privenum(‘N’,’Y’)NON
Show_view_privenum(‘N’,’Y’)NON
Create_routine_privenum(‘N’,’Y’)NON
Alter_routine_privenum(‘N’,’Y’)NON
Create_user_privenum(‘N’,’Y’)NON
Event_privenum(‘N’,’Y’)NON
Trigger_privenum(‘N’,’Y’)NON
Create_tablespace_privenum(‘N’,’Y’)NON
ssl_typeenum(”,’ANY’,
‘X509′,’SPECIFIED’)
NO
ssl_cipherblobNONULL
x509_issuerblobNONULL
x509_subjectblobNONULL
max_questionsint(11) unsignedNO0
max_updatesint(11) unsignedNO0
max_connectionsint(11) unsignedNO0
max_user_connectionsint(11) unsignedNO0
pluginchar(64)NOmysql_native_password
authentication_stringtextYESNULL
password_expiredenum(‘N’,’Y’)NON
password_last_changedtimestampYESNULL
password_lifetimesmallint(5) unsignedYESNULL
account_lockedenum(‘N’,’Y’)NON

45 rows in set (0.00 sec)

字段说明:

  1. 用户列
    user表的用户信息列包括HostUserauthentication_string,其中HostUser为表的联合主键。authentication_sting为用户密码的哈希值。当一个用户连接时,只有这3个值完全匹配才被允许。
  2. 权限列
    后面带_pri的都是用户权限字段,包括了增、删、改、查等普通权限,还包括了关闭服务器、加载用户等高级权限。普通权限用于对数据库实施操作行为的限制;高级权限用于数据库管理行为。

    user表中对应的权限是针对所有用户数据数据库的。这些字段值的类型为ENUM,可以取值只能为Y和N。修改权限使用grant语句和update语句。

  3. 安全列
    安全列只有6个字段,其中两个是ssl相关,两个是x509相关,另外两个是授权插件相关。
  4. 资源控制列

    • max_questions – 用户每小时允许执行的查询操作次数。
    • max_updates – 用户每小时允许执行的更新操作次数。
    • max_connections – 用户每小时允许执行的连接操作次数。
    • max_user_connections – 用户允许同时建立的连接次数。

1.2 db表和host表

db表和host表是MySQL数据中非常重要的权限表。db表中存储了用户对某个数据库的操作权限,决定用户能从哪个主机存取那个数据库。

执行mysql> describe mysql.db;后显示结果如下:

FieldTypeNullKeyDefaultExtra
Hostchar(60)NOPRI
Dbchar(64)NOPRI
Userchar(32)NOPRI
Select_privenum(‘N’,’Y’)NON
Insert_privenum(‘N’,’Y’)NON
Update_privenum(‘N’,’Y’)NON
Delete_privenum(‘N’,’Y’)NON
Create_privenum(‘N’,’Y’)NON
Drop_privenum(‘N’,’Y’)NON
Grant_privenum(‘N’,’Y’)NON
References_privenum(‘N’,’Y’)NON
Index_privenum(‘N’,’Y’)NON
Alter_privenum(‘N’,’Y’)NON
Create_tmp_table_privenum(‘N’,’Y’)NON
Lock_tables_privenum(‘N’,’Y’)NON
Create_view_privenum(‘N’,’Y’)NON
Show_view_privenum(‘N’,’Y’)NON
Create_routine_privenum(‘N’,’Y’)NON
Alter_routine_privenum(‘N’,’Y’)NON
Execute_privenum(‘N’,’Y’)NON
Event_privenum(‘N’,’Y’)NON
Trigger_privenum(‘N’,’Y’)NON

22 rows in set (0.04 sec)

host表中存储了某个主机对数据库的操作权限,配合db权限表对给定主机上的数据库级操作权限做更细致的控制,这个表不受grantrevoke语句的影响。此表在“Server version: 5.7.20 MySQL Community Server (GPL)”中并未发现。

1.3 tables_priv表和columns_priv表

这2张表分别对具体的表和表中的字段来设置权限。

tables_priv表信息:

;mysql> describe mysql.tables_priv;

FieldTypeNullKeyDefaultExtra
Hostchar(60)NOPRI
Dbchar(64)NOPRI
Userchar(32)NOPRI
Table_namechar(64)NOPRI
Grantorchar(93)NOMUL
TimestamptimestampNOCURRENT_TIMESTAMPon update CURRENT_TIMESTAMP
Table_privset(‘Select’,
‘Insert’,
‘Update’,
‘Delete’,
‘Create’,
‘Drop’,
‘Grant’,
‘References’,
‘Index’,
‘Alter’,
‘Create View’,
‘Show view’,
‘Trigger’)
NO
Column_privset(‘Select’,
‘Insert’,
‘Update’,
‘References’)
NO

8 rows in set (0.04 sec)

columns_priv表信息:

mysql> describe mysql.columns_priv;

FieldTypeNullKeyDefaultExtra
Hostchar(60)NOPRI
Dbchar(64)NOPRI
Userchar(32)NOPRI
Table_namechar(64)NOPRI
Column_namechar(64)NOPRI
TimestamptimestampNOCURRENT_TIMESTAMPon update CURRENT_TIMESTAMP
Column_privset(‘Select’,
‘Insert’,
‘Update’,
‘References’)
NO

7 rows in set (0.02 sec)

1.4 procs_priv表

procs_priv表可以对存储过程和存储函数设置操作权限。

mysql> describe mysql.procs_priv;

FieldTypeNullKeyDefaultExtra
Hostchar(60)NOPRI
Dbchar(64)NOPRI
Userchar(32)NOPRI
Routine_namechar(64)NOPRI
Routine_typeenum(
‘FUNCTION’,
‘PROCEDURE’)
NOPRINULL
Grantorchar(93)NOMUL
Proc_privset(‘Execute’,
‘Alter Routine’,
‘Grant’)
NO
TimestamptimestampNOCURRENT_TIMESTAMPon update CURRENT_TIMESTAMP

rows in set (0.02 sec)

2. 账户管理

2.1 登录和退出MySQL服务器

通过MySQL -help命令可以查看MySQL命令的帮助信息。MySQL命令的常用参数如下:

  • -h 主机名:可以指定主机名称和IP

,如果不指定,默认是localhost。

  • -P 端口号:指定服务器的端口号,默认为3306。
  • -u 用户名:指定用户名。
  • -p密码:可以用使用该参数指定登录密码,注意: 密码与p之间不能有空格。
  • -e "SQL语句":如果指定了该语句,会在登录后执行SQL语句。
  • 数据库名称:可以在命令的最后指定数据库名称。

[例1] 用户root,密码为foo,从主机localhost登录到MySQL服务器,设置test_db数据库为登录后的默认当前数据库。

C:\mysql5.7.2\bin>mysql -h localhost -u root -pfoo test_db
Enter password: *********

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 5.7.20 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select database();

+------------+
| database() |
+------------+
| test_db    |
+------------+
1 row in set (0.00 sec)

[例2] 使用root用户,密码为foo,从主机localhost登录到MySQL服务器,设置缺省数据库为test_db,并执行语句describe test1; select * from test1;

C:\mysql5.7.2\bin>mysql -h localhost -u root -pfoo test_db -e "describe test1; select * from test1"
mysql: [Warning] Using a password on the command line interface can be insecure.

+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a1    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
+------+
| a1   |
+------+
|    1 |
|    3 |
|    4 |
+------+

要退出MySQL服务器登录,请使用quit

mysql> quit
Bye

C:\mysql5.7.2>bin>

2.2 新建普通用户

要创建新用户,必须具有相应的权限来执行创建操作。在MySQL数据库中,有两种方式创建新用户,一种是使用create usergrant语句;另一种是直接操作MySQL授权表。

(1). 使用create user语句创建新用户

create user语句基本语法格式如下:

CREATE USER user_specification[, user_specification]...

user_specification:
user@host [IDENTIFIED BY [PASSWORD] 'password'  |  IDENTIFIED WITH auth_plugin [AS 'auth_sting']]

值得注意的是:如果使用PASSWORD关键字,后面的密码要使用哈希值字符窜,否则'password'使用明文密码。

[例3] 使用create user创建一个用户,用户名是jack,密码是pw,主机名为localhost,语句如下:

mysql> create user `jack`@`localhost` identified by 'pw';
Query OK, 0 rows affected (0.24 sec)

-- 如果使用password关键字则要如下操作:

mysql> select password('pw');
+-------------------------------------------+
| password('pw')                            |
+-------------------------------------------+
| *D821809F681A40A6E379B50D0463EFAE20BDD122 |
+-------------------------------------------+
1 row in set, 1 warning (0.03 sec)

mysql> create user jack1@localhost identified by password '*D821809F681A40A6E379B50D0463EFAE20BDD122';
Query OK, 0 rows affected, 1 warning (0.00 sec)

(2). 使用grant语句创建新用户

基本语法如下:

GRANT privileges ON [object_type] priv_level TO user@host [IDENTIFIED BY 'password'] [, user [IDENTIFIED BY 'password']] [WITH GRANT OPTION]

object_type: {
    TABLE
  | FUNCTION
  | PROCEDURE
}


priv_level: {
    *
  | *.*
  | db_name.*
  | db_name.tbl_name
  | tbl_name
  | db_name.routine_name
}

说明:WITH GRANT OPTION子句表示对新建立的用户赋予GRANT权限,即该用户可以对其他用户赋予权限。

[例4] 使用grant语句创建两个新用户jack2jack3,密码分别为pw1pw2,并授于他们对所有数据表的select和update权限。

mysql> grant select,update on table *.* to jack2@localhost identified by 'pw1', jack3@localhost identified by 'pw2';
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> show warnings;
LevelCodeMessage
Warning1287Using GRANT for creating new user is deprecated and will be removed in future release. Create new user with CREATE USER statement.
Warning1287Using GRANT for creating new user is deprecated and will be removed in future release. Create new user with CREATE USER statement.
2 rows in set (0.00 sec)

-- 查看警告可知,最好不要用grant语句来添加新用户,而要用create user语句添加新用户后再授权。如下所示,则不会出现警告:

mysql> create user jack4@localhost identified by 'pw3';
Query OK, 0 rows affected (0.00 sec)

mysql> grant select, update on table *.* to jack4@localhost;
Query OK, 0 rows affected (0.00 sec)

对于用户名到底是使用user@host,还是user呢?请点此进一步查看,简单来说指定user就是要同时指定用户和主机,这两个是一体的。

(3). 直接对user表进行操作

在MySQL中create usergrant语句都是实际上都是对user表进行操作,但一般不建议这样做,除非特殊情况或者极熟悉MySQLuser表中的各项设置才可以。

[例5] 使用insert创建一个新账户

mysql> insert into mysql.user (host,user,authentication_string)
    ->     values('localhost', 'jack5', password('pw'));
    
ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value

mysql> show warnings;
LevelCodeMessage
Warning1681‘PASSWORD’ is deprecated and will be removed in a future release.
Error1364Field ‘ssl_cipher’ doesn’t have a default value
Error1364Field ‘x509_issuer’ doesn’t have a default value
Error1364Field ‘x509_subject’ doesn’t have a default value
4 rows in set (0.01 sec)

由提示信息可以看出并未添加成功,需要指定多个相关字段才能添加成功,所以请使用MySQL提供的标准的语句。

2.3 删除普通用户

(1). 使用drop user语句删除用户

基本语法:

drop user user [, user];

[例6] 删除用户jack4@localhost。

mysql> drop user jack4@localhost;
Query OK, 0 rows affected (0.02 sec)

(2). 直接对user表进行操作

[例7] 删除用户jack3@localhost。

mysql> delete from mysql.user where user='jack3' and host='localhost';
Query OK, 1 row affected (0.16 sec)

2.4 root用户修改自己的密码

(1). 使用mysqladmin命令在命令行中修改密码

[例8] 将root用户的密码修改为”xfoox”

C:\>mysqladmin -u root -h 192.168.1.33 -pfoo  password "xfoox"
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.

说明: -p的密码foo是紧跟着的,不能有空格;password后面的密码要使用双引号;如果省略掉-p后面的密码会要求你输入原密码。当然你可以使用SSL连接服务器,以增加安全性,MySQL开启SSL安全连接的文章请点此访问

(2). 使用set password语句修改密码

正常登陆服务器后,使用如下语句修改:

mysql> set password=password("foo");
Query OK, 0 rows affected (0.14 sec)

注意:在最新版本的MySQL8.0中并不支持password函数,只需要直接写密码即可。

(3). 直接修改user表

mysql> update mysql.user set password=password("foo") where user = "root" and host = "localhost";
ERROR 1054 (42S22): Unknown column 'password' in 'field list'

mysql> update mysql.user set authentication_string=password("foo") where user = "root" and host = "localhost";
Query OK, 0 rows affected, 1 warning (0.15 sec)
Rows matched: 1  Changed: 0  Warnings: 1

mysql> flush privileges;
Query OK, 0 rows affected (0.17 sec)

注意:一般不要使用这种方法,因为每个版本的密码存贮字段名可能不同,最后要记得使用flush privileges语句来冲洗权限表,然后才可以使用新密码登陆。

2.5 root用户修改普通用户的密码

(1). 使用set password语句修改

mysql> set password for jack@localhost = password('foo');
Query OK, 0 rows affected, 1 warning (0.04 sec)

mysql> show warnings;

| Warning | 1287 | 'SET PASSWORD FOR <user> = PASSWORD('<plaintext_password>')' is deprecated and will be removed in a future release. Please use SET PASSWORD FOR <user> = '<plaintext_password>' instead |

1 row in set (0.00 sec)

(2). 使用grant usage语句来修改

mysql> grant usage on *.* to jack@localhost identified by 'foo';
Query OK, 0 rows affected, 1 warning (0.12 sec)

说明:警告提示仍然为未来版本可能不支持该语句来修改用户的密码。

(3). 直接修改user表

同root用户。

2.6 普通用户修改自的密码

普通用户正常登陆后,使用如下语句修改:

mysql> set password = 'foo';
Query OK, 0 rows affected (0.07 sec)

2.7 root用户密码丢失的解决办法

基本步骤

  1. 越过权限表来启动服务。(MySQL服务名字可以自定义的,请按自己的情况处理,一般为mysql
  2. 修改密码。
  3. 刷新权限表。

详细步骤演示

  1. 打开管理员命令窗口,停止本机的MySQL服务,再用参数--skip-grant-tables来越过权限表的检查来启动服务。

    《MySQL笔记 - 用户管理》

    注意,此时光标会不断闪烁,不要关闭此窗口。

    如果在MySQL8.0版本中,启动服务的命令为:E:\mysql8\bin>mysqld --skip-grant-tables --shared-memory --console ,附加--console是为了将信息输出到控制台,不然信息会不显示。

    E:\mysql8\bin>mysqld --skip-grant-tables --shared-memory  --console
    2018-05-14T11:53:03.811523Z 0 [System] [MY-010116] [Server] E:\mysql8\bin\mysqld.exe (mysqld 8.0.11) starting as process 4472
    2018-05-14T11:53:06.244140Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
    2018-05-14T11:53:06.320312Z 0 [System] [MY-010931] [Server] E:\mysql8\bin\mysqld.exe: ready for connections. Version: '8.0.11'  socket: ''  port: 0  MySQL Community Server - GPL.
    2018-05-14T11:53:06.455078Z 0 [Warning] [MY-011311] [Server] Plugin mysqlx reported: 'All I/O interfaces are disabled, X Protocol won't be accessible'
    (注:光标会在这里闪烁)
    (注:在进行完第3步后,在这里我按了Ctrl+c终止,下面是按键完毕后的输出:)
    2018-05-14T12:02:51.10644^5CZ 0 [System]
    
    E:\mysql8\bin> [MY-013105] [Server] E:\mysql8\bin\mysqld.exe: Normal shutdown.
    2018-05-14T12:02:53.120117Z 0 [Warning] [MY-010909] [Server] E:\mysql8\bin\mysqld.exe: Forcing close of thread 9  user: 'root'.
    2018-05-14T12:02:54.515625Z 0 [System] [MY-010910] [Server] E:\mysql8\bin\mysqld.exe: Shutdown complete (mysqld 8.0.11)  MySQL Community Server - GPL.
  2. 打开新的命令窗口,使用root用户登陆,由于越过了权限表,此时虽然要求输入密码,但只需要回车即可,登录后修改密码。

    C:\mysql -u root -p
    enter password:       (此处直接回车即可)
    
    mysql> update mysql.user set authentication_string = password('foo') where user='root' and host='localhost';
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    Rows matched: 1  Changed: 0  Warnings: 1
    

    注意:在5.7版本以前的密码是存储在password字段里的,以后的版本存储在authentication_string字段里,并且在MySQL8.0以后,password()函数也被取消了,采用了caching_sha2_password的加密验证方式,所以,只能把密码字段先用空白字窜替换,即:authentication_string='',然后重新登陆,因为密码为空白,所以只需要回车即可,然后使用alter user root@localhost identified by 'foo';语句来更改密码。

  3. 刷新权限

    mysql> flush privileges;
    Query OK, 0 rows affected (0.00 sec)

    最后关闭管理员窗口,退出登录,即可重新使用新密码连接服务器。

    注意:有时关闭了管理员命令窗口,一般MySQL服务仍然会在后台运行,但有时却不行。如果不能正常登陆,请查看进程,杀掉后,再使用net start mysql启动MySQL服务即可.(MySQL服务名字可以自定义的,请按自己的情况处理

    原文作者:淡夜无声
    原文地址: https://segmentfault.com/a/1190000014856560
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞