工作中MySQL数据库涉及5.6.*/5.7.*/8.0.*版本,本文就日常使用罗列笔记(基于Linux系统、MySQL8)。
1. MySQL服务启动与关闭
MySQL启动脚本和支持的服务器选项组如下:
- mysqld,也称为MySQL Server,是在MySQL安装中完成大部分工作的主程序,MySQL服务器管理包含数据库和表的MySQL数据目录的访问,数据目录也是其他信息(例如日志文件和状态文件)的默认位置;MySQL服务器启动时,它将监听来自客户端程序的网络连接,管理它们对数据库的访问。
MySQL Server包含一组系统变量,这些变量会影响其运行,可以在服务器启动时设置系统变量,并且可以在运行时更改许多系统变量以实现动态服务器重新配置,具体参数参考如下命令:
[root@chengyu ~]# mysqld --verbose --help
有关MySQL Server命令选项,系统变量和状态变量的完整说明参详:https://dev.mysql.com/doc/refman/8.0/en/mysqld-server.html
- Unix环境下启动 mysqld服务器推荐使用 mysqld_safe, 因为它具备一些安全功能,例如将重启服务器发生的错误信息以及运行时的信息记录到错误日志中;mysqld_safe的许多参数与mysqld的相同,mysqld_safe参数如下:
例如(其中–defaults-file是指定配置文件,&表示后台启动):
[root@chengyu ~]# /usr/local/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --port=3307 &
MySQL读取配置文件的优先级:/etc/my.cnf → basedir/my.cnf→ datadir/my.cnf → --defaults-extra-file →
- Unix和类似Unix的系统上的MySQL发行版包括一个名为mysql.server的脚本,该脚本使用mysqld_safe启动MySQL服务器,它可以在使用System V样式运行目录来启动和停止系统服务的系统(例如Linux和Solaris)上使用;mysql.server是MySQL源代码树中使用的脚本名称,安装的名称可能不同(例如,mysqld或 mysql),一般在MySQL安装目录下的support-files中,可以将mysql.server脚本复制到/etc/init.d下并设置为可执行自启动,mysql.server参数可以添加至my.cnf中,如下:
示例:
[mysqld]
basedir =/usr/local/mysql8
datadir =/home/mysql8/data
port = 3307
pid-file = /usr/local/mysql8/mysqld.pid
socket = /usr/local/mysql8/mysql.sock
[mysql.server]
basedir=/usr/local/mysql8
datadir =/home/mysql8/data
pid-file = /usr/local/mysql8/mysqld.pid
service-startup-timeout = 900
systemd提供自动的MySQL服务器启动和关闭,它还使用systemctl命令启用手动服务器管理 ,例如:
systemctl {start|stop|restart|status} mysqld
或者,使用与System V系统兼容的service命令(具有相反的参数):
service mysqld {start|stop|restart|status}
2. MySQL数据库与用户创建
2.1 MySQL对象命名要求
MySQL中的某些对象,包括数据库,表,索引,列,别名,视图,存储过程,分区,表空间,资源组和其他对象名,称为标识符。
- 每种标识符的最大长度:
- 限定符:用以明确解释数据库对象。
注意:默认情况下,表别名在Unix上区分大小写,但在Windows或macOS上不区分大小写,分区,子分区,列,索引,存储的例程,事件和资源组名称在任何平台上都不区分大小写,列别名也不区分大小写;但是,日志文件组的名称区分大小写,这与标准SQL不同,所以为实现最大的可移植性和易用性,命名最好采用一致的约定,例如始终使用小写名称创建和引用数据库和表。
对于MySQL的关键字和保留字,加引号用作标识符,例外:限定名称中句点后的单词必须是标识符,因此即使保留该单词也无需加引号,不过最好避开使用关键字保留字。
- 未加引号的标识符中允许的字符:[0-9,az,AZ $ _],标识符可以以数字开头,但除非加引号,否则不能仅由数字组成,数据库,表和列的名称不能以空格字符结尾。
2.2 创建数据库
MySQL 8.0不支持通过在 数据目录下手动创建目录(例如,使用mkdir)来创建数据库目录 。
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_option] ...
create_option: {
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
| [DEFAULT] ENCRYPTION [=] {'Y' | 'N'}
}
# ENCRYPTION选项在MySQL 8.0.16中引入,定义了默认的数据库加密,该默认加密由数据库中创建的表继承。允许的值为'Y'(启用加密)和 'N'(禁用加密)。
示例:
mysql> CREATE DATABASE IF NOT EXISTS dbcy DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.13 sec)
2.3 创建用户
- 帐户首次创建时没有权限,默认角色为NONE。要分配特权或角色,请使用以下GRANT语句;
- 帐户名的主机名部分(如果省略)默认为’%’;
- 对于每个帐户,CREATE USER 在mysql.user系统表中创建一个新行。
语法如下:
CREATE USER [IF NOT EXISTS]
user [auth_option] [, user [auth_option]] ...
DEFAULT ROLE role [, role ] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
[COMMENT 'comment_string' | ATTRIBUTE 'json_object']
示例1:创建一个使用默认身份验证插件和给定密码的帐户。将密码标记为过期,以便用户在与服务器的第一次连接时必须选择一个新密码:
mysql> CREATE USER 'cy'@'localhost' IDENTIFIED BY '123456' PASSWORD EXPIRE;
示例2:创建一个使用caching_sha2_password身份验证插件和给定密码的帐户,要求每180天选择一个新密码,并启用登录失败跟踪,以使三个连续的错误密码会导致两天的临时帐户锁定:
mysql> CREATE USER 'cy'@'localhost' IDENTIFIED WITH caching_sha2_password BY '123456'
PASSWORD EXPIRE INTERVAL 180 DAY
FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 2;
示例3:创建多个帐户,并指定一些每个帐户属性和一些全局属性:必须使用有效的X.509证书进行连接、每小时最多允许60个查询、密码更改不能重复使用五个最新密码中的任何一个、该帐户最初是被锁定的,因此实际上是一个占位符,只有在管理员将其解锁后才能使用。
mysql> CREATE USER 'cy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'cy123456', 'nn'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'nn123456'
REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60
PASSWORD HISTORY 5
ACCOUNT LOCK;
从MySQL 8.0.21开始,可以选择创建具有用户注释或用户属性的用户:
mysql> CREATE USER 'cy'@'localhost' COMMENT 'Some information about cy';
mysql> CREATE USER 'cy'@'localhost' ATTRIBUTE '{"name": "ChengYu", "city": "DongGuan", "phone": "123-456-7890"}';
2.4 创建表
语法如下:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
(create_definition,...)
[table_options]
[partition_options]
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options]
[partition_options]
[IGNORE | REPLACE]
[AS] query_expression
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
{ LIKE old_tbl_name | (LIKE old_tbl_name) }
示例1创建普通表:
mysql> CREATE TABLE `tb_wx_user` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`cellPhone` varchar(20) DEFAULT NULL COMMENT '手机号',
`nickname` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '昵称',
`sex` int(1) DEFAULT '0' COMMENT '性别(1.男,2.女,0.未知)',
`addr` varchar(100) DEFAULT NULL COMMENT '城市',
`createDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`userid`),
UNIQUE KEY `uq_cellPhone` (`cellPhone`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表'
示例2创建分区表:
# hash分区
mysql> CREATE TABLE tb_hash (col1 INT, col2 CHAR(5))
PARTITION BY HASH(col1);
# key分区
mysql> CREATE TABLE tb_key (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY KEY(col3)
PARTITIONS 4;
# range分区
mysql> CREATE TABLE tb_range (
year_col INT,
some_data INT
)
PARTITION BY RANGE (year_col) (
PARTITION p3 VALUES LESS THAN (2002),
PARTITION p4 VALUES LESS THAN (2006),
PARTITION p5 VALUES LESS THAN MAXVALUE
);
# list分区
mysql> CREATE TABLE client_firms (
id INT,
name VARCHAR(35)
)
PARTITION BY LIST (id) (
PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
);
2.5 创建函数
语法如下:
delimiter常应用在存储过程、函数中定义结束符,默认情况下,delimiter 为“;” ,而存储过程中每个SQL语句的结尾都有个 “;”,如果每逢 “;” 就向 MySQL 提交的话会出问题,于是更改 MySQL 的delimiter。
mysql> CREATE
[DEFINER = user]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
示例,通过笔记编号tid获取笔记内容详情logmark:
DROP FUNCTION IF EXISTS get_cylog;
CREATE FUNCTION get_cylog(cid INT) RETURNS VARCHAR(200)
BEGIN
DECLARE cylog_detail VARCHAR(200);
SELECT logmark FROM tb_cylog WHERE tid=cid INTO cylog_detail;
RETURN cylog_detail;
END
# 使用这个函数
mysql> select get_cylog(1)\G
*************************** 1. row ***************************
get_cylog(1): 过去与未来有别,原因先于结果。先有伤口,后有疼痛,而非反之。杯子碎成千片,而这些碎片不会重新组成杯子。我们无法改变过去,我们会有遗憾、懊悔、回忆。而未来是不确定、欲望、担忧、开放的空间,也许是命运。我们可以向未来而活,塑造它,因为它还不存在。一切都还有可能……时间不是一条双向的线,而是有着不同两端的箭头。
1 row in set (0.00 sec)
# 查看函数状态
mysql> show function status like 'get_cylog'\G
*************************** 1. row ***************************
Db: dbcy
Name: get_cylog
Type: FUNCTION
Definer: cy@192.183.3.147
Modified: 2020-06-15 09:40:42
Created: 2020-06-15 09:40:42
Security_type: DEFINER
Comment:
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
# 也可以查看函数创建语句
mysql> show create function get_cylog;
*************************** 1. row ***************************
Function: get_cylog
sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
Create Function: CREATE DEFINER=`cy`@`192.183.3.147` FUNCTION `get_cylog`(cid INT) RETURNS varchar(200) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
BEGIN
DECLARE cylog_detail VARCHAR(200);
SELECT logmark FROM tb_cylog WHERE tid=cid INTO cylog_detail;
RETURN cylog_detail;
END
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
# 删除函数
mysql> drop function get_cylog;
2.6 创建事件
语法如下:
CREATE
[DEFINER = user]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'string']
DO event_body;
示例,定期更新tb_cylog的days字段:
mysql> delimiter //
mysql> CREATE DEFINER = `cy`@`192.183.147` EVENT `e_cylog_up`
-> ON SCHEDULE EVERY 1 DAY STARTS '2020-02-08 00:00:00' ON COMPLETION PRESERVE ENABLE DO
-> UPDATE tb_cylog SET days = days + 1;//
Query OK, 0 rows affected, 1 warning (0.09 sec)
mysql> delimiter ;
# 查看event是否开启
mysql> SHOW VARIABLES LIKE '%event_sche%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | ON |
+-----------------+-------+
1 row in set (0.01 sec)
# 将事件计划开启
mysql> SET GLOBAL event_scheduler = 1;
# 将事件计划关闭
mysql> SET GLOBAL event_scheduler = 0;
# 关闭事件任务
mysql> ALTER EVENT e_cylog_up ON COMPLETION PRESERVE DISABLE;
# 开启事件任务
mysql> ALTER EVENT e_cylog_up ON COMPLETION PRESERVE ENABLE;
# 查看事件任务
mysql> SHOW EVENTS;
# 删除事件
mysql> drop event e_cylog_up;
2.7 创建视图
相关语法如下:
# 创建视图
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
# 修改视图
ALTER
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
# 删除视图
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
# 查看视图创建语句
SHOW CREATE VIEW view_name;
# 查看视图状态
SHOW TABLE STATUS LIKE 'view_name':
示例:
mysql> CREATE VIEW v_cylog AS SELECT tname,logmark FROM tb_cylog where tname='ChengYu';
Query OK, 0 rows affected (0.11 sec)
mysql> select * from v_cylog\G
*************************** 1. row ***************************
tname: ChengYu
logmark: 过去与未来有别。原因先于结果。先有伤口,后有疼痛,而非反之。杯子碎成千片,而这些碎片不会重新组成杯子。我们无法改变过去,我们会有遗憾、懊悔、回忆。而未来是不确定、欲望、担忧、开放的空间,也许是命运。我们可以向未来而活,塑造它,因为它还不存在。一切都还有可能……时间不是一条双向的线,而是有着不同两端的箭头
*************************** 2. row ***************************
tname: ChengYu
logmark: 时间的缺失并不意味着一切都停滞不变。它只能说明,让世界感到疲倦的不间断的事件并不是按时间顺序排列的,无法被一个巨大的钟表测量.
2 rows in set (0.00 sec)
2.8 创建索引
语法如下:
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
[index_type]
ON tbl_name (key_part,...)
[index_option]
[algorithm_option | lock_option] ...
示例:
mysql> CREATE UNIQUE INDEX ind_tid ON tb_cylog(tid);
mysql> CREATE FULLTEXT INDEX ind_logmark ON tb_cylog((logmark));
mysql> CREATE INDEX ind_log ON tb_cylog((tid, tname));
2.9 创建触发器
语法如下:
CREATE
[DEFINER = user]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
[trigger_order]
trigger_body
示例,当tb_cylog有insert操作时更新tb_notice表:
mysql> DELIMITER //
mysql> CREATE TRIGGER tri_cylog_insert
-> AFTER INSERT
-> ON tb_cylog FOR EACH ROW
-> BEGIN
-> insert into tb_notice(contents,createtime) values('成屿更新啦',NOW());
-> END//
Query OK, 0 rows affected (0.10 sec)
mysql> DELIMITER ;
# 测试
mysql> insert into tb_cylog values(3,'ChengYu','生有时,死有时;哀恸有时,跳舞有时;杀戮有时,医治有时;摧毁有时,建造有时.', now(),5300);
Query OK, 1 row affected (0.06 sec)
mysql> select * from tb_notice\G
*************************** 1. row ***************************
nid: 1
contents: 成屿更新啦
createtime: 2020-06-15 15:20:16
1 row in set (0.00 sec)
2.10 创建存储过程
语法如下:
CREATE
[DEFINER = user]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
示例,通过笔记编号tid获取笔记内容详情logmark:
mysql> delimiter //
mysql> CREATE PROCEDURE pro_cylog (IN cid INT, OUT cylog_detail VARCHAR(200))
-> BEGIN
-> SELECT logmark into cylog_detail FROM tb_cylog WHERE tid=cid;
-> END
-> //
Query OK, 0 rows affected (0.08 sec)
mysql> delimiter ;
# 调用存储过程
mysql> call pro_cylog(2,@cylog_detail)\G
Query OK, 1 row affected (0.00 sec)
mysql> select @cylog_detail\G
*************************** 1. row ***************************
@cylog_detail: 时间的缺失并不意味着一切都停滞不变。它只能说明,让世界感到疲倦的不间断的事件并不是按时间顺序排列的,无法被一个巨大的钟表测量.
1 row in set (0.00 sec)
# 查询存储过程
mysql> show create procedure pro_cylog\G
*************************** 1. row ***************************
Procedure: pro_cylog
sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_cylog`(IN cid INT, OUT cylog_detail VARCHAR(200))
BEGIN
SELECT logmark into cylog_detail FROM tb_cylog WHERE tid=cid;
END
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
# 查看存储过程状态
mysql> show procedure status like '%cylog%'\G
*************************** 1. row ***************************
Db: dbcy
Name: pro_cylog
Type: PROCEDURE
Definer: cy@192.183.3.147
Modified: 2020-06-15 10:24:44
Created: 2020-06-15 10:24:44
Security_type: DEFINER
Comment:
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
#删除存储过程
mysql> drop procedure pro_cylog;
Query OK, 0 rows affected (0.13 sec)