前提要述:参考书籍《MySQL必知必会》
文章目录
17.1 字符集和校对顺序
我们有时候会乱码,主要原因就是字符集的编码设置,这是很多语言都遇到过的问题,数据库也是如此;而校对顺序就是:假如A和a的比较,取决于我们是否区分大小写,这就是需要设置校对顺序。
像我们创建表或数据库时,通常得指定字符集,不然就会给出一个默认的字符集。该默认的字符集在mysql安装目录中名为my.ini的文件中可以看到,也可以修改。下面是我在my.ini的配置:
[mysqld]
# port 3306 端口号
port=3306
# install path 安装路径
basedir=G:\\frame\\MYSQL\\mysql-5.7.24-winx64
# data path 存放数据的路径
datadir=G:\\frame\\MYSQL\\mysql-5.7.24-winx64\\mysqldata
# max_connections 最大连接数
max_connections=200
# max_connect_errors 连接错误5次就拒绝连接(防止黑客侵入数据丢失)
max_connect_errors=5
# charset 默认编码方式
character-set-server=utf8
# default-storage-engine 默认存储引擎
default-storage-engine=INNODB
# plugs 默认密码插件
default_authentication_plugin=mysql_native_password
[mysql]
default-character-set=utf8
[client]
port=3306
default-character-set=utf8
我都把字符集改成默认为utf8。
一些术语:
- 字符集(Character Set)为字母和符号的集合;
- 编码(Encoding)为某个字符集成员的内部表示;
- 校对(也叫字符序)(Collation)为规定字符如何比较的指令。
17.1.1 使用字符集和校对顺序
MySQL支持众多的字符集。为查看所支持的字符集完整列表,使用以下语句:
SHOW CHARACTER SET;
可以看到所有可用的字符集以及每个字符集的描述和默认校对。
查看所支持的校对的完整列表:
SHOW COLLATION;
可以看到所有可用的校对,以及它们适用的字符集。有的字符集不止一种校对。
查看目前我们使用的字符集:
# 查看字符集
SHOW VARIABLES LIKE 'character%'';
下面解释显示的Variable_name:
- character_set_client:客户端来源数据使用的字符集
- character_set_connection:连接层字符集
- character_set_database:当前选中数据库的默认字符集
- character_set_results:查询结果字符集
- character_set_server:默认的内部操作字符集
- character_set_system:系统元数据(字段名等)字符集
为什么会有这么多种字符集?这涉及到转换:(参考别人,最下面有贴转载地址)
MySQL中的字符集转换过程
-
MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
-
进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
- 使用每个数据字段的CHARACTER SET设定值(character_set_system);
- 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
- 若上述值不存在,则使用对应数据库的DEFAULTCHARACTER SET设定值(character_set_database);
- 若上述值不存在,则使用character_set_server设定值。
-
将操作结果从内部操作字符集转换为character_set_results。
可以回忆一下,在创建数据库时我们需要指定字符集和校对顺序;在表中也有指定,不然就默认。这也可看出MySQL对于字符集提供了不同级别的设置,包括server级、database级、table级、column级。其中,中间两个级别就是刚才说的那两种。
而column级可用在表定义列时指定,我们也可以在SELECT语句中指定列的字符集和校对顺序:
SELECT _utf8 '我是小白' COLLATE utf8_general_ci;
而server级则就是我们上面的character_set_server,可用在mysql安装目录的my.ini指定。
查看校对顺序:
# 查看校对顺序
SHOW VARIABLES LIKE 'collation%';
对于校对顺序,一般常使用有两种就是是否区分大小写的校对顺序,像utf8_general_ci是不区分大小写;utf8_bin就区分大小写。名字带有general_ci的时不区分大小写的校对,而不带的就是区分大小写的校对。
下面来个创建表时指定的字符集和校对顺序:
CREATE TABLE mytable
(
c1 INT PRIMARY KEY,
t2 VARCHAR(10),
t3 VARCHAR(10) CHARACTER SET 'utf8' COLLATE 'utf8_bin'
) DEFAULT CHARACTER SET 'utf8'
COLLATE 'utf8_general_ci';
可插入大写A,然后使用WHERE子句试试。
mysql> SELECT * FROM mytable WHERE t2='A';
+----+----+----+
| c1 | t2 | t3 |
+----+----+----+
| 1 | A | A |
+----+----+----+
1 row in set (0.07 sec)
mysql> SELECT * FROM mytable WHERE t2='a';
+----+----+----+
| c1 | t2 | t3 |
+----+----+----+
| 1 | A | A |
+----+----+----+
1 row in set (0.06 sec)
mysql> SELECT * FROM mytable WHERE t3='a';
Empty set
mysql> SELECT * FROM mytable WHERE t3='A';
+----+----+----+
| c1 | t2 | t3 |
+----+----+----+
| 1 | A | A |
+----+----+----+
1 row in set (0.06 sec)
一般,MySQL如下确定使用什么样的字符集和校对:
- 如果指定CHARACTER SET和COLLATE两者,则使用这些值。
- 如果只指定CHARACTER SET, 则使用此字符集以及其默认的校对。
- 如果即不指定CHARACTER SET,也不指定COLLATE,则使用数据库默认的。
COLLATE子句还可以用在GROUP BY、HAVING、聚集函数、别名等。
参考:
Mysql字符集设置
17.2 安全管理
17.2.1 访问控制
MySQL服务器的安全基础是:用户应该对他们需要的数据具有适当的访问权,既不能多也不能少。
回忆前面登录数据库时,用户名使用的是root,它对整个MySQL服务器具有完全的控制。但是在日常工作中,绝不能使用root,应该创建一系列账号,有的用于管理,有的供用户使用,有的供开发人员使用。
17.2.2 管理用户
MySQL用户账号和信息存储在名为mysql的MySQL数据库中。一般不需要直接访问mysql数据库和表(稍后就会知道原因),但有时需要直接访问。需要直接访问它的时机之一是在需要获得所有用户账号列表时。可使用以下代码:
USE mysql;
SELECT user FROM user;
可用多个客户机(mysql命令行多开),其中一个作为管理登录,其他作为被测试的用户登录。
17.2.3 创建用户账号
使用CREATE USER语句:
CREATE USER 'ben' IDENTIFIED BY '123456';
(我测试了好像不一定要在mysql数据库里创建)
解释:可使用这样:'ben’指定用户名,IDENTIFIED BY指定密码。
用户可定义为user@host,比如’ben’@‘localhost’。MySQL的权限用用户名和主机名结合定义。如果不指定主机名,则使用默认的主机名%(授予用户访问权限而不管主机名)
IDENTIFIED BY 指定的口令(密码)为纯文本,保存到user表之前对其进行加密。
重命名用户名:
RENAME USER ben TO benb;
17.2.4 删除用户账号
使用DROP USER语句:
DROP USER benb;
17.2.5 设置访问权限
在创建用户后,必须接着分配访问权限。新创建的用户账号没用访问权限,只能登录而已,所以看不到数据,也不能操作数据库。
可使用以下语句查看用户账号的权限:
SHOW GRANTS FOR ben;
输出:
+---------------------------------+
| Grants for ben@% |
+---------------------------------+
| GRANT USAGE ON *.* TO 'ben'@'%' |
+---------------------------------+
1 row in set (0.04 sec)
解释:显示用户ben有一个权限USAGE ON .。USAGE表示根本没有权限(这MySQL设置的,不直观),所以此结果就表示在任意数据库和任意表上对任何东西没有权限。
可使用GRANT语句设置权限,但必须给出以下信息:
- 要授予的权限;
- 被授予访问权限的数据库或表;
- 用户名。
比如:
GRANT SELECT ON crashcourse.* TO ben;
解释:授予用户在crashcourse.*(crashcourse数据库所有表,不管数据库存不存在)上使用SELECT。即,用户ben对crashcourse数据库所有表具有只读访问权限。
来查看:
# 查看ben的权限
SHOW GRANTS FOR ben;
# 输出:
+-------------------------------------------------+
| Grants for ben@% |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO 'ben'@'%' |
| GRANT SELECT ON `crashcourse`.* TO 'ben'@'%' |
+-------------------------------------------------+
3 rows in set (0.04 sec)
撤销权限使用REVOKE语句:
REVOKE SELECT ON crashcourse.* FROM ben;
注意:被撤销的访问权限必须存在,否则出错。
GRANT和REVOKE可在几个层次上控制访问权限:
- 整个服务器,使用GRANT ALL和REVOKE ALL;
- 整个数据库,使用ON database.*;
- 特定的表,使用ON database.table;
- 特定的列;
- 特定的存储过程。
参考官网:MySQL
权限 | 说明 |
---|---|
ALL [PRIVILEGES] | 除了GRANT OPTION外的所有权限 |
ALTER | 使用ALTER TABLE |
ALTER ROUTINE | 使用ALTER PROCEDURE和DROP PROCEDURE |
CREATE | 使用CREATE TABLE |
CREATE ROUTINE | 使用CREATE PROCEDURE |
CREATE TABLESPACE | 使用CREATE TABLESPACE |
CREATE TEMPORARY TABLES | 使用CREATE TEMPORARY TABLE |
CREATE USER | 使用GREATE USER、DROP USER、RENAME USER和REVOKE ALL PRIVILEGES |
CREATE VIEW | 使用CREATE VIEW |
DELETE | 使用DELETE |
DROP | 使用DROP TABLE |
EVENT | 允许使用为事件计划程序创建、更改、删除或显示事件的语句。 |
EXECUTE | 使用CALL和存储过程 |
FILE | 使用SELECT INTO OUTFILE和LOAD DATA INFILE |
GRANT OPTION | 使用GRANT和REVOKE |
INDEX | 使用CREATE INDEX和DROP INDEX |
INSERT | 使用INSERT |
LOCK TABLES | 使用LOCK TABLES |
PROCESS | 使用SHOW FULL PROCESSLIST(查看进程权限) |
PROXY | 允许一个用户模拟或成为另一个用户 |
REFERENCES | 创建外键约束需要父表的REFERENCES权限 |
RELOAD | 使用FLUSH |
REPLICATION CLIENT | 服务器位置的访问 |
REPLICATION SLAVE | 由复制从属使用 |
SELECT | 使用SELECT |
SHOW DATABASES | 使用SHOW DATABASES |
SHOW VIEW | 使用SHOW VIEW |
SHUTDOWN | 使用mysqladmin shutdown(用来关闭MySQL) |
SUPER | 使用CHANGE MASTER、KILL、LOGS、PURGE、MASTER和SET GLOBAL。还允许mysqladmin调试登录 |
TRIGGER | 使用 |
UPDATE | 使用UPDATE |
USAGE | 无访问权限 |
可通过列出各权限并用逗号分隔,将多条GRANT语句串在一起,如下:
GRANT SELECT, INSERT ON crashcourse.* TO ben;
在使用GRANT和REVOKE时,用户账号必须存在,但对所涉及的对象没有这个要求。这允许管理员在创建数据库和表之前设计和实现安全措施。这样的副作用就是:当某个数据库或表被删除时,相关的访问权限还在。而且如果将来重新创建该数据库或表,这些权限仍然起作用。
17.2.6 更改口令
使用SET PASSWORD语句,新口令必须如下加密:
SET PASSWORD FOR ben = PASSWORD('n3w');
新口令必须传递到PAWWRORD()函数进行加密。
还可以对当前登录用户的口令更改,即不指定用户名:
SET PASSWORD = PASSWORD('n3w');
17.3 数据库维护
17.3.1 备份数据
MySQL数据必须经常备份。由于MySQL数据库是基于磁盘的文件,普通的备份系统和例程就能备份MySQL的数据。但是由于这些文件总是处于打开和使用状态,普通的文件副本备份不一定总是有效。下面提出解决:
- 使用命令行实用程序mysqldump转存所有数据库内容到某个外部文件。在进行常规备份前这个实用程序应该正常允许,以便能够整个地备份转存文件。
- 可用,命令行实用程序mysqlhotcopy从一个数据库复制所有数据(并非所有数据库引擎都支持这个实用程序)
- 可用使用MySQL的BACKUP TABLE或SELECT INTO OUTFILE转存所有数据到某个外部文件。这两条语句都接受将要创建的系统文件名,此系统文件必须不存在,否则会出错。数据可用RESTORE TABLE来复原。
为保证所有数据被写道磁盘(包括索引数据),可能需要在进行备份前使用FLUSH TABLES语句,即刷新未写数据。
17.3.2 进行数据库维护
下面说一些该知道的语句:
- ANALYZE TABLE:用来检查表键是否正确:
ANALYZE TABLE orders;
输出:
+-----------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-----------+---------+----------+----------+
| tt.orders | analyze | status | OK |
+-----------+---------+----------+----------+
1 row in set (0.08 sec)
- CHECK TABLE用来针对许多问题对表进行检查。在MyISAM表上还对索引进行检索(5.0以后也应该对InnoDB的索引一样检索)。CHECK TABLE支持一系列的用于MyISAM表的方式:CHANGED检查自最后一次检查以来改动过的表;EXTENDED执行最彻底的检查,FAST只检查未正常关闭的表;MEDIUM检查所有被删除的链接并进行键检验;QUICK只进行快速扫描。
CHECK TABLE orders, orderitems;
输出:
+---------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------+-------+----------+----------+
| tt.orders | check | status | OK |
| tt.orderitems | check | status | OK |
+---------------+-------+----------+----------+
2 rows in set (0.08 sec)
其他使用方式:
CHECK TABLE orders,orderitems QUICK;
- 如果MyISAM表访问产生不正确和不一致的结果,可能需要用REPAIR TABLE来修复相应的表。这条语句不应该经常使用,如果需要经常使用,那么可能会有更大的问题要解决。
- 如果从一个表中删除大量数据,应该使用OPTIMIZE TABLE来回收所用的空间,从而优化表的性能。
17.3.3 其他指令
- --helo:显示帮助,一个选择列表;
- --safe-mode:装载减去某些最佳配置的服务器;
- --verbose:显示全文本消息
- --version:显示版本信息
17.3.4 查看日志文件
- 错误日志:它包含启动和关闭问题以及任意关键错误的细节。此日志名通常为host
name.err,位于data目录中。此日志名可用:--log-error 命令行选项更改。 - 查询日志:它记录所有的MySQL活动,在诊断问题时非常有用。此日志文件可能会很快地变得很大,因此不应该长期使用它。此日志名通常为hostname.log,位于data目录中。此名字可用--log 命令行选项更改。
- 二进制日志:它记录更新过数据(或可能更新过数据)的所有语句。此日志名通常为hostname-bin,位于data目录中。此名字可用:--log-bin 命令行选项更改。注意,这个日志文件是MySQL5中添加的,以前的MySQL版本中使用的是更新日志。
- 缓慢查询日志:此日志记录执行缓慢的任何查询。这个日志在确定数据库何处需要优化很有用。 此日志名通常为hostname-slow.log,位于data目录中。此名字可用: --log-slow-queries 命令行选项更改。
在使用日志时,可用FLUSH LOGS语句来刷新和重新开始所有的日志文件。
更多的缓慢查询日志请看这篇:MySQL慢查询日志总结