這裏記錄的是這兩年學習工做過程當中遇到的經常使用的 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