这里记录的是这两年学习工做过程当中遇到的经常使用的 MySQL 语句和命令,部分是网上收集来的,出处已经不记得了,这里先谢过这些大佬。本文包括常见 SQL 语句,还有部分运维语句和命令,没有作详细的说明,更可能是给出一个例子。就这点语句固然还不能说是全,可是后续也会陆续增长完善。记录得有些乱,有须要的能够酌情提取。mysql
mysql -h 主机地址 -u 用户名 -P端口号 -p
c++
使用 SSL 链接sql
mysql --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem -h主机地址 -u用户名 -p
shell
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
数据库
host
指定该用户在哪一个主机上能够登录,若是是本地用户可用localhost
, 若是想让该用户能够从任意远程主机登录,可使用通配符%
.GRANT [all privileges/某个权限] ON databasename.tablename TO 'username'@'host';
bash
若是想让该用户能够受权,用如下命令: 运维
GRANT all privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;
socket
ALTER USER 'username'@'host' ACCOUNT LOCK;
解锁ide
ALTER USER 'username'@'host' ACCOUNT UNLOCK;
常见场景:函数
1 建立读写权限的用户
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, EXECUTE, CREATE VIEW, SHOW VIEW ON databasename.tablename TO 'username'@'host';
2 建立只读权限用户
GRANT SELECT,SHOW VIEW ON databasename.tablename TO 'username'@'host';
方法一
SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');
若是是当前登录用户用
SET PASSWORD = PASSWORD("newpassword");
方法二
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
REVOKE [ALL/某个权限] ON databasename.tablename FROM 'username'@'host';
某个用户权限能够用命令SHOW GRANTS FOR 'username'@'host';
查看.
rename user 'old_name'@'host' to 'new_name'@'host';
DROP USER 'username'@'host';
# 修改已存在用户 ALTER USER 'username'@'%' REQUIRE SSL; # 建立用户 create user username_ssl@'%' identified by 'password' require ssl;
flush privileges;
-- 查看数据库 show databases; -- 建立库 create database [IF NOT EXISTS] <库名> [character set='utf8']; -- 删除库 drop database <库名>;
-- 显示数据表 use <库名>; show tables; -- 建立表: create table 表名 (字段设定列表) [engine=InnoDB] [charset=utf8mb4]; -- 查看建立表的 DDL 语句 show create table <表名>; -- 显示表结构 desc <表名>; -- 删除表 drop table [IF EXISTS] <表名>; -- 临时表 CREATE TEMPORARY TABLE <表名>(<字段定义>);
e.g.
CREATE TABLE USER ( id INT NOT NULL AUTO_INCREMENT, stu_id INT NOT NULL, name VARCHAR(30) NOT NULL, phone VARCHAR(20), address VARCHAR(30) NOT NULL, age INT NOT NULL, PRIMARY KEY (id), UNIQUE KEY `un_stu_id` (stu_id), KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
注意: 为 text 等创建索引时要指定长度 e.g. KEY
idx_text (f_text(64))
含有主键等信息的完整表结构:
CREATE table 新表名 LIKE book;
只有表结构,没有主键等信息:
create table 新表名 select * from books; 或 create table 新表名 as(select * from book); 或 create table 新表名 select * from books where1=2;
注: create table <t> select ...
会形成索引丢失
INSERT INTO <新表> SELECT * FROM <旧表>;
show create table <表名>;
truncate table <表名>;
备份单个库
shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u root -p <database_name> >database_name.sql
备份一个表
shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u root -p <database_name> <table_name> > table_name.sql
备份多个库
shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u username -p --databases <dbname1> <dbname2> > Backup.sql
备份全部库
shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -A -u root -p > back.sql
忽略某些库表
--ignore-table=performance_schema.* --ignore-table=information_schema.* --ignore-table=sys.* --ignore-table=test.*
带上压缩
shell> mysqldump -A | gzip >> backup.sql.gz
shell> mysql -u root -p -f [database_name] < backup.sql
提取某个库的全部数据
shell> sed -n '/^-- Current Database: `test_restore`/,/^-- Current Database:/p' mysql_back.sql
只提取建表语句
shell> sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `test1`/!d;q' mysql_back.sql
只提取数据
shell> grep -i 'INSERT INTO `test1`' mysql_back.sql
提取全部建库表语句
shell> grep -iv 'INSERT INTO `' mysql_back.sql
<select语句> into outfile "dest_file";
load data infile "<file_name>" into table <table_name>;
alter table <表名称> change <旧字段名称> <新字段名称>
alter table <旧表名称> rename <新表名称>
alter table <表名称> change <字段名称> <字段名称> <字段类型> [not null];
alter table <表名称> modify <字段名称> <字段类型> [not null];
alter table 表名称 add column 字段名称 字段类型;
加在某个字段后面
alter table 表名称 add column 字段名称 字段类型 after 某个字段;
加在最前
alter table 表名称 add column 字段名称 字段类型 first;
alter table <表名称> change <原字段名称> <新字段名称 字段类型>;
alter table 表名称 alter 字段名称 set default 值;
该方法不会锁表
alter table <表名称> change column <字段名称> <字段名称> <字段类型>;
alter table <表名称> drop column <列名>;
SELECT [DISTINCT] <字段名称,用逗号隔开/*> FROM <left_table> [<join_type> JOIN <right_table> ON <链接条件>] WHERE <where条件> GROUP BY <分组字段> HAVING <筛选条件> ORDER BY <排序条件> [desc/asc] LIMIT n[, m]
1 在不使用聚合函数的时候,group by 子句中必须包含全部的列,不然会报错
正确: select name,age from test group by name,age; //和 select 同样
2 在 group by 子句中不要加上聚合函数处的列名
SQL 标准
要求 having 必须引用 group 子句中的列或者用聚合函数处理过
后的列。
mysql 对这一标准进行了一些扩展,它容许 having 引
用 select 中检索的列和外部查询中的列。
having 中用到的条件要
么在 group by 中出现,要么在 select 的列中出现,要么在外查
询中出现。
from 子查询时要给数据表指定一个别名。from (select ..) [as] 别名 where...
select 语句 union [all] select 语句
union 会去重
select * from tableA A [left、right] join tableB B on A.id = B.id
select * from tableA,tableB
select * from tableA cross join tableB
逗号与 cross join
区别是逗号不能使用 on
结果会有 n * n 条记录(笛卡尔乘积)
select * from tableA A inner join tableB B on A.id = B.id
select * from tableA A inner join tableB B using(id)
using(字段)
能够合并相同字段,而且符合 A.id = B.id
内链接在没有条件时和交叉链接没有区别。
STRAIGHT_JOIN
能够手动指定驱动表
方法一
-- 普通索引 ALTER TABLE 表名称 ADD INDEX index_name (column_list) -- 惟一索引 ALTER TABLE 表名称 ADD UNIQUE (column_list) -- 主键索引 ALTER TABLE 表名称 ADD PRIMARY KEY (column_list)
方法二
CREATE INDEX index_name ON 表名称 (column_list) CREATE UNIQUE INDEX index_name ON 表名称 (column_list)
column_list 指出对哪些列进行索引,多列时各列之间用逗号分隔。
索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。
另外,ALTER TABLE容许在单个语句中更改多个表,所以能够在同时建立多个索引。
-- 删除索引 DROP INDEX index_name ON 表名称; ALTER TABLE 表名称 DROP INDEX index_name; -- 删除主键 ALTER TABLE 表名称 DROP PRIMARY KEY;
show index from 表名称; show keys from 表名称;
USE INDEX
: 向优化器提示如何选择索引IGNORE INDEX
: 忽略索引FORCE INDEX
: 强制使用索引select * from tableA USE INDEX (key1, key2) where key1=1 and key2=2
建表时
constraint 外键名 foreign key(外键字段) references 关联表名(关联字段);
修改表
alter table 表名 add constraint 外键名 foreign key(外键字段名) references 外表表名(对应的表的主键字段名);
ALTER TABLE table-name DROP FOREIGN KEY key-id;
IF(expr1,expr2,expr3)
若是 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; 不然返回值则为 expr3。
SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END as testCol
IFNULL(expr1,expr2)
假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 不然其返回值为 expr2。
查询数据库中的存储过程和函数
- 存储过程 show procedure status; select `name` from mysql.proc where db = '<dbname>' and `type` = 'PROCEDURE'; -- 函数 show function status; select `name` from mysql.proc where db = '<dbname>' and `type` = 'FUNCTION'
查看存储过程或函数的建立代码
show create procedure <proc_name>; show create function <func_name>;
create or replace view <视图名>(<列名 1>,<列名 2>...) as <select 语句>;
drop view <视图 1> [,视图 2....视图 n];
trigger_time: { BEFORE | AFTER } -- 事件以前仍是以后触发 trigger_event: { INSERT | UPDATE | DELETE } -- 三个类型 trigger_order: { FOLLOWS | PRECEDES } other_trigger_name
假设定义一个触发器,每次插入把 ctime
设为当前时间
delimiter // -- 更改结束符 create trigger <触发器名字> before insert on <表名> for each row begin set new.ctime=now(); end;// delimiter ;
假设定义一个触发器,每次更新把 mtime
设为当前时间
delimiter // -- 更改结束符 create trigger <触发器名字> before update on <表名> for each row begin set new.mtime=now(); end;// delimiter ;
# 查看状态 status; show status; # innodb 状态 show innodb status; # 查看参数 show variables like '%参数名称%'; # 查看隔离级别 select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+
select * into outfile 文件地址 [控制格式] form tableA;
导出到 csv,并压缩
shell> mysql -B -u帐号 -p -e "SELECT语句" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" | gzip > data.csv.gz
控制格式同导入文件
load data infile 文件名 [replace|ignore] into table 表名 [控制格式]
replace
和 ignore
: 表示对主键重复的数据处理方式fields terminated by '\t' enclosed by '' escaped by '\\'
e.g.
SELECT * INTO OUTFILE '/tmp/data.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM tableA;
MySQL >= 8
select (@@key_buffer_size + @@query_cache_size + @@tmp_table_size + @@innodb_buffer_pool_size + @@innodb_additional_mem_pool_size + @@innodb_log_buffer_size + @@max_connections * ( @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size+ @@join_buffer_size + @@binlog_cache_size + @@thread_stack ) )/1024/1024/1024 as max_mem_G;
MySQL < 8
select (@@key_buffer_size + @@query_cache_size + @@tmp_table_size + @@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@max_connections * ( @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size+ @@join_buffer_size + @@binlog_cache_size + @@thread_stack ) )/1024/1024/1024 as max_mem_G;
数据总大小
SELECT ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES;
某个库大小
SELECT ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES WHERE TABLE_SCHEMA='库名';
统计全部库按大小排序
SELECT TABLE_SCHEMA, ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES group by TABLE_SCHEMA order by data_size_G desc;
select SUBSTRING_INDEX(host,':',1) as ip , count(*) from information_schema.processlist group by ip;
mysql5.6
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; waiting_trx_id -- 请求的事物ID waiting_thread -- 请求的线程ID waiting_query -- 等待的SQL语句 blocking_trx_id -- 阻塞上面请求的事物的ID blocking_thread -- 阻塞的线程ID blocking_query -- 阻塞的当前的SQL,这个是没法看到的,除非SQL尚未执行完成(不必定是该事物当中的最后一条SQL语句)
mysql5.7
select * from sys.innodb_lock_waits;
SELECT table_schema, table_name FROM information_schema.TABLES WHERE table_name NOT IN ( SELECT DISTINCT TABLE_NAME FROM information_schema.COLUMNS WHERE COLUMN_KEY = 'PRI') AND table_schema NOT IN ('mysql' , 'information_schema','sys', 'performance_schema');
SELECT t.TABLE_SCHEMA,t.TABLE_NAME,INDEX_NAME, CARDINALITY, TABLE_ROWS, CARDINALITY/TABLE_ROWS AS SELECTIVITY FROM information_schema.TABLES t, ( SELECT table_schema, table_name, index_name, cardinality FROM information_schema.STATISTICS WHERE (table_schema,table_name,index_name,seq_in_index) IN ( SELECT table_schema, table_name, index_name, MAX(seq_in_index) FROM information_schema.STATISTICS GROUP BY table_schema , table_name , index_name ) ) s WHERE t.table_schema = s.table_schema AND t.table_name = s.table_name AND t.table_schema = '数据库名' -- 指定某一个库名 ORDER BY SELECTIVITY;
shell> mysql -uroot -p<password> -e 'show processlist \G' | grep 'State:' | sort | uniq -c | sort -rn
analyze table <table_name>;
optimize table <table_name>;
check table <table_name>;
repair table <table_name>;
# 检查全部表 shell> mysqlcheck -u root -p<password> -A -c # 修复全部表 shell> mysqlcheck -u root -p<password> -A -c
shell> awk '/^# Time:/{print $3, $4, c;c=0}/^# User/{c++}' slowquery.log
基于position
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-position=<start_pos> --stop-position=<stop_pos> <mysql binlog文件> > result.sql
基于时间点
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-datetime='<开始时间>' --stop-datetime='<结束时间>' <mysql binlog文件> > result.sql
查看某个pos的日志
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS <mysql binlog文件> | grep -A '20' <pos>
统计各进程打开句柄数:
lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr | head -n 10 # 某个进程 lsof -n|awk '$2=="<某个进程的PID>" {print $2}'|sort|uniq -c|sort -nr | head -n 10
统计各用户打开句柄数
lsof -n|awk '{print $3}'|sort|uniq -c|sort -nr # mysql用户 lsof -n|awk '$3 == "mysql" {print $3}'|sort|uniq -c|sort -nr
统计各命令打开句柄数
lsof -n|awk '{print $1}'|sort|uniq -c|sort -nr
#/bin/bash user='username' pass='password' sock='socket' expgrants() { mysql -B -u"${user}" -p"${pass}" -S"${sock}" -N $@ -e "SELECT CONCAT( 'SHOW CREATE USER ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \ mysql -u"${user}" -p"${pass}" -S"${sock}" -f $@ | \ sed 's#$#;#g;s/^\(CREATE USER for .*\)/-- \1 /;/--/{x;p;x;}' mysql -B -u"${user}" -p"${pass}" -S"${sock}" -N $@ -e "SELECT CONCAT( 'SHOW GRANTS FOR ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \ mysql -u"${user}" -p"${pass}" -S"${sock}" -f $@ | \ sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/-- \1 /;/--/{x;p;x;}' }
而后执行脚本
方法一
select concat('KILL ',id,';') from information_schema.processlist where user='某个用户' into outfile '/tmp/kill.txt'; source /tmp/kill.txt;
方法二
mysqladmin -uroot -p processlist|awk -F "|" '{if($3 == "要杀的链接的用户")print $2}'|xargs -n 1 mysqladmin -uroot -p kill