部署
docker部署
dockerhub上有很多MySQL版本,这里我们选择常用的 MySQL5.7版本
-
拉取镜像:
# docker pull mysql:5.7.38 5.7.38: Pulling from library/mysql c1ad9731b2c7: Pull complete 54f6eb0ee84d: Pull complete cffcf8691bc5: Pull complete 89a783b5ac8a: Pull complete 6a8393c7be5f: Pull complete af768d0b181e: Pull complete 810d6aaaf54a: Pull complete 81fe6daf2395: Pull complete 5ccf426818fd: Pull complete 68b838b06054: Pull complete 1b606c4f93df: Pull complete Digest: sha256:7e99b2b8d5bca914ef31059858210f57b009c40375d647f0d4d65ecd01d6b1d5 Status: Downloaded newer image for mysql:5.7.38 docker.io/library/mysql:5.7.38
-
查看docker镜像:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7.38 2a0961b7de03 2 weeks ago 462MB
-
创建容器内在本地的映射文件夹:
mkdir -p /home/mysql/data /home/mysql/logs /home/mysql/conf
-
初始化MySQL的配置文件
touch /home/mysql/conf/my.cnf
-
创建docker容器并启动,将数据,日志,配置文件映射到本机
docker run -p 3306:3306 --name mysql -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/logs:/var/log/mysql -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7.38
-
或者我们可以使用docker-compose.yml启动
version: '3' services: db: image: 'docker.io/mysql:5.7.38' #使用的镜像 restart: always command: --lower_case_table_names=1 #区分大小写 container_name: mysql #容器名 volumes: - ./data:/var/lib/mysql #挂载目录,持久化存储 ports: - '3306:3306' environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: "123456" #设置root用户的密码
-
查看容器是否启动
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d1f3a7431f0 mysql:5.7.38 "docker-entrypoint.s…" 16 seconds ago Up 15 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
-
查看本地文件夹内容:
其中,data文件夹已经有内容了
# ls /home/mysql/ conf data logs [root@localhost ~]# ls /home/mysql/conf/ [root@localhost ~]# ls /home/mysql/data/ auto.cnf client-cert.pem ibdata1 ibtmp1 private_key.pem server-key.pem ca-key.pem client-key.pem ib_logfile0 mysql public_key.pem sys ca.pem ib_buffer_pool ib_logfile1 performance_schema server-cert.pem [root@localhost ~]# ls /home/mysql/logs
常用命令
-
进入MySQL命令行界面
docker exec -it mysql /bin/bash mysql -uroot -p123456
-
查看当前使用引擎
# 查看当前引擎 show engines; # 查看默认引擎 show variables like '%storage_engine%'; # 查看字符集 show variables like '%character%'; # 查看字符集 show variables like 'collation%'; # 查看MySQL所支持的字符集 show charset; #显示当前使用或者指定的database中的每个表的信息。信息包括表类型和表的最新更新时间。 show table status; # 查看表的字符集 show table status from 库名 like 表名; # 查看数据库 show databases; #显示系统中正在运行的所有进程,也就是当前正在执行的查询。 show processlist; #显示表中列信息 show columns from table_name from database_name; show columns from database_name.table_name; #显示一个用户的权限,显示结果类似于grant 命令 show grants for user_name@localhost; #显示表中索引信息 show index from table_name; #显示一些系统特定资源的信息,例如,正在运行的线程数量 show status; #显示系统变量的名称和值 show variables; #显示服务器所支持的不同权限 show privileges;
-
登录
mysql -u userName -p databaseName -h172.1.0.8
-
dump数据
#dump数据 docker exec -it mysql mysqldump -uroot -p123456 inm_user > ./inm_user.sql docker exec -i mysql permission < ./permission.sql #拷贝数据 docker cp permission.sql mysql:/home #进入mysql命令行 docker exec -it mysql mysql -uroot -p123456 #创建数据库 create database permission default character set utf8mb4 collate; #选择数据库 use permission; #导入dump的数据库文件数据 source /home/permission.sql;
sql语句
插入数据
INSERT INTO test VALUES (1,'b4','c4') ON DUPLICATE KEY UPDATE b=VALUES(b),c=VALUES(c);
更新数据
UPDATE table_1
INNER JOIN table_2 on table_1.`name` = table_2.user_name
SET table_1.user_id = table_2.user_id
WHERE table_1.created_at>table_2.created_at;
UPDATE table_1 SET table_1.user_id = table_2.user_id WHERE table_1.created_at>table_2.created_at;
删除数据
delete from table_1 where id = 1;
清空表格
-- 关闭外键检查,防止出现Cannot truncate a table referenced in a foreign key constraint...类似的报错
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;
TRUNCATE table2;
SET FOREIGN_KEY_CHECKS = 1;
查询数据
select * from table_1;
修改表结构
使用after或者first字段决定字段的位置
增加字段
ALTER TABLE `server` ADD COLUMN ip INT(8) NOT NULL DEFAULT 0 COMMENT '服务器IP'AFTER `note`;
删除表字段
ALTER TABLE netline_wave DROP COLUMN `alert_time`;
修改字段类型
ALTER TABLE netline_wave MODIFY `title` VARCHAR(128);
删除索索引
索引
索引原理
-
Mysql索引概念: 说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这本书1000页,有500也是目录,它当然效率低,目录是要占纸张的,而索引是要占磁盘空间的。
-
Mysql索引主要有两种结构:B+树和hash.
-
hash:hsah索引在mysql比较少用,他以把数据的索引以hash形式组织起来,因此当查找某一条记录的时候,速度非常快.当时因为是hash结构,每个键只对应一个值,而且是散列的方式分布.所以他并不支持范围查找和排序等功能.
-
B+树:b+tree是mysql使用最频繁的一个索引数据结构,数据结构以平衡树的形式来组织,因为是树型结构,所以更适合用来处理排序,范围查找等功能.相对hash索引,B+树在查找单条记录的速度虽然比不上hash索引,但是因为更适合排序等操作,所以他更受用户的欢迎.毕竟不可能只对数据库进行单条记录的操作.
-
索引相关sql
查询索引
show index from t_test
创建索引
-
主键索引
ALTER TABLE `table_name` ADD PRIMARY KEY (`column`)
-
普通索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column`)
-
唯一索引
ALTER TABLE `table_name` ADD UNIQUE (`column`)
-
组合/多列/联合索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
-
联合唯一索引
alter table t_aa add unique index(aa,bb); //或者 CREATE UNIQUE INDEX idx_aa_bb on t_aa(aa,bb);
如果创建这个索引的时候,表中有历史数据存在重复记录,则可以执行以下语句:
alter ignore table t_aa add unique index(aa,bb);
或者执行类似以下sql:
DELETE t1 FROM newip_addr_ping t1 INNER JOIN newip_addr_ping t2 WHERE t1.id < t2.id AND t1.ip_address = t2.ip_address AND t1.creator_time = t2.creator_time;
-
全文索引
ALTER TABLE `table_name` ADD FULLTEXT ( `column` )
还有一种情况就是,我们需要为以前的表 创建这个索引,有可能以前的数据中存在重复的记录 那怎么办呢?
alter ignore table t_aa add unique index(aa,bb);
它会删除重复的记录(会保留一条),然后建立唯一索引,高效而且人性化。
删除索引
-
删除
DROP INDEX server_id_time ON netline_wave;
索引优化
存储过程和事件
mysql存储过程
-
创建存储过程
DELIMITER $$ CREATE PROCEDURE `deleteNetprobeTables`() begin declare i int; set i=1; while i<=2 do set @tb = CONCAT('TRUNCATE TABLE netprobe',i); PREPARE create_stmt FROM @tb; EXECUTE create_stmt; set i=i+1; end while; end $$; DELIMITER ;
-
调用存储过程
call deleteNetprobeTables();
-
查看存储过程
show procedure status;
-
删除存储过程
drop PROCEDURE deleteNetprobeTables;
-
复杂存储过程示例
CREATE PROCEDURE proc_Add_Date_Partition_For_Table(IN BeginDate DATETIME, IN EndDate DATETIME, IN DBName VARCHAR(20),IN TableName VARCHAR(50)) BEGIN DECLARE PartitionName varchar(50); DECLARE PartitionColumn varchar(50); DECLARE PartitionValue Datetime; if EndDate is not null then select PARTITION_NAME ,REPLACE(PARTITION_EXPRESSION,'`','') as PARTITION_COLUMN, str_to_date(SUBSTR(PARTITION_DESCRIPTION FROM 2 FOR 10),'%Y-%m-%d') as PARTITION_VALUE into PartitionName,PartitionColumn,PartitionValue from INFORMATION_SCHEMA.PARTITIONS where TABLE_SCHEMA=DBName and table_name=TableName order by PARTITION_ORDINAL_POSITION desc limit 1; IF PartitionValue IS NOT NULL THEN SET BeginDate = PartitionValue; END IF; WHILE BeginDate <= EndDate DO set @SqlStr=concat('alter table ',DBName,'.',TableName, ' add partition(partition p_', DATE_FORMAT(BeginDate,'%Y%m%d'),' values less than('',DATE_FORMAT(DATE_ADD(BeginDate,INTERVAL 1 day),'%Y-%m-%d'),''));'); PREPARE STMT FROM @SqlStr; EXECUTE STMT; SET BeginDate = DATE_ADD(BeginDate,INTERVAL 1 day); END WHILE; end if; END;
mysql事件
-
打开事件开关
SHOW VARIABLES LIKE 'event_scheduler'; SET GLOBAL event_scheduler = 1;
-
创建事件
事件定时类型可以有多种选择,如每季度、每月、每天、定时启动、延时启动、从某个时间点开始定时启动等
CREATE EVENT delete_table_schedule ON SCHEDULE AT '2021-09-01 00:00:00' + INTERVAL 22 DAY do call deleteNetprobeTables(); CREATE EVENT delete_table_schedule ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY do call deleteNetprobeTables();
-
查看事件
SHOW events;
-
删除事件
DROP EVENT delete_table_schedule;
-
查看当前时间
SELECT CURRENT_TIMESTAMP
函数
常用函数
-
随机生成IP
SELECT CONCAT( TRUNCATE (RAND() * 255 + 1, 0), '.', TRUNCATE (RAND() * 255 + 1, 0), '.', TRUNCATE (RAND() * 255 + 1, 0), '.', TRUNCATE (RAND() * 255 + 1, 0) )
-
随机生成mac
SELECT CONCAT_WS( ':', substring(MD5(RAND()),1,2), substring(MD5(RAND()),1,2), substring(MD5(RAND()),1,2), substring(MD5(RAND()),1,2), substring(MD5(RAND()),1,2), substring(MD5(RAND()),1,2) );
-
随机生成两位数
SELECT TRUNCATE ((RAND() * 90 + 10), 0)
-
随机两位字符
SELECT LEFT (uuid(), 2);
自定义函数
日期函数
日期类型的 default 设置
类型 | 字节 | 格式 | 用途 | 是否支持设置系统默认值 |
---|---|---|---|---|
date | 3 | YYYY-MM-DD | 日期值 | 不支持 |
time | 3 | HH:MM:SS | 时间值或持续时间 | 不支持 |
year | 1 | YYYY | 年份 | 不支持 |
datetime | 8 | YYYY-MM-DD HH:MM:SS | 日期和时间混合值 | 不支持 |
timestamp | 4 | YYYYMMDD HHMMSS | 混合日期和时间,可作时间戳 | 支持 |
关于 default 设置,通常情况下会使用当前时间作为默认值。
Example:
ts_time timestamp NOT NULL DEFAULT NOW();
或者
ts_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP();
根据上表可知,除了 timestamp 类型支持系统默认值设置,其他类型都不支持。
如果建表语句中有:
ts_time1 time NOT NULL DEFAULT NOW();
ts_time3 year NOT NULL DEFAULT NOW();
ts_time2 date NOT NULL DEFAULT CURRENT_TIMESTAMP();
ts_time2 datetime NOT NULL DEFAULT CURRENT_TIMESTAMP();
都会报错。所以想要设置某个日期列的默认值为当前时间,只能使用 timestamp 类型,并设置 DEFAULT NOW() 或 DEFAULT CURRENT_TIMESTAMP() 作为默认值。
常见的日期函数
函数 | 描述 |
---|---|
NOW() | 返回当前的日期和时间 |
CURDATE() | 返回当前的日期 |
CURTIME() | 返回当前的时间 |
DATE() | 提取日期或日期/时间表达式的日期部分 |
EXTRACT() | 返回日期/时间按的单独部分 |
DATE_ADD() | 给日期添加指定的时间间隔 |
DATE_SUB() | 从日期减去指定的时间间隔 |
DATEDIFF() | 返回两个日期之间的天数 |
DATE_FORMAT() | 用不同的格式显示日期/时间 |
CURRENT_TIME() | 同CURTIME() |
CURRENT_DATE | 同CURDATE() |
CURRENT_TIMESTAMP | 返回当前的时间和NOW()相同 |
where 和 having区别
1、having用于groyup by之后。 2、where是用于表中筛选查询,having用于在where和group 结果中查询。 3、havin可以使用聚合函数,而where 不能。 4、having执行顺序位于where之后。
查询案例记录
- 查询重复记录,去重,并选择最新数据
SELECT `cmd` FROM cmd_info ci WHERE EXISTS
(SELECT 1 FROM cmd_info WHERE cmd=ci.cmd AND id < ci.id) ORDER BY id desc LIMIT 50
涉及到知识点:exists/not exists select 1
-
原理
以exist为例:先执行外层,再把外层的数据传到内层的sql,如果满足内层的sql条件,则外层保留数据
Not exists相反
select 1表示满足条件,其实除了1,其他字符也可以代替,select * select 2、3、4都是一样
-
使用UNION连接两个查询结果,查询条数需要一致
常见问题
- 升级问题
8.0升级8.0.30后报错:
This redo log was created with MySQL 8.0.27, and it appears logically non empty
删除ib_logfile0 ib_logfile1两个文件即可,删除前备份文件
- 无法登录问题:
先把mysql配置为免密登录,然后进入mysql执行
USE mysql;
ALTER USER 'root'@'%' IDENTIFIED BY 'dev57vwnAjPK&UNE' PASSWORD EXPIRE NEVER;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'dev57vwnAjPK&UNE';
flush privileges;
- 执行数据插入的问题:
### Cause: java.sql.SQLSyntaxErrorException: INSERT command denied to user 'root'@'106.120.101.58' for table 'sys_job_log'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: INSERT command denied to user 'root'@'106.120.101.58' for table 'sys_job_log'
原因:没有插入权限
解决方案:修改root权限,如下图所示 执行:
SELECT * FROM mysql.user;
FLUSH PRIVILEGES;
将对应的权限修改为Y即可:
参考链接
Dbeaver 链接异常问题
DBeaver连接mysql时Public Key Retrieval is not allowed错误解决附图片
问题 Public Key Retrieval is not allowed
解决 在新建连接的时候,驱动属性里设置 allowPublicKeyRetrieval 的值为 true。