Mysql
MYSQL(Centos 6、5……系)/Mariadb(Centos 7系)要點:
1.mysql-server服務器的安裝部署。[採用SQL語言管理的關係型數據庫]
2.常見的mysql數據庫、表的管理(增、刪、改、查)語句。
3.mysql數據庫、表的備份方法。
4.mysql的幾種日誌文件。
5.mysql的集羣部署:主從複製、讀寫分離、高可用
6.部署一個LAMP環境的Web服務器。以論壇、電商網站作爲網站實例。
關係型數據庫(SQL):採用SQL語言管理,採用"數據表格"存儲數據。(前期必須將表格式設計合理,後期
難以修改)通常用於企業的網站、OA信息系統。
常見的關係型數據庫系統有:mysql-server(SUN公司-->Oracle公司)、SQL Server(微軟)、Oracle數據庫
(商用,銀行、金融公司會用)
非關係型數據庫(No SQL):不採用SQL語言管理,採用"鍵值對"來存儲數據。(不採用表存儲數據,後期修
改很靈活)通常用戶大數據分析處理。
常見的非關係型數據庫系統有:redis、mongodb……
mysql的學習技巧:
理解mysql的數據庫、表的時候可以跟excel進行類比,可以讓我們更容易理解和學懂mysql的操作。
mariadb-server服務器、mariadb客戶端的安裝部署:
1.查軟件是否已安裝。
rpm -q mariadb-server mariadb
2.安裝軟件
yum install -y mariadb-server mariadb
3.啓動服務器端的服務,允許開機自動啓動。
systemctl restart mariadb
systemctl enable mariad
4.內測:用mariadb的root賬號登錄到本地mariadb-server服務器上。(以下常用SQL語句必須很熟練)
mysql 等同於 mysql -uroot 在mysql服務器本地以root身份登錄
exit 退出登錄。
mysql -uroot -p -h 127.0.0.1 提示輸入密碼時,直接回車即可,因爲默認的root初始密碼爲空
? 或 \h 或 help 顯示mysql的命令幫助
status 或 \s 顯示mysql的工作狀態
help show 顯示show命令的幫助
show databases; 顯示庫文件列表
use mysql; 打開mysql這個數據庫
show tables; 顯示當前數據庫中的所有表的名稱
select user,host,password from mysql.user; 在mysql數據庫文件中user表中查看user、hosts、
password字段的內容。
grant all on . to jin@'%' identified by 'jin' with grant option; 創建一個擁有全部權限的jin
用戶賬號
2/125
grant all on . to jin@'localhost' identified by 'jin' with grant option; 創建允許本地登錄
的jin賬號
select user,host,password from mysql.user; 在mysql數據庫文件中user表中查看user、hosts、
password字段的內容。
exit 或 \q 退出mysql登錄
mysql -ujin -pjin 用jin用戶登錄到本地的mysql數據庫服務器
注意:切記,mariadb數據庫服務的賬號是獨立的,根Linux系統的賬號沒有任何關係。
用excel來類比mysql數據庫的概念:
1.庫文件(數據庫database/db):可以理解成一個excel文件。一個庫(database)文件中可以有0~n張表
(table)。mysql的庫文件默認保存在/var/lib/mysql目錄中,庫文件在linux系統中是以"目錄的形式存在的",
庫目錄中存放的是此數據庫的表。
2.表(table):可以理解成excel文件中的一張表。一張表中可以有1~n個字段。表在linux系統中是文件名的
形式保存在庫的目錄中。
3.字段(field):可以理解成excel表中的表頭的列標題。一個字段可以包含0~n行記錄(record)。字段和記錄
是以正文的形式保存在表文件中的。
mysql應用場景:
1.用來存儲網站的重要數據信息,如電商、論壇、博客、影視網站(如優酷、愛奇藝)等網站的用戶賬號id和
密碼信息、商品信息、影片信息等。
注意:數據庫中是不存儲圖片、視頻文件的,只存文本信息,數據庫中通常只存音視頻、圖片文件的路徑
文本信息(即元數據)。
2.用來存儲一些手機APP(如淘寶app、京東app)的用戶賬號、商品、音視頻的數據信息。
mysql和應用間的工作流程架構:
3/125
情況說明:
對於訪問量(併發量)不大的web應用程序,apache和mysql服務器軟件可以用一臺物理機或虛擬機來實現,
訪問量大的web應用程序,就得把apache和mysql業務分開。
Mysql語句默寫
SQL語句(2019-03-13-AM-默寫):
庫的操作:
1.查庫:show databases;
2.建庫:create database 庫名 [選項];
3.開庫:use 庫名;
4.刪庫:drop database 庫名;
4/125
表的操作:
1.查表(顯示庫中的表文件):show tables;
2.建表:create table 表名(字段1 類型 約束,字段2 類型 約束,...);
3.查表結構:desc 表名;
4.表中新增一列(在最後):alter table 表名 add 字段名 類型 約束;
5.刪除表中的sex這個字段(列):alter table 表名 drop sex;
6.刪除表:drop table 表名;
記錄操作:
1.查表中的所有記錄:select from 表名;
2.查test庫中表tb1的id<=3的所有記錄:select from test.tb1 where id<=3;
3.在tb1表中插入一行記錄:insert into tb1 values(值1,值2,...);
4.更新tb1表中name爲jack的記錄,將他的name值更新成jacker:
update tb1 set name='jacker' where name='jack';
5.刪除tb1表中id<=3的記錄:delete from tb1 where id<=3;
授權管理(用戶安全管理):
1.查mysql庫中user表的user、host、password字段的數據記錄:(查mysql系統中的用戶賬號)
select user,host,password from mysql.user;
2.在mysql中創建一個跟root賬號相同權限的新賬號admin:
grant all on . to admin@'%' identified by '密碼' with grant option;
3.查看root賬號的授權信息:
show grants for root@'localhost';
4.回收admin賬號的insert、update、delete權限:
revoke insert,update,delete on . from admin@'主機名或IP';
5.刪除admin賬號:
drop user admin@'主機名或IP';
Mysql的庫、表、記錄的增刪改
庫(database)的增、刪、改、查命令操作
查:show databases;
增:create database 庫名;
刪:drop database 庫名;
表(table)的增、刪、改、查命令操作
查:show tables;
增:create able 表名(字段名1 數據類型)
查表結構:desc 表名;
刪:drop table 表名;
修改表:alter table 表名 add 字段名 數據類型;
alter table 表名 modify 字段名 新數據類型
alter table 表名 change 舊字段名 新字段名 新數據類型
alter table 表名 drop 字段名
記錄的增、刪、改、查命令操作
查:select * from 表名 [where 條件]
增:insert into 表名[(字段1,字段2,.)] values(值1,值2,.),(值1,值2,.);
5/125
更新:update [庫名.]表名 set 字段名='新值'[where 件];
刪:delete from [庫名.]表名 [where 條件];
Mysql的root密碼遺忘後的重設方法
1、修改/etc/my.cnf主配置文件。
vim /etc/my.cnf
[mysqld]
skip-grant-table 跳過權限表驗證(添加此行)
2、重啓mariadb服務,在mysql-server服務器本地免密碼登錄,做更新root密碼的操作
3、修改/etc/my.cnf主配置文件。
vim /etc/my.cnf
[mysqld]
#skip-grant-table 註釋或刪除此行
4、重啓mariadb服務
5、在mysql-server服務器本地使用root賬號和新密碼登錄,登錄成功,就說明密碼重設成功
Mysql主從複製工作原理和配置步驟
主從複製工作原理:在主庫上把數據更改記錄到二進制日誌中,備庫監測並讀主庫主機上的二進制日誌文
件新增的內容,且將新內容寫入到備庫主機自己的中繼日誌文件中,讀取備庫主機上中繼日誌文件中心的
SQL語句,並且自動執行這些SQL語句,最終在備庫主機上創建了這個庫。
配置步驟:
1.在master主機上的/etc/my.cnf主配置文件中開啓binlog二進制日誌文件功能,並且給主機設置server-id
唯一標識編號,重啓mariadb服務。
2.在master主機上創建用於主從複製的用戶賬號,並查看master狀態中的binlog日誌文件的position位置
數值。
3.在slave主機上的/etc/my.cnf主配置文件中設置server-id唯一標識編號,重啓mariadb服務。
4.在slave主機上用help change master查命令幫助,並用change master命令告訴slave主機他的master
主人的正確信息。
5.在slave主機上用start slave啓動mariadb的隨從服務,並用show slave status查看AB主從複製的數據同步
狀態,要確認兩個線程的yes狀態。
數據庫的邏輯備份和物理備份
邏輯備份就是將數據中的表備份成create table、insert into等表和數據記錄的SQL語句。
物理備份就是就是將數據庫、表的源文件(/var/lib/mysql/庫名目錄)複製或tar打包壓縮一份到別的目錄
中。
物理備份的模式:
冷備份:首先,停止數據庫的服務,然後用cp、tar命令對數據庫文件進行備份。
熱備份:直接在數據庫服務運行的狀態下做備份,需要用mysql的第三方備份和恢復工具進行操作。
單庫全表備份:
mysqldump -uroot -p'密碼' 庫名 > 備份文件名.sql
單庫全表恢復:
mysql -uroot -p'密碼'-e 'create database 庫名;show databases;'
mysql -uroot -p456 庫名 < 備份文件名.sql
mysql -uroot -p'密碼' -e 'use 庫名;show tables;'
單庫單表備份:
mysqldump -uroot -p'密碼' 庫名 表名 > 備份文件名.sql
單庫單表恢復:
6/125
mysql -uroot -p'密碼' -e 'create database 庫名;show
mysql -uroot -p'密碼' 庫名 < 備份文件名.sql
mysql -uroot -p'密碼' -e 'use 庫名;show tables;select from 表名'
mysql庫表基本操作
練習:在mysql數據庫中完成以下操作。
1.在mysql服務器本地登錄進行數據庫的管理。
2.查看服務器上的庫文件名列表,創建一個名稱爲mydb的庫文件。打開mydb這個庫文件。
3.查看mydb庫中的表,創建一個名稱爲tb1的表。表中有id、name、sex、qq、addr字段,字段的數據類
型全部爲char字符型,寬度爲25個字符。
4.查看tb1表中的全部字段的全部記錄,插入2條記錄到表中,在查一次表的全部記錄。
5.附加操作,退出數據庫的登錄。查看mydb數據庫文件中的表。
操作步驟參考:
1.在mysql服務器本地登錄進行數據庫的管理。
mysql 或 mysql -uroot
2.查看服務器上的庫文件名列表,創建一個名稱爲mydb的庫文件。打開mydb這個庫文件。
show databases;
create database mydb;
use mydb;
3.查看mydb庫中的表,創建一個名稱爲tb1的表。表中有id、name、sex、qq、addr字段,id字段的數據
類型爲int整型,其他字段的數據類型全部爲char字符型,寬度爲25個字符。
show tables;
create table tb1(
id int,
name char(25),
sex char(25),
qq char(25),
addr char(25)
);
4.顯示tb1的表結構,查看tb1表中的全部字段的全部記錄,插入3條記錄到表中,在查一次表的全部記
錄。
desc tb1;
select from tb1;
insert into tb1 values(1,'lucy','fmale','123456','qf');
7/125
insert into tb1 values
(2,'tom','male','1314520','qf'),
(3,'jack','male','1213520','qf');
select from tb1;
5.附加操作,退出數據庫的登錄。查看mydb數據庫文件中的表。
exit
ls -R /var/lib/mysql/mydb
cat /var/lib/mysql/mydb/db.opt mydb庫文件的選項(option)配置文件
練習:在mysql服務器本地登錄數據庫系統,顯示數據庫文件列表,打開mydb庫文件,創建一個名稱爲tb2
的表,表中包含id、name這兩個字段,顯示tb2表結構,在tb2表中插入2條記錄。記錄的內容自己看着
辦。
mysql遠程管理的方式
方法一:(linux系統管理員採用)
首先用ssh遠程登錄到linux或windows系統,然後從linux或windows系統本地用mysql客戶端命令登錄到
mysql-server數據庫服務器。
方法二:(DBA[database administrator]數據庫管理員採用)
直接在linux或windows系統的主機上用mysql的客戶端命令或mysql的第三方客戶端軟件(如Navicat)來直
接遠程登錄到mysql-server數據庫服務器。
8/125
創建遠程管理數據庫的賬號:
grant all on . to 用戶名@'客戶端主機名或IP' identified by '密碼' with grant option;
說明:用help grant查看grant命令的幫助信息
grant命令語法格式:
grant 權限1,權限2,權限n on 庫名稱.表名稱 to 用戶名@'客戶端主機名或IP' identified by
'密碼' with 選項 option;
權限:all 表示有跟root相同的所有權限,權限還可以是select、update、create、delete、drop等操作權
限。
庫名稱.表名稱 表示此用戶允許操作的庫和表。.*就表示允許此用戶操作所有的庫和表。
客戶端主機名或IP的寫法:
localhost 表示本地主機(即本機自己)
% 表示任何IP的客戶主機
192.168.11.% 表示192.168.11.0網段的所有客戶端主機
172.16.%.% 表示172.16.0.0網段的所有客戶端主機
IP地址的A、B、C類取值範圍:
A類 1.0.0.0~127.255.255.255
B類 128.0.0.0~191.255.255.255
C類 192.0.0.0~223.255.255.255
with 選項: 常見選項如下
grant option 表示此用戶擁有用grant命令創建新用戶賬號的權限
MAX_QUERIES_PER_HOUR 90 每小時最多請求90次
MAX_UPDATES_PER_HOUR count 每小時最多更新count次
MAX_CONNECTIONS_PER_HOUR count 每小時最多登陸連接count次(即併發量)
MAX_USER_CONNECTIONS count 每小時最多用戶連接count次
9/125
MySQL數據庫操作
MySQL數據庫基本操作
一、初識SQL語言
SQL(Structured Query Language 即結構化查詢語言)
SQL語言主要用於存取數據、查詢數據、更新數據和管理關係數據庫系統,SQL語言由IBM開發。SQL語言
分爲3種類型:
DDL語句 數據庫定義語言(Data Definition Language): 數據庫、表、視圖、索引、存儲過程,例如
CREATE DROP ALTER
DML語句 數據庫操縱語言(Data Manipulation Language): 插入數據INSERT、刪除數據DELETE、更新
數據UPDATE、查詢數據SELECT
DCL語句 數據庫控制語言(Data Control Language): 例如控制用戶的訪問權限GRANT(授予權限
)、REVOKE(收回權限)
二、系統數據庫(即mysql自帶的庫文件)
information_schema: 虛擬庫,主要存儲了系統中的一些數據庫對象的信息,例如用戶表信息、列信
息、權限信息、字符信息等
performance_schema: 主要存儲數據庫服務器的性能(performance)參數
mysql: 授權庫,主要存儲系統用戶的權限信息
test: MySQL數據庫系統自動創建的測試數據庫
創建需要的業務主庫(用戶自己創建新庫、新表)...
練習:給mysql-server的root用戶分別設置本地、遠程登錄密碼。
grant all on . to root@'localhost' identified by 'root';
grant all on . to root@'%' identified by 'root';
flush privileges; 刷新權限表
select user,host,password from mysql.user; 查詢mysql庫中user表的user、host、password這3列
的數據記錄信息。
exit 或 \q
再次登錄測試:
mysql 無密碼登錄,提示錯誤
mysql -uroot -proot 用root用戶和密碼登錄,成功登錄
三、忘記MySQL密碼
vim /etc/my.cnf 這是mariadb和mysql的主配置文件
[mysqld]
skip-grant-table 此行爲跳過權限表的驗證,實現無密碼訪問數據庫
#重啓mariadb或mysqld數據庫服務
systemctl restart mariadb 或 service mysqld restart
mysql 免密碼登錄
mysql> select user,password,host from mysql.user; (選做)
+------+-------------------------------------------+-----------+
| user | password | host |
10/125
+------+-------------------------------------------+-----------+
| root | *F861720E101148897B0F5239DB926E756B1C28B3 | localhost |
| root | | sxl.com |
| root | | 127.0.0.1 |
| root | | ::1 |
| | | localhost |
| | | sxl.com |
+------+-------------------------------------------+-----------+
6 rows in set (0.00 sec)
更新mysql數據庫中user表中的root用戶的密碼爲127:
mysql> update mysql.user set password=password("127") where user="root" and host="localhost";
update命令語法:
update 庫名.表名 set 字段名=新值(可用mysql函數) where 匹配條件
刷新權限表:
mysql> flush privileges;
mysql> \q 或 exit
vim /etc/my.cnf
[mysqld]
#skip-grant-table 註釋或刪掉此行
systemctl restart mariadb (centos 7版) 或 service mysqld restart (centos 6版)
再次登錄測試:
mysql 無密碼登錄,提示錯誤
mysql -uroot -p127 用root用戶和密碼登錄,成功登錄
創建業務數據庫
語法
CREATE DATABASE 數據庫名;
數據庫命名規則:
區分大小寫
唯一性
不能使用關鍵字如 create select
不能單獨使用數字
查看數據庫
SHOW DATABASES;
選擇數據庫
USE 數據庫名
SELECT database(); 返回當前數據庫的名字
刪除數據庫
DROP DATABASE 數據庫名;
實例:創建數據庫,創建數據表。
創建數據庫
create database db1;
打開數據庫
11/125
use db1;
修改庫名??
創建表(字段名稱 類型(值的範圍))
mysql> use test; 打開test庫
mysql> show tables; --查看當前所有表
mysql> create table emp(id int,name char(20),salary int,type char(20)); --創建表
mysql> desc emp; --查看錶屬性(即表結構)
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | char(20) | YES | | NULL | |
| salary | int(11) | YES | | NULL | |
| type | char(20) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)
#在表中插入數據記錄
mysql> insert into emp value(1,'haha',5000,'oracle'); --表內添加數據
mysql> insert into emp values (2,'up02',6000,'linux') , (3,'qf03',9000,'cloud');
mysql> select * from emp; --查看emp表內數據
mysql> exit; --退出mysql的登錄
[root@localhost python]# mysql -uroot -p
mysql> create table test.dept (deptno int,dname varchar(20),locate varchar(20))engine=innodb;
mysql> desc test.dept;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| deptno | int(11) | YES | | NULL | |
| dname | varchar(20) | YES | | NULL | |
| locate | varchar(20) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
--以上create table時指定存儲引擎爲innodb,該引擎支持事務
mysql> use test; --打開test庫
mysql> insert into dept values(1,'oracle','1F') ;
mysql> select from dept;
+--------+--------+--------+
| deptno | dname | locate |
+--------+--------+--------+
| 1 | oracle | 1F |
+--------+--------+--------+
1 row in set (0.00 sec)
mysql> insert into dept values(2,'linux','2F') ;
mysql> insert into dept values(3,'win','3F') ;
mysql> select from dept ;
mysql> select * from dept where locate='2F';
#以下命令不操作
12/125
/usr/local/mysql/bin/mysqld --verbose --help | less
Default options are read from the following files in the given order:
/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf
忘記MySQL密碼
忘記MySQL密碼的解決
vim /etc/my.cnf 這是mariadb和mysql的主配置文件
[mysqld]
skip-grant-table 此行爲跳過權限表的驗證,實現無密碼訪問數據庫
#重啓mariadb或mysqld數據庫服務
systemctl restart mariadb 或 service mysqld restart
mysql 免密碼登錄
mysql> select user,password,host from mysql.user; (選做)
+------+----------------- --------------------------+-----------+
| user | password | host |
+------+-------------------------------------------+-----------+
| root | *F861720E101148897B0F5239DB926E756B1C28B3 | localhost |
| root | | sxl.com |
| root | | 127.0.0.1 |
| root | | ::1 |
| | | localhost |
| | | sxl.com |
+------+-------------------------------------------+-----------+
6 rows in set (0.00 sec)
更新mysql數據庫中user表中的root用戶的密碼爲127:
mysql> update mysql.user set password=password("127") where user="root" and host="localhost";
update命令語法:
update 庫名.表名 set 字段名=新值(可用mysql函數) where 匹配條件
刷新權限表:
mysql> flush privileges;
mysql> \q 或 exit
vim /etc/my.cnf
[mysqld]
#skip-grant-table 註釋或刪掉此行
systemctl restart mariadb (centos 7版) 或 service mysqld restart (centos 6版)
再次登錄測試:
mysql 無密碼登錄,提示錯誤
mysql -uroot -p127 用root用戶和密碼登錄,成功登錄
13/125
MySQL表操作
MySQL表操作 DDL
表是數據庫存儲數據的基本單位,由若干個字段組成,主要用來存儲數據記錄。表的操作包括創建表、查
看錶、修改表和刪除表。
這些操作都是數據庫管理中最基本,也是最重要的操作。本節內容包括:
創建表: create table 表名(字段1 數據類型,字段2 數據類型,...)
查看錶結構: desc 表名
show create table 表名
表完整性約束.....
主鍵:primary key
外鍵:foreign key
……
修改表 alter table
複製表 create table ...
刪除表 drop table
五、複製表
警告:要先準備一張有數據的源表,否則無法正常完成下面的實驗。
複製表結構和記錄 (key不會複製: 主鍵、外鍵和索引)
命令格式:create table 新表名 select from 源表名;
實例:下面是將service的表結構和數據複製到new_service表中。
mysql> create table new_service select from service;
提示:複製表之後,請用show tables、desc和select命令查看錶的相關信息。
只複製表結構
命令格式:create table 新表名 select from 源表名 where 1=2;
mysql> create table new1_service select from service where 1=2; //由於1不等於2,條件爲假,查
不到任何記錄
複製表結構,包括Key
命令格式:create table 新表名 like 源表名;
mysql> create table t4 like employees;
複製表記錄:下面是隻複製了某條記錄
命令格式:insert into 目標表名 select from 源表名 where 字段名=值;
mysql> insert into t4 select from company.employees where id=1;
刪除表中的所有記錄:
命令格式:delete from 表名;
複製表記錄:下面是複製所有的條記錄
命令格式:insert into 目標表名 select from 源表名;
mysql> insert into t4 select from company.employees;
六、刪除表
DROP TABLE 表名;
14/125
七、刪除庫
drop database 庫名;
一、創建表(表的基本操作)
任務目標:創建school庫,在school庫中創建student1表,表中有id、name、sex、age這四個字段,最後
在表中插入3條記錄,查詢表中的數據記錄。
表school.student1
字段1 字段2 字段3 字段4
id name sex age
1 tom male 23 記錄1
2 jack male 21 記錄2
3 alice female 19 記錄3
語法:
create table 表名(
字段名1 類型[(寬度) 約束條件],
字段名2 類型[(寬度) 約束條件],
字段名3 類型[(寬度) 約束條件]
)[存儲引擎 字符集];
==在同一張表中,字段名是不能相同
==寬度和約束條件可選
==字段名和類型是必須的
mysql> CREATE DATABASE school; //創建數據庫school
mysql> use school;
mysql> create table student1(
-> id int,
-> name varchar(50),
-> sex enum('m','f'),
-> age int
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> create table test100(id int)engine=innodb;
mysql> desc student1; //查看數據表student1的結構,結果如下
mysql> show tables; //查看錶(當前所在庫)
15/125
+------------------+
| Tables_in_school |
+------------------+
| student1 |
+------------------+
1 row in set (0.00 sec)
mysql> select id,name,sex,age from student1; //查詢表中所有字段的值
Empty set (0.00 sec)
mysql> select * from student1; //查詢表中所有字段的值
Empty set (0.00 sec)
mysql> select name,age from student1; //查詢表中指定字段的值
Empty set (0.00 sec)
向表中插入內容
語法:
insert into 表名(字段1,字段2...) values(字段值列表...);
查看錶結構
順序插入
只向指定的字段插入值
16/125
表school.student2
id id int
姓名 name varchar(50)
出生年份 born_year year
生日 birthday date
上課時間 class_time time
註冊時間 reg_time datetime
mysql> create table student2(
-> id int,
-> name varchar(50),
-> born_year year, 數據類型爲年
-> birthday date, 數據類型爲日期,即顯示年、月、日
-> class_time time, 數據類型爲時間,格式爲 時:分:秒
-> reg_time datetime 數據類型爲日期+時間
-> );
mysql> desc student2;
mysql> insert into student2 values(1,'tom',now(),now(),now(),now());
mysql> insert into student2 values(2,'jack',1982,19821120,123000,20140415162545);
mysql> select from student2;
說明:now()是mysql中內定的函數,功能是獲取當前的系統時間。
mysql> alter table student2 add newf datetime; //在表中添加新字段newf
mysql> desc student2; //顯示student2的表結構(即表的屬性)
mysql> select from student2;
mysql> alter table student2 drop newf; //在表中刪除字段newf
表school.student3
17/125
id int
姓名 name varchar(50)
性別 sex enum('male','female')
愛好 hobby set('music','book','game','disc')
說明:
enum枚舉型:相當於單選題,只能填其中一個選項。
set設置型(也稱集合型):相當於多選題,可以填其中的一個或多個選項。
mysql> create table student3(
-> id int,
-> name varchar(50),
-> sex enum('male','female'),
-> hobby set('music','book','game','disc')
-> );
mysql> desc student3;
mysql> show create table student3\G 查看student3表創建的過程
mysql> insert into student3 values (1,'tom','male','book,game');
mysql> insert into student3 values (2,'jack','male','film');
mysql> select * from student3;
mysql> update student3 set hobby='music' where id=2; 更新數據
更新前的數據記錄 更新後的數據記錄
student3表的小結:
1、如果對字段的取值用set進行了範圍設置,當插入數據時填寫了範圍以外的數據,將不被識別。例如上
面紅色的“film”
二、查看錶結構
DESCRIBE查看錶結構
DESCRIBE 表名;
DESC 表名;
SHOW CREATE TABLE查看錶詳細結構
SHOW CREATE TABLE 表名;
三、表完整性約束
作用:用於保證數據的完整性和一致性
約束條件 說明
PRIMARY KEY (PK) 標識此字段爲此表的主鍵,可以唯一的標識記錄,不可以爲空 UNIQUE +
NOT NULL
FOREIGN KEY (FK) 標識此字段爲此表的外鍵,實現子表與父表(父表主鍵/子表1外鍵/子表2
外鍵)之間的關聯
18/125
NOT NULL 標識此字段不能爲空,如網上註冊賬號時的必填項就要用此功能
UNIQUE KEY (UK) 唯一鍵,標識此字段的值是唯一的,可以爲空,一個表中可以有多個
UNIQUE KEY
AUTO_INCREMENT 標識此字段的值自動增長(整數類型,而且爲主鍵),通常用在“序號”字段
DEFAULT 爲此字段設置默認值,用戶不填寫此信息是默認填寫此值。
UNSIGNED 無符號,正數
ZEROFILL 使用0填充,如填寫0000001這種記錄是可以使用此約束
說明:
- 是否允許爲空,默認NULL,可設置NOT NULL,字段不允許爲空,必須賦值
- 字段是否有默認值,缺省的默認值是NULL,如果插入記錄時不給字段賦值,此字段使用默認值
sex enum('male','female') not null default 'male'
age int unsigned NOT NULL default 20 必須爲正值(無符號) 不允許爲空 默認是20 -
是否是key
主鍵 primary key
外鍵 forengn key
索引 (index,unique...)===DEFAULT、NOT NULL
default:指定默認值
not null:不允許爲空。就類似於我們在網上註冊賬號時,有些內容必須要填寫,空着就提交不了。
表school.student4
19/125
mysql> insert into student4 values(1,'jack','m',20,'book');
Query OK, 1 row affected (0.00 sec)
mysql> select from student4;
mysql> insert into student4(id,name) values(2,'robin'); 沒定義的取默認值
Query OK, 1 row affected (0.00 sec)
mysql> insert into student4 values(3,NULL,'m',40,'book');
ERROR 1048 (23000): Column 'name' cannot be null //錯誤提示:列‘name’不能爲空
===設置唯一約束 UNIQUE
唯一約束:控制此列的值不允許重複,必須是唯一的一個值。
表company.department1
mysql>create database company;
mysql>CREATE TABLE company.department1 (
dept_id INT,
dept_name VARCHAR(30) UNIQUE,
comment VARCHAR(50)
);
20/125
表company.department2
CREATE TABLE company.department2 (
-> dept_id INT,
-> dept_name VARCHAR(30),
-> comment VARCHAR(50),
-> CONSTRAINT uk_name UNIQUE(dept_name)
-> );
21/125
===設置主鍵約束 PRIMARY KEY
primary key字段的值是不允許重複,且不允許爲空NULL(UNIQUE + NOT NULL)
單列做主鍵
多列做主鍵(複合主鍵)
單列做主鍵
表school.student6 方法一
mysql> use school;
mysql> create table student6(
id int primary key not null auto_increment,
name varchar(50) not null,
sex enum('male','female') not null default 'male',
age int not null default 18
);
Query OK, 0 rows affected (0.00 sec)
說明:auto_increment 表示自動生成順序編號
表school.student7 方法二
mysql> create table student7(
-> id int auto_increment not null,
-> name varchar(50) not null,
-> sex enum('male','female') not null default 'male',
-> age int not null default 18,
-> CONSTRAINT pk_id primary key(id) pk_id名稱
22/125
-> );
Query OK, 0 rows affected (0.00 sec)
MySQL 錯誤:there can be only one auto column and it must bedefined as a key
mysql> insert into student6 values (1,'alice','female',22);
mysql> insert into student6(name,sex,age) values
-> ('jack','male',19),
-> ('tom','male',23);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select from student6;
+----+-------+------+-----+
| id | name | sex | age |
+----+-------+------+-----+
| 1 | alice | female | 22 |
| 2 | jack | male | 19 |
| 3 | tom | male | 23 |
+----+-------+------+-----+
3 rows in set (0.00 sec)
23/125
複合主鍵
應用場合:需要用兩列的值來標識數據的唯一性。
表school.service
host_ip 存儲主機IP
service_name 服務名
port 服務對應的端口
allow(allow,deny) 服務是否允許訪問
主鍵: host_ip + port = primary key
mysql> create table service(
host_ip varchar(15) not null,
service_name varchar(10) not null,
port varchar(5) not null,
allow enum('Y','N') default 'N',
primary key(host_ip,port)
);
Query OK, 0 rows affected (0.00 sec)
24/125
mysql> insert into service values ('192.168.2.168','ftp','21','Y');
mysql> insert into service values ('192.168.2.168','httpd','80','Y');
mysql>select * from service;
===設置字段值增 AUTO_INCREMENT
表company.department3
CREATE TABLE department3 (
dept_id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(30),
comment VARCHAR(50)
);
===設置外鍵約束 FOREIGN KEY
父表company.employees(員工)
mysql>create database company;
mysql>use company;
mysql> create table employees(
-> name varchar(50) not null,
-> mail varchar(20),
25/125
-> primary key(name) 聲明name爲主鍵(即主要關鍵字)
-> )engine=innodb;
子表company.payroll(工資)
mysql> create table payroll(
-> id int not null auto_increment,
-> pname varchar(50) not null,
-> payroll float(10,2) not null, 數據類型爲float浮點型(即小數)
-> primary key(id), 聲明id爲主鍵
-> foreign key(pname) 聲明payroll表中的pname字段爲外鍵
-> references employees(name) 設置外鍵pname的數據來源爲employess表中的name
-> on update cascade 聲明兩張表中的數據會同步更新
-> on delete cascade 聲明兩張表中的數據會同步刪除
-> )engine=innodb;
子表name外鍵,關聯父表(employees 主鍵name),同步更新,同步刪除
cascade 刪除包含與已刪除鍵值有參照關係的所有記錄
#首先,在父表employees中插入tom、jack的記錄。
mysql> insert into employees values('tom','163.com'),
('jack','126.net');
#然後,在子表payroll中插入tom、jack的記錄。
mysql> insert into payroll(pname,payroll) values('lucy',16.8); 會提示錯誤,因爲做了外鍵關聯,並
且父表中沒有lucy的信息
mysql> insert into payroll(pname,payroll) values
('tom',15.6),
('jack',100.5);
26/125
mysql> update employees set name='tomaaa' where name='tom';
mysql> select from emplyees;
mysql> select from payroll;
mysql> delete from employees where name='jack';
結論:
0、外鍵的作用就是實現在子表中引用父表中某列的值,這樣子表中外鍵的值是依賴於父表的。
1、父表中的主鍵才能作爲子表中的外鍵。
2、當父表中某個員工的記錄修改時,子表也會同步修改
3、當父表中刪除某個員工的記錄,子表也會同步刪除
四、修改表ALTER TABLE
語法:
- 修改表名
ALTER TABLE 表名
RENAME 新表名;
小結:相當於excel中雙擊表的名字,然後輸入新的表名。 -
增加字段(增加字段後請用"desc 表名"查看錶結構)
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…],
ADD 字段名 數據類型 [完整性約束條件…];
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] FIRST;
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] AFTER 字段名;
小結:增加字段就相當於excel表格中插入一列格子。 - 刪除字段
ALTER TABLE 表名
DROP 字段名;
小結:相當於excel中刪除一列格子。 - 修改字段
ALTER TABLE 表名
MODIFY 字段名 數據類型 [完整性約束條件…];
ALTER TABLE 表名
CHANGE 舊字段名 新字段名 舊數據類型 [完整性約束條件…];
ALTER TABLE 表名
CHANGE 舊字段名 新字段名 新數據類型 [完整性約束條件…];
小結:相當於Excel表格中修改表的列標題。
示例: - 修改存儲引擎
mysql> alter table service
-> engine=innodb; //engine=myisam|memore|....
27/125
show create table school.service; - 添加字段
mysql> create table student10 (id int);
mysql> alter table student10
-> add name varchar(20) not null,
-> add age int not null default 22;
mysql> alter table student10
-> add stu_num int not null after name; //添加name字段之後
mysql> alter table student10
-> add sex enum('male','female') default 'male' first; //添加到最前面
- 刪除字段
mysql> alter table student10
-> drop sex;
mysql> alter table service
-> drop mac; - 修改字段類型modify
mysql> alter table student10
-> modify age tinyint;
mysql> alter table student10
-> modify id int not null primary key ; //修改字段類型、約束、主鍵
- 增加約束(針對已有的主鍵增加auto_increment)
mysql> alter table student10 modify id int not null primary key auto_increment; //錯誤,該字段
已經是primary key
ERROR 1068 (42000): Multiple primary key defined
mysql> alter table student10 modify id int not null auto_increment;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0 - 增加複合主鍵:注意,此功能用於表中沒有主鍵的情況下。
mysql> alter table service
-> add primary key(host_ip,port); - 增加主鍵
mysql> alter table student1
-> add primary key(id); - 增加主鍵和自動增長
mysql> alter table student1
-> modify id int not null primary key auto_increment; -
刪除主鍵
a. 刪除自增約束(修改字段的類型即可)
mysql> alter table student10 modify id int not null;
28/125
b. 刪除主鍵
mysql> alter table student10 drop primary key;
主鍵處理的小結:
如果表中已設置過主鍵,並且這個主鍵是“自動增長”的類型,此時想設置複合主鍵的話,必須先對此主鍵
取消自動增長,然後刪除此主鍵,最後再設置複合主鍵才行,否則會失敗。MySQL單表查詢
MySQL單表查詢 SELECT DML簡單查詢
通過條件查詢
查詢排序
限制查詢記錄數
使用集合函數查詢
分組查詢
使用正則表達式查詢
表cmp.emp5
僱員編號 id int
僱員姓名 name varchar(30)
僱員性別 sex enum
僱用時期 hire_date date
職位 post varchar(50)
職位描述 job_description varchar(100)
薪水 salary double(15,2)
辦公室 office int
部門編號 dep_id int
mysql> create database cmp;
mysql> use cmp;
mysql> CREATE TABLE cmp.emp5(
id int primary key AUTO_INCREMENT not null,
name varchar(30) not null,
sex enum('male','female') default 'male' not null,
29/125
hire_date date not null,
post varchar(50) not null,
job_description varchar(100),
salary double(15,2) not null,
office int,
dep_id int
);
mysql> insert into emp5
(name,sex,hire_date,post,job_description,salary,office,dep_id) values
('jack','male','20180202','instructor','teach',5000,501,100),
('tom','male','20180203','instructor','teach',5500,501,100),
('robin','male','20180202','instructor','teach',8000,501,100),
('alice','female','20180202','instructor','teach',7200,501,100),
('tianyun','male','20180202','hr','hrcc',600,502,101),
('harry','male','20180202','hr',NULL,6000,502,101),
('emma','female','20180206','sale','salecc',20000,503,102),
('christine','female','20180205','sale','salecc',2200,503,102),
('zhuzhu','male','20180205','sale',NULL,2200,503,102),
('gougou','male','20180205','sale','',2200,503,102);
一、簡單查詢
簡單查詢
SELECT FROM emp5; 如果表的列過多,將此處的;分號換成\G分組顯示
SELECT name, salary, dep_id FROM emp5;
說明:select 字段1,字段2,字段n from 表名;
避免重複DISTINCT
30/125
SELECT DISTINCT post FROM emp5;
通過四則運算查詢
SELECT name, salary14 FROM emp5;
SELECT name, salary14 AS Annual_salary FROM emp5; 取名年薪
SELECT name, salary14 Annual_salary FROM emp5;
定義顯示格式
CONCAT() 函數用於連接字符串。將多列的值輸出成一列。
SELECT CONCAT(name, ' annual salary: ', salary*14) AS Annual_salary FROM emp5;
說明:中間“藍色的字”是單獨的一個字符串。並不是表中的列標題(即字段)。
二、單條件查詢:相當於excel中的篩選功能,即查詢所需要的數據
條件中用and、between and、is null、not等關鍵字定義條件範圍
單條件查詢
SELECT name,post FROM emp5 WHERE post='hr';
31/125
多條件查詢:and是與(同時滿足這兩個條件),or或(滿足其中一個條件的記錄),not非(不滿足此條件
的記錄)
SELECT name,post,salary FROM emp5 WHERE post='hr' AND salary>4000;
SELECT name,post,salary FROM emp5 WHERE post='hr' or post='sale';
SELECT name,post,salary FROM emp5 WHERE not post='hr';
32/125
關鍵字BETWEEN AND:bettween 起始值 and 截止值
查詢salary在5000到15000的記錄
SELECT name,salary FROM emp5 WHERE salary BETWEEN 5000 AND 15000;
查詢salary不在5000到15000之間的記錄
SELECT name,salary FROM emp5 WHERE salary NOT BETWEEN 5000 AND 15000;
關鍵字IS NULL
查詢job_description字段的值爲空的記錄
SELECT name,job_description FROM emp5 WHERE job_description IS NULL;
SELECT name,job_description FROM emp5 WHERE job_description IS NOT NULL; 不爲空的記
錄
SELECT name,job_description FROM emp5 WHERE jobdescription=''; ''並非是NULL,查的結
果跟NULL不同
33/125
關鍵字IN集合查詢
查詢salary值爲4000、5000、6000或9000的記錄
SELECT name, salary FROM emp5 WHERE salary=4000 OR salary=5000 OR salary=6000 OR
salary=9000 ;
SELECT name, salary FROM emp5 WHERE salary IN (4000,5000,6000,9000) ; 等同於上一行命令的功能
(首選)
SELECT name, salary FROM emp5 WHERE salary NOT IN (4000,5000,6000,9000) ; 不在這個範圍內
的記錄
34/125
關鍵字LIKE模糊查詢
通配符’%’:表示任意一串字符,類似於shell腳本中的星號。
SELECT FROM emp5 WHERE name LIKE 'al%'; 通配
通配符’’:表示任意一個字符,類似於Shell腳本中的?問號。
SELECT FROM emp5 WHERE name LIKE 'al___'; 佔位符(此處有三個佔位符)
三、查詢排序
按單列排序
select from 表名 order by 排序的字段 排序方式(asc升序或desc降序);
SELECT FROM emp5 ORDER BY id desc;
SELECT FROM emp5 ORDER BY salary; 默認是按升序
SELECT name, salary FROM emp5 ORDER BY salary ASC; 升
SELECT name, salary FROM emp5 ORDER BY salary DESC; 降
按多列排序:只有第1列數據中有相同的值時,第2列的排序纔會有效果。
SELECT FROM emp5 ORDER BY hire_date DESC,salary ASC;
參考表格如下:
id type price
01 book 10
02 book 20
03 water 5
04 water 3
05 book 15
四、限制查詢的記錄數
示例:
SELECT FROM emp5 LIMIT 5;
SELECT FROM emp5 ORDER BY salary DESC LIMIT 5; //默認初始位置爲0
SELECT FROM emp5 ORDER BY salary DESC LIMIT 0,5;
SELECT FROM emp5 LIMIT 3,5; //從第4條開始,共顯示5條
35/125
五、使用集合函數查詢
示例:
SELECT COUNT() FROM emp5; 總記錄數(即共有多少行記錄)
SELECT COUNT() FROM emp5 WHERE dep_id=101;指定條件的數量(類似於excel中的countif函
數)
SELECT MAX(salary) FROM emp5; 查詢指定字段的最大值
SELECT MIN(salary) FROM emp5;最小
SELECT AVG(salary) FROM emp5;平均(類似於excel中的average函數)
SELECT SUM(salary) FROM emp5;求和
SELECT SUM(salary) FROM emp5 WHERE dep_id=101;條件求和(類似於excel中的sumif)
mysql> select from emp5 where salary = (SELECT MAX(salary) FROM emp5); 顯示salary最大值的記
錄
測試一下:select max(salary) from emp5;
mysql> select from emp5 where salary = (SELECT MAX(salary) FROM emp5); 顯示salary最小值的記
錄
六、分組查詢
GROUP BY關鍵字和GROUP_CONCAT()函數一起使用
命令格式:select 字段1,字段2 from 表名 group by 分組字段名;
查出表中每個部門的人員名單。
SELECT dep_id,GROUP_CONCAT(name) FROM emp5 GROUP BY dep_id;
小結:由於表中的jack、tom、robin、alice的dep_id號都是100,所以顯示出這樣的分組結果。
上題中的源表內容如下所示
dep_id name
100 jack
100 tom
36/125
100 robin
100 alice
101 tianyun
101 harry
102 emma
102 christine
SELECT dep_id,GROUP_CONCAT(name) as emp_members FROM emp5 GROUP BY dep_id;
GROUP BY與集合函數一起使用
下面是統計每個部門的人數
SELECT dep_id,COUNT(dep_id) FROM emp5 GROUP BY dep_id;
顯示錶中的所有數據,跟上圖進行比較
七、使用REGEXP正則表達式查詢
正則表達式:可以簡單理解成高級的匹配方法。
SELECT FROM emp5 WHERE name REGEXP '^ali'; 以ali開頭的信息,類似於al%
SELECT FROM emp5 WHERE name REGEXP 'yun$'; 以yun結尾的信息,類似於%yun
SELECT FROM emp5 WHERE name REGEXP 'm{2}'; 字符m出現2次的信息,類似於%mm%
37/125
小結:對字符串匹配的方式
WHERE name = 'tom';
WHERE name LIKE 'to%';
WHERE name REGEXP 'yun$';
Mysql多表查詢
MySQL多表查詢
多表連接查詢
複合條件連接查詢
子查詢
一、準備兩張表
表cmp.emp6
mysql> show databases;
mysql> create database cmp;
mysql> use cmp;
mysql> create table emp6( emp_id int auto_increment primary key not null, emp_name varchar
(50), age int, dept_id int);
38/125
insert into emp6(emp_name,age,dept_id) values
('tianyun',19,200),
('tom',26,201),
('alice',24,202),
('robin',40,200),
('natasha',28,204);
39/125
表cmp.dept6
mysql> create table dept6(dept_id int,dept_name varchar(100));
40/125
insert into dept6 values (200, 'hr'),
(201,'it'),
(202,'sale'),
(203,'fd');
二、多表的連接查詢
交叉連接: 生成笛卡爾積,它不使用任何匹配條件(很少用)
內連接: 只連接匹配的行,需要用where指定條件
外連接之左連接: 會顯示左邊表內所有的值,不論在右邊表內匹不匹配
外連接之右連接: 會顯示右邊表內所有的值,不論在左邊表內匹不匹配
全外連接: 包含左、右兩個表的全部行
=================交叉連接(很少用)=======================
簡單用法:select from 表1名,表2名;
mysql> select emp6.emp_name,emp6.age,emp6.dept_id,dept6.dept_name from emp6,dept6;
命令格式:select 表1名.字段1,表1名.字段n,表2名.字段1,表2名.字段n from 表1名,表2名;
41/125
交叉連接的原理圖
=================內連接(等值連接)=======================
只找出有部門的員工 (部門表中沒有natasha所在的部門)
mysql> select emp6.emp_id,emp6.emp_name,emp6.age,dept6.dept_name from emp6,dept6
where emp6.dept_id = dept6.dept_id;
命令格式:select 表1名.字段1,表1名.字段n,表2名.字段1,表2名.字段n from 表1名,表2名 where
條件;
注意:select 命令右側的表1名和表2名可以省略。
42/125
內連接的工作原理圖(等值連接)
mysql> select emp_id,emp_name,age,dept_name from emp6,dept6 where emp6.dept_id =
dept6.dept_id;
外連接語法:
SELECT 字段列表
FROM 表1 LEFT|RIGHT JOIN 表2
ON 表1.字段 = 表2.字段;
43/125
左連接:select 字段列表 from 主表 left join 副表 on 條件;
右連接:select 字段列表 from 副表 right join 主表 on 條件;
=================外連接(左連接 left join)=======================
mysql> select emp_id,emp_name,dept_name from emp6 left join dept6 on emp6.dept_id =
dept6.dept_id;
找出所有員工及所屬的部門,包括沒有部門的員工
左連接的工作原理圖
=================外連接(右連接right join)=======================
mysql> select emp_id,emp_name,dept_name from emp6 right join dept6 on emp6.dept_id =
dept6.dept_id; 以右邊做參照
找出所有部門包含的員工,包括空部門
=================全外連接(等同於交叉連接)=======================
mysql> select from emp6 full join dept6;
44/125
三、複合條件連接查詢
示例1:以內連接的方式查詢emp6和dept6表,並且emp6表中的age字段值必須大於25
mysql> select emp_id, emp_name, age, dept_name from emp6,dept6 where emp6.dept_id =
dept6.dept_id and age>25;
找出公司所有部門中年齡大於25歲的員工
示例2:以內連接的方式查詢emp6和dept6表,並且以age字段的降序方式顯示
mysql> select emp_id, emp_name, age, dept_name from emp6,dept6 where emp6.dept_id =
dept6.dept_id order by age desc;
四、子查詢
子查詢是將一個查詢語句嵌套在另一個查詢語句中。
45/125
內層查詢語句的查詢結果,可以爲外層查詢語句提供查詢條件。
子查詢中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
還可以包含比較運算符:= 、 !=、> 、<等
- 帶IN關鍵字的子查詢
mysql> select * from emp6 where dept_id IN (select dept_id from dept6);
說明:查 emp6表中的所有數據,條件是dept_id必須是dept6表中存在的dept_id記錄。
帶in子查詢的工作原理圖 - 帶比較運算符的子查詢
=、!=、>、>=、<、<=、<>
mysql> select dept_id,dept_name from dept6 where dept_id IN (select DISTINCT dept_id from
emp6 where age>=25); 查詢員工年齡大於等於25歲的部門
帶比較運算符的子查詢的工作原理圖
-
帶EXISTS關鍵字的子查詢
EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真
假值。Ture或False 當返回Ture時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行
查詢
46/125
mysql> select from emp6 WHERE EXISTS (SELECT dept_name from dept6 where dept_id=203);
mysql> select from emp6 WHERE EXISTS (SELECT dept_name from dept6 where
dept_id=205); dept6表中不存在dept_id=205,False
Empty set (0.00 sec)MySQL數據類型
MySQL數據類型一、MySQL常見的數據類型
在MySQL數據庫管理系統中,可以通過存儲引擎來決定表的類型。同時,MySQL數據庫管理系統也
提供了數據類型決定表存儲數據的類型。MySQL數據庫管理系統提供的數據類型:
數值類型:
整數類型 TINYINT SMALLINT MEDIUMINT INT BIGINT
浮點數類型(即小數) FLOAT DOUBLE
定點數類型 DEC
位類型 BIT
字符串類型:
CHAR系列 CHAR VARCHAR
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列 TINYBLOB BLOB MEDIUMBLOB LONGBLOB
BINARY系列 BINARY VARBINARY
枚舉類型: ENUM (用於實現單選功能)
47/125
集合類型: SET (用於實現多選功能)
時間和日期類型: DATE TIME DATETIME TIMESTAMP YEAR
數位數 7 6 5 4 3 2 1 0
二進制數 1 1 1 1 1 1 1 1
1位十進制數:如 0~9 這個範圍的所有數
2位十進制數:如 0~99 這個範圍的所有數
3位十進制數:如 0~999 這個範圍的所有數
1bit就是1位二進數:如 0 ~ 1 這個取值範圍的所有二進制數 0 、 1
2bit就是2位二進數:如 00 ~ 11 這個取值範圍的所有二進制數 00 、01、10、11
3bit就是3位二進數:如 000 ~ 111 這個取值範圍的所有二進制數 000、001、010、011、100、101、
110、111
8bit就是8位二進制數:如 0000 0000 ~ 1111 11111 這個取值範圍的所有二進制數
1Byte=8bit=28
2Byte=28bit=16bit=216
3Bbye=38bit=24bit=224
4Bbye=48bit=32bit=232
8Bbye=88bit=64bit=264
二、數據類型測試
===整數類型測試:tinyint,int
作用:用於存儲用戶的年齡、遊戲的Level、經驗值等。
警告:以下測試是在test庫中創建的表。use test;
LAB1:
mysql> create table test1(
-> tinyint_test tinyint,
-> int_test int
-> );
mysql> desc test1;
+--------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+-------+
| tinyint_test | tinyint(4) | YES | | NULL | |
| int_test | int(11) | YES | | NULL | |
+--------------+------------+------+-----+---------+-------+
48/125
2 rows in set (0.01 sec)
說明:int(11)中的11是數值的位數(也稱寬度),int(11)表示能存11位的整數(11位中包括+-號的符號位)。
如果要存的數的範圍是-99~+99要用int(3)。
mysql> insert into test1 values (111,111);
Query OK, 1 row affected (0.09 sec)
mysql> select from test1;
+--------------+----------+
| tinyint_test | int_test |
+--------------+----------+
| 111 | 111 |
+--------------+----------+
mysql> insert into test1(tinyint_test) values(128); 數值超出了-128~+127這個範圍
ERROR 1264 (22003): Out of range value for column 'tinyint_test' at row 1
mysql> insert into test1(int_test) values(99999999999); 數值超出了-2 147 483 648~+2 147
483 647這個範圍
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into test1(int_test) values(-99999999999);
Query OK, 1 row affected, 1 warning (0.00 sec)
//測試結果,默認有符號,超過存儲範圍出錯。
tinyint的取值範圍:-128~127 即-27~+27-1
int的取值範圍:-2 147 483 648~+2 147 483 647 即-231~+231-1
LAB2: 無符號(unsigned)×××測試
mysql> create table test2(
-> tinyint_test tinyint unsigned, //約束條件unsigned限定只能存正值(無符號)
-> int_test int unsigned
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> desc test2;
+--------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+-------+
| tinyint_test | tinyint(3) unsigned | YES | | NULL | |
| int_test | int(10) unsigned | YES | | NULL | |
+--------------+---------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into test2(tinyint_test) values(99999); 數值超出了0~255這個範圍
Query OK, 1 row affected, 1 warning (0.01 sec) 提示'1行被處理,1個警告'
mysql> insert into test2(tinyint_test) values(-99999); 數值超出了0~255這個範圍
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select from test2;
49/125
mysql> insert into test2(int_test) values(99999999999); 數值超出了0~4294967295這個範圍
Query OK, 1 row affected, 1 warning (0.01 sec) 提示'1行被處理,1個警告'
mysql> insert into test2(int_test) values(-99999999999); 數值超出了0~4294967295這個範圍
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> select from test2;
mysql> insert into test2 values(-20,-20);
ERROR 1264 (22003): Out of range value for column 'tinyint_test' at row 1
附加練習:測試無符號的bigint的取值範圍。
MariaDB [test]> create table t3(bigint_test bigint unsigned);
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> desc t3;
+-------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+---------+-------+
| bigint_test | bigint(20) unsigned | YES | | NULL | |
+-------------+---------------------+------+-----+---------+-------+
1 row in set (0.00 sec)
MariaDB [test]> insert into t3 values
(9999999999999999999999999999999999999999999999999999999999);
Query OK, 1 row affected, 1 warning (0.00 sec)
MariaDB [test]> insert into t3 values
(-9999999999999999999999999999999999999999999999999999999999);
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [test]> select from t3;
+----------------------+
| bigint_test |
+----------------------+
| 18 446 744 073 709 551 615 | 無符號bigint的最大值
| 0 | 無符號bigint的最小值
+----------------------+
2 rows in set (0.00 sec)
測試整數類型的顯示寬度
mysql> create table t1 (
-> id1 int,
-> id2 int(6)
-> );
50/125
mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1 | int(11) | YES | | NULL | |
| id2 | int(6) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
mysql> insert into t1 values(1,1);
Query OK, 1 row affected (0.00 sec)
mysql> select from t1;
+------+------+
| id1 | id2 |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
實現以0開頭的序號:zerofill
mysql> create table t2 (
-> id1 int zerofill,
-> id2 int(6) zerofill
-> );
Query OK, 0 rows affected (0.05 sec)
mysql> desc t2;
+-------+---------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------------+------+-----+---------+-------+
| id1 | int(10) unsigned zerofill | YES | | NULL | |
| id2 | int(6) unsigned zerofill | YES | | NULL | |
+-------+---------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into t2 values(2,2);
Query OK, 1 row affected (0.01 sec)
mysql> select from t2;
+------------+--------+
| id1 | id2 |
+------------+--------+
| 0000000002 | 000002 |
+------------+--------+
1 row in set (0.00 sec)
mysql> insert into t2 values(3,2222222); //插入大於寬度限制的值,仍然可以存儲
Query OK, 1 row affected (0.03 sec)
mysql> select from t2;
+------------+---------+
| id1 | id2 |
+------------+---------+
| 0000000002 | 000002 |
51/125
| 0000000003 | 2222222 |
+------------+---------+
2 rows in set (0.00 sec)
結論:×××的寬度僅爲顯示寬度,不是限制取值範圍。因此建議×××無
須指定寬度。
tinyint(1) 和 tinyint(3) 沒什麼區別,佔用字節都是一位,存儲範圍都是一樣的 init(number)後面不
加 zerofill就沒有任何區別 增加糊顯示的長度不一樣
tinyint(3) zerofill ,當插入的數據少於3位的時候,左邊自動補零,這纔是限制顯示長度
int(1) 和 tinyint(1) ,夠用的情況下,優先選擇tinyint(1),因爲佔字節少、節省空間。
tinyint一個字節 smallint 兩個字節 MEDIUMINT三個字節 int 4個字節 BIGINT 8個字節。
unsigned無符號 無正負
varchar(5) 這裏的5 限制的是儲存字符的個數,字符不分貴賤(不分 中文、英文、數字...)。
mysql的基本數據類型裏幾個int如下:
類型 大小 範圍(有符號) 範圍(無符號) 用
途
TINYINT 1字節 (-128~127) (0~255) 迷你
整數值
SMALLINT 2 字節 (-32 768~32 767) (0~65 535) 小整
數值
MEDIUMINT 3 字節 (-8 388 608~8 388 607) (0~16 777 215) 中等
整數值
INT或INTEGER 4 字節 (-2 147 483 648~2 147 483 647) (0~4 294 967 295) 整數
值
BIGINT 8 字節 (-9 233 372 036 854 775 808~9 223 372 036 854 775 807)
(0~18 446 744 073 709 551 615) 大整數值
===浮點數類型測試:
作用:用於存儲用戶的身高、體重、薪水等
浮點數和定點數都可以用類型名稱後加(M,D)的方式來表示,(M,D)表示一共顯示M位數字(整數位
+小數位),其中D位於小數點後面,M和D又稱爲精度和標度。
例如:要存的數值是99.999,用無符號(無+-號)的浮點型如何表示。
float(5,3) unsigned
create table flt(weight float(5,3) unsigned);
insert into flt values(98.888),(9999.99999);
select from flt;
單精度浮點數(float)與雙精度浮點數(double)的區別如下:
(1)在內存中佔有的字節數不同
• 單精度浮點數在機內佔4個字節
舉例:
最小值:0000 0000 0000 0000 .0000 0000 0000 0000
最大值:1111 1111 1111 1111 . 1111 1111 1111 1111
• 雙精度浮點數在機內佔8個字節
52/125
(2)有效數字位數不同
• 單精度浮點數有效數字8位
• 雙精度浮點數有效數字16位
(3)所能表示數的範圍不同
• 單精度浮點的表示範圍:-3.40E+38 ~ +3.40E+38(3.40E+38” 表示的數是3.4×10的38次方 +38強調
指次方的指數是正數)
• 雙精度浮點的表示範圍:-1.79E+308 ~ +1.79E+308
(4)在程序中處理速度不同
一般來說,CPU處理單精度浮點數的速度比處理雙精度浮點數快
浮點數:
float和double在不指定精度時,默認會按照實際的精度(由實際的硬件和操作系統決定)來顯示,
實例:
create table t2(salary float(5,2)); 即整數+小數共5位,小數是2位
desc t2;
insert into t2 values(100.5),(520.23),(5230.1289);
select * from t2;
說明:上面的5230.1289超出了我們定義的數據長度,產生了溢出,所以查出來的結果有問題。
如果只是小數位的長度超出了範圍,會自動四捨五入。
定點數:
decimal(十進制 小數)在不指定精度時,默認的整數位爲10,默認的小數位爲0
decimal 數據類型最多可存儲 38 個數字,所有數字都能夠放到小數點的右邊。decimal 數據類型存儲了一
個準確(精確)的數字表達法;不存儲值的近似值。定義 decimal 的列、變量和參數的兩種特性如下:· p
小數點左邊和右邊
數字之和,不包括小數點。如 123.45,則 p=5,s=2。指定精度或對象能夠控制的數字個數。· s指定可放
到小數點右邊的小數位數或數字個數。p 和 s 必須遵守以下規則:0 <= s <= p <= 38。
p (有效位數) 可儲存的最大十進位數總數,小數點左右兩側都包括在內。 s (小數位數) 小數點右側所能儲存的最大十進位數。 所以能取得最大數是38位都在小數點左邊即10的38次方-1,同理最小-10的38次方+1 定點數在MySQL內部以字符串形式存儲,比浮點數更精確,適合用來表示貨幣等精度高的數據。 mysql> create table test4(float_test float(5,2)); //一共5位,小數佔2位,整數佔3位 Query OK, 0 rows affected (0.00 sec) mysql> desc test4; +------------+------------+------+-----+---------+-------+ |
Field | Type | Null | Key | Default | Extra | +------------+------------+------+-----+---------+-------+ |
float_test | float(5,2) | YES | NULL | +------------+------------+------+-----+---------+-------+ 1 row in set (0.00 sec) mysql> insert into test4 values (10.2), (70.243), (70.246); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 53/125 mysql> select * from test4; +------------+ |
float_test | +------------+ |
10.20 | 70.24 | 70.25 | +------------+ 3 rows in set (0.00 sec) mysql> insert into test4 values (1111.2); ERROR 1264 (22003): Out of range value for column 'float_test' at row 1 定點數decimal測試: mysql> create table test5(decimal_test decimal(5,2)); mysql> insert into test5 values (70.245); Query OK, 1 row affected, 1 warning (0.05 sec) MariaDB [mydb]> select * from t3; +-------+ |
d | +-------+ |
70.25 | +-------+ 說明:插入數據時,當小數位超過我們所定義的位數時,會自動四捨五入。 mysql> show warnings; 查看報警信息 +-------+------+---------------------------------------------------+ |
Level | Code | Message | +-------+------+---------------------------------------------------+ |
Note | 1265 | Data truncated for column 'decimal_test' at row 1 | +-------+------+---------------------------------------------------+ 1 row in set (0.00 sec) ===位類型測試:BIT 十進制對應二進制 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0 128 64 32 16 8 4 2 1 十進制4 ----》2進製爲0100 16進制轉換成二進制的方法是,取四合一 0 1 2 3 4 5 6 7 8 9 A B C D E F 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 16進制4---》2進製爲0100 BIT(M)可以用來存放多位二進制數,M範圍從1~64,如果不寫默認爲1位 對於位字段可以使用函數讀取: bin()顯示爲二進制 54/125 hex()顯示爲十六進制(0-9A-F) mysql> create table test_bit (id bit(4)); 創建數據表 Query OK, 0 rows affected (0.35 sec) mysql> desc test_bit; 顯示test_bit表結構 +-------+--------+------+-----+---------+-------+ |
Field | Type | Null | Key | Default | Extra | +-------+--------+------+-----+---------+-------+ |
id | bit(4) | YES | NULL | +-------+--------+------+-----+---------+-------+ 1 row in set (0.01 sec) mysql> insert into test_bit values(4); mysql> select * from test_bit; 注意,當類型爲bit時,無法直接顯示數據的值。 +------+ |
id | +------+ |
---|
+------+
1 row in set (0.00 sec)
mysql> select bin(id),hex(id) from test_bit; 查詢數據時,臨時指定顯示數據類型的結果
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 100 | 4 |
+---------+---------+
1 row in set (0.00 sec)
說明:bin是指明輸出爲2進制,hex輸出成16進制。
插入超過指定寬度的值:(表中id字段的數據類型爲bit,寬度爲4bit,即4位2進制)
mysql> insert into test_bit values(8); 8的2進制是1000
Query OK, 1 row affected (0.05 sec)
mysql> insert into test_bit values(9); 9的2進制是1001
Query OK, 1 row affected (0.06 sec)
mysql> insert into test_bit values(16); 16的2進制是10000,超過了4bit,下面提示數據太長
ERROR 1406 (22001): Data too long for column 'id' at row 1
===時間和日期類型測試:year、date、time、datetime、timestamp
作用:用於存儲用戶的註冊時間,文章的發佈時間,文章的更新時間,員工的入職時間等
源貼:https://www.cnblogs.com/mxwz/p/7520309.html
TIMESTAMP和DATETIME的相同點:
1> 兩者都可用來表示YYYY-MM-DD HH:MM:SS[.fraction]類型的日期。
TIMESTAMP和DATETIME的不同點:
1> 兩者的存儲方式不一樣
對於TIMESTAMP,它把客戶端插入的時間從當前時區轉化爲UTC(世界標準時間)進行存儲。查詢時,將
55/125
其又轉化爲客戶端當前時區(即會計算時差)進行返回。
而對於DATETIME,不做任何改變,基本上是原樣輸入和輸出。
mysql> create table test_time(
-> d date,
-> t time,
-> dt datetime
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc test_time;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d | date | YES | | NULL | |
| t | time | YES | | NULL | |
| dt | datetime | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> insert into test_time values(now(),now(),now()); now()是顯示當前時間(日期、時間)
的函數。
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> select from test_time;
+------------+----------+---------------------+
| d | t | dt |
+------------+----------+---------------------+
| 2013-12-18 | 00:06:10 | 2013-12-18 00:06:10 |
+------------+----------+---------------------+
1 row in set (0.00 sec)
mysql> create table t(id timestamp);
Query OK, 0 rows affected (0.01 sec)
mysql> desc t;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-----------------------------+
| id | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+-----------+------+-----+-------------------+-----------------------------+
1 row in set (0.00 sec)
mysql> insert into t values(null);
Query OK, 1 row affected (0.00 sec)
mysql> select from t;
+---------------------+
| id |
+---------------------+
| 2013-12-18 00:08:41 |
+---------------------+
1 row in set (0.00 sec)
56/125
注意事項:
其它的時間,按要求插入
==插入年份時,儘量使用4位值
==插入兩位年份時,<=69,以20開頭,比如65, 結果2065
=70,以19開頭,比如82,結果1982
mysql> create table t3(born_year year);
Query OK, 0 rows affected (0.40 sec)
mysql> desc t3;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| born_year | year(4) | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into t3 values
-> (12),(80);
Query OK, 2 rows affected (0.06 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select from t3;
+-----------+
| born_year |
+-----------+
| 2012 |
| 1980 |
+-----------+
2 rows in set (0.00 sec)
===字符串類型測試:CHAR、VARCHAR
作用:用於存儲用戶的姓名、愛好、發佈的文章等文本(即文字)信息。
(必記) CHAR 列的長度固定爲創建表時聲明的長度(字數): 0 ~ 255
(必記) VARCHAR 列中的值爲可變長字符串,長度(字數): 0 ~ 65535
注(必記):在檢索(即查詢)的時候,CHAR列刪除了尾部的空格,而VARCHAR則保留這些空格
注(必記):常用中文字符用utf-8編碼佔用3個字節
字符所佔字節數(詳細):https://blog.csdn.net/u013749540/article/details/84103883
mysql> create table vc (
-> v varchar(4),
-> c char(4)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc vc;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| v | varchar(4) | YES | | NULL | |
57/125
| c | char(4) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into vc values('ab ','ab ');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select from vc;
+------+------+
| v | c |
+------+------+
| ab | ab |
+------+------+
1 row in set (0.00 sec)
mysql> select length(v),length(c) from vc; length是計算字符長度的函數
+-----------+-----------+
| length(v) | length(c) |
+-----------+-----------+
| 4 | 2 |
+-----------+-----------+
1 row in set (0.00 sec)
mysql> insert into vc values('abc ','abd ');
mysql> select length(v),length(c) from vc;
+-----------+-----------+
| length(v) | length(c) |
+-----------+-----------+
| 4 | 2 |
| 4 | 3 |
+-----------+-----------+
mysql> select concat(v,'='), concat(c,'=') from vc; //在後面加字符'=',看的更清楚
+---------------+---------------+
| concat(v,'=') | concat(c,'=') |
+---------------+---------------+
| ab = | ab= |
+---------------+---------------+
1 row in set (0.00 sec)
說明:concat是連接字符串的函數,即將多個單詞(即字符)連成一句話。
字符串類型測試:BINARY、VARBINARY
BINARY 和 VARBINARY類似於CHAR 和 VARCHAR,不同的是它們包含二進制字符而不包含非二進制字符
串,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,並且排序和比較基於列值字節的數
值值。
BINARY和VARBINARY允許的最大長度一樣,如同CHAR和VARCHAR,不同的是BINARY和VARBINARY的
長度是字節長度而不是字符長度
字符集:如日常生活中常見的標準字符有0~9、a-z、A~Z、漢字等。
字節字符串:1漢字=2字節
字符字符串:1漢字=1字符
mysql> create table binary_t (c binary(3));
Query OK, 0 rows affected (0.03 sec)
58/125
mysql> desc binary_t;
+-------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+---------+-------+
| c | binary(3) | YES | | NULL | |
+-------+-----------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into binary_t set c='aaa';
Query OK, 1 row affected (0.00 sec)
mysql> select ,hex(c) from binary_t; hex表示16進制
+------+--------+
| c | hex(c) |
+------+--------+
| aaa | 616161 |
+------+--------+
1 row in set (0.00 sec)
當列數據項大小一致時應使用 binary。
當列數據項大小不一致時應使用 varbinary。
===字符串類型===
ENUM類型即枚舉類型、集合類型SET測試
字段的值只能在給定範圍中選擇
常見的是單選按鈕和複選框
enum 單選 只能在給定的範圍內選一個值,如性別 sex 男male/女female
set 多選 在給定的範圍內可以選擇一個或一個以上的值(愛好1,愛好2,愛好3...)
表school.student3
姓名 name varchar(50)
性別 sex enum('m','f')
愛好 hobby set('music','book','game','disc')
mysql> use test;
mysql> create table student3(
-> name varchar(50),
-> sex enum('m','f'),
-> hobby set('music','book','game','disc')
-> );
Query OK, 0 rows affected (0.31 sec)
mysql> desc student3;
+-------+-----------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------------------------------+------+-----+---------+-------+
| name | varchar(50) | YES | | NULL | |
| sex | enum('m','f') | YES | | NULL | |
| hobby | set('music','book','game','disc') | YES | | NULL | |
+-------+-----------------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into student3 values
-> ('tom','m','book,game');
Query OK, 1 row affected (0.00 sec)
59/125
mysql> select from student3;
+------+------+-----------+
| name | sex | hobby |
+------+------+-----------+
| tom | boy | book,game |
+------+------+-----------+
1 row in set (0.00 sec)
mysql> insert into student3 values ('jack','m','film'); 不在枚舉範圍
ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 (縮短)
mysql> show create table student3\G
1. row
Table: student3
Create Table: CREATE TABLEstudent3
(name
varchar(50) default NULL,sex
enum('m','f') default NULL,hobby
set('music','book','game','disc') default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)字符所佔字節數
字符所佔字節數
原文: https://blog.csdn.net/u013749540/article/details/84103883
英文字母:
字節數 : 1;編碼:GB2312
字節數 : 1;編碼:GBK
字節數 : 1;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 1;編碼:UTF-8
字節數 : 4;編碼:UTF-16
60/125
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
中文漢字:
字節數 : 2;編碼:GB2312
字節數 : 2;編碼:GBK
字節數 : 2;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 3;編碼:UTF-8 由於1個漢字佔3個字節, 所以2個漢字佔23個字節,即6個字節 char
(6)
字節數 : 4;編碼:UTF-16
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
練習:執行如下命令,熟悉utf8字符編碼的漢字佔用3個字節的標準。
echo '×××' |cut -c 1-3 結果如下
中華人
echo '×××' |cut -b 1-9 結果如下
中華人
echo '×××' |cut -b 1-8 結果如下
中華▒ 由於utf8編碼的每個漢字佔3個字節,三個字要佔9個字節,而此處只提取了8個字節,所以最後
一個字出現亂碼了
練習:執行如下mysql的操作。
create table tk(name char(8))engine=innodb CHARACTER set UTF8;
insert into tk values('劉濤'),('劉濤老公');
select from tk;
Mariadbz主從複製
AB主從複製:
簡稱AB複製,在A主機上做create、update、insert、drop、delete等數據庫、表、記錄的增、刪、
改操作,B主機上會自動做數據庫、表、記錄的同步更新。
AB複製的工作原理(即工作過程):
- 在主庫上把數據更改記錄到二進制日誌(Binary Log)中。
- 備庫將主庫上的日誌複製到自己的中繼日誌(Relay Log)中。
61/125- 備庫讀取中繼日誌中的事件,將其重放到備庫數據庫之上。
AB複製的一主一從模式工作過程:
A主機: create database db1 ----> 會將此命令自動寫入本機的二進制日誌文件中
B主機: I/O線程 監測並讀A主機上的二進制日誌文件新增的內容,且將新內容寫入到B主機自己的中繼
日誌文件中
SQL線程 讀取B主機上中繼日誌文件中心的SQL語句,並且自動執行這些SQL語句。最終在B主
機上創建了db1這個庫。
網絡拓撲:(1主1從)
mysql主服務器(master主人):192.168.11.11
mysql從服務器(slave隨從、奴隸):192.168.11.12
項目準備:(在master、slave主機上分別做如下操作)
0.[選做]。安裝mariadb-server服務器端軟件、mariadb客戶端軟件,啓動mariadb服務,查mariadb服務端
口號3306。
yum install -y mariadb-server mariadb
systemctl restart mariadb
lsof -i :3306 或 netstat -atunlp | grep :3306
1.停止master、slave主機上的mariadb服務,並且清空/var/lib/mysql的所有數據。
systemctl stop mariadb
rm -rfv /var/lib/mysql/
62/125
2.重啓master、slave主機上的mariadb服務。並且查庫、test庫中是否有表(無表就OK)。
systemctl restart mariadb
mysql -uroot -e 'show databases;use test;show tables;'
AB複製的配置思路:
1.在A主機(master)上的/etc/my.cnf主配置文件中開啓binlog二進制日誌文件功能,並且給主機設置
server-id唯一標識編號。重啓mariadb服務。
2.在A主機上創建用於AB主從複製的用戶賬號,並查看master狀態中的binlog日誌文件的position位置數
值。
3.在B主機上的/etc/my.cnf主配置文件中設置server-id唯一標識編號。。重啓mariadb服務。
4.在B主機上用help change master查命令幫助,並用change master命令告訴B主機他的master主人的
正確信息。
5.在B主機上用start slave啓動mariadb的隨從服務,並用show slave status查看AB主從複製的數據同
步狀態,要確認兩個線程的yes狀態。
AB複製的配置實施:
1.在A主機(master)上的/etc/my.cnf主配置文件中開啓binlog二進制日誌文件功能,並且給主機設置
server-id唯一標識編號。重啓mariadb服務。
vim /etc/my.cnf 做如下修改
[mysqld] 找到此行,添加如下藍色字的3行功能選項
server-id=11 指定server-id爲11,通常用本機IP的最後一組數
log-bin=master-bin 添加此行,指定二進制日誌文件名爲master-bin
skip_name_resolv=1 跳過域名解析功能
重啓mariadb服務:
systemctl restart mariadb
2.在A主機上創建用於AB主從複製的用戶賬號,並查看master狀態中的binlog日誌文件的position位置數
值。
mysql -uroot -e "grant replication slave on .* to 'rep'@'192.168.11.%' identified by 'rep';"
mysql -uroot -e 'select user,host,password from mysql.user;show master status;'
3.在B主機上的/etc/my.cnf主配置文件中設置server-id唯一標識編號。重啓mariadb服務。
vim /etc/my.cnf 做如下修改
[mysqld] 找到此行,添加如下藍色字的3行功能選項
server-id=12 指定server-id爲12,通常用本機IP的最後一組數
#log-bin=slave-bin 添加此行,指定二進制日誌文件名爲slave-bin
skip_name_resolv=1 跳過域名解析功能
63/125
重啓mariadb服務:
systemctl restart mariadb
mysql -urep -prep -h192.168.11.11 -e 'status;' 測試rep用戶是否能遠程訪問master主機的數據
庫服務
4.在B主機上用help change master查命令幫助,並用change master命令告訴B主機他的master主人的
正確信息。
mysql
help change master to;
CHANGE MASTER TO
MASTER_HOST='192.168.11.11',
MASTER_USER='rep',
MASTER_PASSWORD='rep',
MASTER_PORT=3306,
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=542,
MASTER_CONNECT_RETRY=10; //重試連接的時間爲10秒
金老師的環境:
CHANGE MASTER TO
MASTER_HOST='10.31.165.5',
MASTER_USER='rep',
MASTER_PASSWORD='rep',
MASTER_PORT=3306,
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=542,
MASTER_CONNECT_RETRY=10;
5.在B主機上用start slave啓動mariadb的隨從服務,並用show slave status查看AB主從複製的數據同
步狀態,要確認兩個線程的yes狀態。
mysql -uroot -p
start slave;
show slave status\G 注: \G 是分組(group)顯示信息。
注:change master to設置的信息默認保存在/var/lib/mysql/master.info文件中,relay中繼日誌的設置信
64/125
息默認保存在/var/lib/mysql/relay-log.info文件中。
ls /var/lib/mysql/
cat /var/lib/mysql/master.info
cat /var/lib/mysql/relay-log.info
cat /var/lib/mysql/mysql.sock 此套接字設備文件無法查看,是正常現象
5.測試主從複製的數據同步。
首先,在A主機(192.168.11.11)上創建一個名稱爲db1的庫,並查庫。
mysql
create database db1;
show database;
然後,在B主機上查庫,看到了db1庫,說明AB主機的數據自動同步成功。
mysql -uroot -e 'show databases;'
MySQL讀寫分離
MySQL讀寫分離
MySQL的主從複製和MySQL的讀寫分離兩者有着緊密聯繫,首先部署主從複製,只有主從複製完了,才能
在此基礎上進行數據的讀寫分離。
簡單來說,讀寫分離就是隻在主服務器上寫,只在從服務器上讀,基本的原理是讓主數據庫處理事務性查
詢,而從數據庫處理select查詢,數據庫複製被用來把事務性查詢導致的改變更新同步到集羣中的從數據
庫。
MySQL 讀寫分離技術
- 基於程序代碼內部實現
在代碼中根據 select、insert 進行選擇分類; 這類方法也是目前生產環境應用最廣泛的。優點是性能較好,
因爲在程序代碼中實現,不需要增加額外的設備作爲硬件開支。缺點是需要開發人員來實現,運維人員無從
下手。 -
基於中間代理層實現
代理一般是位於客戶端和服務器之間, 代理服務器接到客戶端請求後通過判斷然後轉發到後端數據庫。目
前主要有兩個代表性程序:
mysql-proxy: mysql-proxy 爲 MySQL 開源項目,通過其自帶的 lua 腳本進行 SQL 判斷,雖然是 MySQL 官方
產品,但是 MySQL 官方並不建議將 mysql-proxy 用到生產環境。
amoeba: 由陳思儒開發,作者曾就職於阿里巴巴,現就職於盛大。該程序由 java 語言進行開發,目前只聽說
阿里巴巴將其用於生產環境。另外,此項目嚴重缺少維護和推廣。
65/125
mysql的讀寫分離集羣架構圖是啥樣的?
數據庫代理軟件(也稱爲中間件):
1.mysql官方推出的代理軟件:mysql-proxy
2.360團隊開發的Atlas(是mysql-proxy的二次開發優化版)
3.阿里公司的開發團隊開發的Amoeba(是變形蟲的意思):基於java的軟件,必須要安裝java的運行套件
jdk軟件包。
4.mycat:是Amoeba的二次開發優化版,基於java的軟件,必須要安裝java的運行套件jdk軟件包。mycat
可以實現分庫、分表功能,很多互聯網公司的mysql數據庫集羣都會用mycat作爲集羣管理的中間件。
5.mysql-router:mysql團隊在2016年左右發佈的一款新的數據庫代理服務器軟件。
mysql的官網:https://www.mysql.com/
mysql的社區版下載網址:https://dev.mysql.com/downloads/mysql/
• DOWNLOADS
• MySQL Community Server 社區版服務器
• MySQL NDB Cluster NDB網絡數據庫集羣(cluster)
• MySQL Shell mysql的命令行工具
• MySQL Router mysql的集羣代理軟件
• MySQL Workbench 類似於navicat的圖形界面客戶端軟件
練習:下載ali阿里的網絡yum源。
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum repolist
練習:下載mysql官網的網絡yum源,通過網絡yum源安裝mysql-workbench-community客戶端軟件。
cd
wget https://repo.mysql.com//mysql80-community-release-el7-2.noarch.rpm
rpm -ivh mysql80-community-release-el7-2.noarch.rpm
rpm -ql mysql80-community-release
yum search mysql
yum install -y mysql-workbench-community
mysql的相關軟件下載網址:https://www.mysql.com/downloads/
MySQL Enterprise Edition
(commercial)
MySQL Enterprise Edition includes the most comprehensive set of advanced features and
management tools for MySQL.
• MySQL Database
• MySQL Storage Engines (InnoDB, MyISAM, etc.)
• MySQL Connectors (JDBC, ODBC, .Net, etc.)
• MySQL Replication 複製功能
• MySQL Partitioning 分區功能,實現分庫分表分區等功能
• MySQL Utilities 工具箱
• MySQL Workbench 圖形界面(GUI)客戶端程序,是類似於Navicat的軟件
• MySQL Enterprise Backup 企業版備份軟件
• MySQL Enterprise Monitor 企業版監控
• MySQL Enterprise HA 企業版高可用集羣管理軟件
• MySQL Enterprise Security 企業版安全管理軟件
• MySQL Enterprise Transparent Data Encryption (TDE) 企業版透明數據加密
66/125
• MySQL Enterprise Firewall 企業版防火牆
• MySQL Enterprise Encryption 企業版機密軟件
• MySQL Enterprise Audit 企業版審計軟件
MySQL Proxy
MySQL Proxy:MySQL_Proxy Master
Slave1 Slave2
=========================================
IP 192.168.1.250 192.168.1.27 192.168.1.215
192.168.1.66
Server_ID 6
215 66
實現步驟:
MySQL主/備複製
安裝並配置MySQL Proxy
測試Proxy
一、MySQL主/備複製(略)
二、安裝並配置MySQL Proxy
注意:mysql-proxy代理服務器上是不用安裝mysql軟件的。 - 安裝並配置
[root@MySQL_Proxy ~]# service mysqld stop
[root@MySQL_Proxy ~]# chkconfig mysqld off
[root@MySQL_Proxy ~]# rpm -qa |grep lua
lua-5.1.4-4.1.el6.x86_64
67/125
[root@MySQL_Proxy ~]# tar xf mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz -C /usr/local/
[root@MySQL_Proxy ~]# cd /usr/local/
[root@MySQL_Proxy ~]# ln -s mysql-proxy-0.8.4-linux-el6-x86-64bit mysql-proxy
[root@MySQL_Proxy ~]# vim /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
min_idle_connections = 1,
max_idle_connections = 1, -
啓動mysql-proxy
[root@MySQL_Proxy ~]# lsof -i TCP:3306
[root@MySQL_Proxy ~]# /usr/local/mysql-proxy/bin/mysql-proxy --help-proxy
-P 指定proxy服務器工作的地址和端口,如-P 192.168.11.13:3306
-b 指定後端的寫服務器的地址和端口, 如 -b 192.168.11.11:3306
-r 指定讀read服務器的地址和端口,如-r 192.168.11.12:3306
-s 指定判斷的腳本,如-s /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
--daemon 以後臺進程的方式啓動調整最大打開的文件數
[root@MySQL_Proxy ~]# ulimit -a |grep 'open files'
[root@MySQL_Proxy ~]# ulimit -n 10240
[root@MySQL_Proxy ~]# ulimit -a |grep 'open files'
open files (-n) 10240
/usr/local/mysql-proxy/bin/mysql-proxy -P 10.31.165.7:3306 -b 10.31.165.5:3306 -r
10.31.165.6:3306 -s /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua --daemon
#運行mysql-proxy數據庫代理服務器軟件,並指定代理服務器IP和端口號,以及後端的讀、寫服務器的IP
和端口號。
[root@MySQL_Proxy ~]# ln -s /usr/local/mysql-proxy/bin/mysql-proxy /bin/mysql-proxy 創建軟
鏈接文件
[root@MySQL_Proxy ~]# /usr/local/mysql-proxy/bin/mysql-proxy -P 192.168.1.250:3306 -b
192.168.1.27:3306 -r 192.168.1.215:3306 -r 192.168.1.66:3306 -s /usr/local/mysql-proxy/share/doc/
mysql-proxy/rw-splitting.lua --daemon
2014-02-13 17:15:54: (critical) plugin proxy 0.8.4 started
[root@MySQL_Proxy ~]# netstat -tnlp |grep :3306
tcp 0 0 192.168.10.137:3306 0.0.0.0:* LISTEN 16620/mysql-proxy
[root@MySQL_Proxy ~]# vim /etc/rc.local 添加如下內容(此操作是爲了然系統啓動時自動運行mysqlproxy代理服務器軟件)
ulimit -n 10240
/usr/local/mysql-proxy/bin/mysql-proxy -P 192.168.1.250:3306 -b 192.168.1.27:3306 -r
192.168.1.215:3306 -r 192.168.1.66:3306 -s /usr/local/mysql-proxy/share/doc/mysql-proxy/rwsplitting.lua --daemon
到此結束,以下內容暫時不做。以下是採用mysql-proxy.cnf配置文件來指定代理服務器IP和端口號,以及後端的讀、寫服務器的IP和端口
68/125
號。然後在運行mysql-proxy服務時指定配置文件來加載相關功能。
cat /usr/local/mysql-proxy/mysql-proxy.cnf 此文件需要自己用vim創建,內容如下
[mysql-proxy]
log-file = /usr/local/mysql-proxy/mysqlproxy.log
proxy-address=192.168.1.253:3306 代理服務器的IP和端口號
proxy-backend-addresses=192.168.1.251:3306 後端可寫服務器的IP和端口號
proxy-read-only-backend-addresses=192.168.1.252:3306 後端只讀服務器的IP和端口號
proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua 讀寫分離的判斷腳本
運行測試:
首先:殺mysql-proxy的進程,pkill -9 mysql-proxy
然後,執行 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/mysqlproxy.cnf &
最後,查3306端口: lsof -i :3306 或 netstat -tnlp |grep :3306
++++++++++
[mysql-proxy]
daemon = true
pid-file = /var/run/mysql-proxy.pid
log-file = /var/log/mysql-proxy.log
log-level = debug
max-open-files = 1024
plugins = admin,proxy
user = mysql-proxy
#
#Proxy Configuration
proxy-address = 0.0.0.0:3306
proxy-backend-addresses = 192.168.211.120:3306 主
proxy-read-only-backend-addresses = 從 192.168.211.130:3306,192.168.211.130:3307
#proxy-lua-script =
proxy-lua-script = /usr/src/mysql-proxy-0.8.5/lib/rw-splitting.lua
#proxy-skip-profiling = true
#Admin Configuration
admin-address = 0.0.0.0:4041
admin-lua-script = /usr/local/lib/mysql-proxy/lua/admin.lua
admin-username = admin
admin-password = adminchmod 600 /etc/mysql-proxy.cnf
mysql -uadmin -padmin -h192.168.211.140 -P4041
mysql> select * from backends;三、測試
- 主庫(在192.168.11.11主庫上做)
mysql
mysql> grant ALL on . to bbs@'%' identified by 'tianyun';
mysql> flush privileges;
mysql> create database bbs;
mysql> create table bbs.t1 (name varchar(50));
69/125 - 備庫
mysql> stop slave; //暫時斷掉和主庫的連接 - 從客戶端測試
a. 讀 ====主 or 備
b. 寫 ====主 -
備庫
mysql> start slave;MYSQL代理服務器查詢的狀態結果
客戶機訪問MYSQL代理服務器後的變化:
Atlas
##採用Atlas實現MySQL讀寫分離
mysql的讀寫分離集羣架構圖:
client----->mysql-proxy代理(數據庫代理商)----->mysql-server服務器A(Read/Write可讀可寫)
----->mysql-server服務器B(ReadOnly可讀)
----->mysql-server服務器C(ReadOnly可讀)
----->mysql-server服務器D(ReadOnly可讀)
一、基礎介紹1、背景描述
目前我們的高可用DB的代理層採用的是360開源的Atlas,從上線以來,已穩定運行2個多月。無論是從性
能上,還是穩定性上,
相比其他開源組件(amoeba、cobar、MaxScale、MySQL-Proxy等),還是很出色的。
當初我們之所以選擇Atlas,主要看中它有以下優點:
(1)、基於mysql-proxy-0.8.2進行修改,代碼完全開源;
(2)、比較輕量級,部署配置也比較簡單;
(3)、支持DB讀寫分離;
(4)、支持從DB讀負載均衡,並自動剔除故障從DB;
70/125
(5)、支持平滑上下線DB;
(6)、具備較好的安全機制(IP過濾、賬號認證);
(7)、版本更新、問題跟進、交流圈子都比較活躍。
在測試期間以及線上問題排查過程中,得到了360 Atlas作者朱超的熱心解答,在此表示感謝。有關更多
Atlas的介紹,我就不一一例舉,可以參考以下鏈接:
https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md
3、系統環境
CentOS 7.6 x86_64
master主服務器(R/W可讀可寫):192.168.11.11
slave從服務器(ReadOnly只讀):192.168.11.12
atlas-proxy前端代理(讀寫分離的代理):192.168.11.13
##安裝mysql-server主服務端(192.168.10.25)
service firewalld stop
chkconfig firewalld off
setenforce 0
getenforce
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
yum install -y mariadb mariadb-server
service mariadb restart
chkconfig mariadb on
sed -i '1aserver_id=25' /etc/my.cnf
sed -i '2alog-bin=mysql-bin' /etc/my.cnf
service mariadb restart
mysql -uroot -e "grant all on . to admin@'%' identified by '01';flush privileges;"
mysql -uroot -e "grant replication slave on . to rep@'%' identified by '01';flush privileges;"
mysql -uroot -e "select user,host,password from mysql.user;"
mysql -uroot -e "reset master;show master status;"
##安裝mysql-server主服務端(192.168.10.26)
service firewalld stop
chkconfig firewalld off
setenforce 0
getenforce
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
yum install -y mysql mysql-server
service mysql restart
chkconfig mysql on
sed -i '1aserver_id=26' /etc/my.cnf
sed -i '2alog-bin=mysql-bin' /etc/my.cnf
service mysql restart
mysql -uroot -e "grant all on . to admin@'%' identified by '01';flush privileges;"
mysql -uroot -e "grant replication slave on . to rep@'%' identified by '01';flush privileges;"
mysql -uroot -e "select user,host,password from mysql.user;"
mysql -uroot -e "change master to
master_host='192.168.100.25',master_user='rep',master_password='01',master_port=3306,master_log_file='mysqlbin.000001',master_log_pos=245;"
sleep 30s
mysql -uroot -e "start slave;show slave status\G"
##安裝配置atlas讀寫分離(192.168.10.11)
service firewalld stop
71/125
chkconfig firewalld off
setenforce 0
getenforce
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
grep '^SELINUX=' /etc/selinux/config
安裝和配置atlas軟件
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
rpm -ql Atlas
echo "PATH=$PATH:/usr/local/mysql-proxy/bin/" > /etc/profile.d/atlas.sh
source /etc/profile.d/atlas.sh 加載環境配置文件
ll /usr/local/mysql-proxy/
##mysql-proxy文件功能說明:
bin目錄下放的都是可執行文件 - “encrypt”是用來生成MySQL加密密碼的,在配置的時候會用到
- “mysql-proxy”是MySQL自己的讀寫分離代理軟件
- “mysql-proxyd”是360弄出來的mysql-proxy原版的新版本,後面有個“d”,服務的啓動、重啓、停止。都
是用他來執行的
conf目錄下放的是配置文件 - “test.cnf”只有一個文件,用來配置代理的,可以使用vim來編輯
lib目錄下放的是一些包,以及Atlas的依賴
log目錄下放的是日誌,如報錯等錯誤信息的記錄
進入bin目錄,使用encrypt來對數據庫的密碼進行加密,我的MySQL數據的用戶名是admin,密碼是01,
我需要對密碼進行加密
cd /usr/local/mysql-proxy/bin/
./encrypt 01 生成加密密碼,並複製此密碼 注:此處的密碼01是mysql-server服務器上admin用戶賬號
的密碼,請在後端的mysql-server服務器上用grant all on . to admin@'%' identified by
'01' with grant option;來創建admin這個用戶,然後刷新權限表 flush privileges。在192.168.11.11和
192.168.11.12做
cd /usr/local/mysql-proxy/conf/ 切換到atlas的配置文件目錄中
cp -av test.cnf test.cnf.bak //備份test.cnf配置文件
vi test.conf 修改後的讀寫分離的完整配置文件內容(以下紅字是要改的內容)
[mysql-proxy]
admin-username = user
admin-password = pwd
proxy-backend-addresses = 192.168.100.25:3306 後端負責讀寫的服務器IP和端口號
proxy-read-only-backend-addresses = 192.168.100.26:3306@1,192.168.100.27:3306@2
pwds = admin:VFnEp9P4Vu4=, rep:VFnEp9P4Vu4=
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
proxy-address = 0.0.0.0:3306
admin-address = 0.0.0.0:2345
test.cnf讀寫分離配置文件功能說明:
1:[mysql-proxy] //讀寫分離代理配置
72/125
6:admin-username = user //管理接口的用戶名
9:admin-password = pwd //管理接口的密碼
12:proxy-backend-addresses = 192.168.100.25:3306 //主數據庫的IP地址和端口號(可讀可寫)
15:proxy-read-only-backend-addresses = 192.168.100.26:3306@1,192.168.100.27:3306@2 //讀服
務器的ip、端口和權重
18:pwds = admin:VFnEp9P4Vu4=, rep:VFnEp9P4Vu4= //後端MYSQL的用戶名和encrypt命令生成
的加密密碼
21:daemon = true //設置爲守護進程模式(後臺運行)
24:keepalive = true //允許keepalive
27:event-threads = 8 //工作線程數爲8
30:log-level = message //日誌等級爲message消息
33:log-path = /usr/local/mysql-proxy/log //日誌文件路徑
45:proxy-address = 0.0.0.0:3306 //Atlas監聽的管理接口IP和端口
48:admin-address = 0.0.0.0:2345 //Atlas監聽的管理接口IP和端口
啓動atlas服務:/usr/local/mysql-proxy/bin/mysql-proxyd test start
查atlas端口號:lsof -i :3306 和 lsof -i :2345
重啓atlas服務:/usr/local/mysql-proxy/bin/mysql-proxyd test restart
設置mysql-proxyd開機啓動:
echo "/usr/local/mysql-proxy/bin/mysql-proxyd test start" >> /etc/profile
source /etc/profile
tcpdump抓包: tcpdump -i eth0 port 3306
說明:抓取經過192.168.10.11代理主機的eth0網卡的3306端口的數據包,驗證讀寫分離效果。
訪問atlas代理服務器的測試:
yum install -y mariadb 安裝mariadb客戶端軟件
mysql -uadmin -p01 -h 192.168.10.11 -P3306
登錄到atlas管理端:mysql -uuser -ppwd -h 192.168.10.11 -P2345
mysql的讀寫分離集羣架構圖:
client----->Atlas代理(數據庫代理商)----->mysql-server服務器A(Read/Write可讀可寫)
----->mysql-server服務器B(ReadOnly可讀)
----->mysql-server服務器C(ReadOnly可讀)
----->mysql-server服務器D(ReadOnly可讀)
73/125
Mycat
Mysql事務
事務:這個詞的字面意思是什麼? 答:要做的一件事情和任務。mysql中採用事務功能可以實現有選擇
性胡對錶中數據操作做回滾、提交。
MYSQL默認處理任務的原則:執行增、刪、改操作會自動保存數據到庫、表、記錄中。
MYSQL事務的ACID原則(必看的經典段子):https://blog.csdn.net/qin_jian_bo/article/details/78324839
MYSQL的事務處理主要有兩種方法。
1、用begin,rollback,commit來實現
begin 開始一個事務,然後執行create、update、insert等操作
rollback 事務回滾(相當於word中的ctrl+Z撤消)
commit 事務確認(提交,相當於word中的ctrl+s保存)
2、直接用set來改變mysql的自動提交模式
MYSQL默認是自動提交的,也就是你提交一個QUERY,它就直接執行!我們可以通過
show variables \G 查看MYSQL環境變量
show variables like 'autocom%'; 查看autocommit環境變量的狀態
在etc/my.cnf進行設置 重啓服務mariadb set autocommit=0 禁止自動提交(臨時設置)
(即自動開啓事務功能,並不需要用begin開始事務,但是必須用commit提交操作,或用rollback撤消操
作)
set autocommit=1 開啓自動提交(必須用begin開始一個事務,用commit或rollback結束事務)
來實現事務的處理。
但注意當你用 set autocommit=0 的時候,你以後所有的SQL都將做爲事務處理,直到你用commit確認或
rollback結束,注意當你結束這個事務的同時也開啓了個新的事務!按第一種方法只將當前的作爲一個事
務!
個人推薦使用第一種方法!
MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理!其他的類型是不支持的!
注意:事務功能只對表的insert、delete、update這些操作有效。
-
修改存儲引擎
mysql> alter table 表名 engine=innodb; //engine=myisam|memore|....
實例:打開test數據庫文件,創建一張dbtest的表,查看錶中的數據,開啓事務功能,插入2條數據,提交
事務,查看錶中的數據。開啓新事務,插入1條記錄,回滾操作(撤消),查看錶中的數據。
mysql> use test;
Database changed
74/125
mysql> CREATE TABLEdbtest
(
-> id int(4)
-> ) TYPE=INNODB;
Query OK, 0 rows affected, 1 warning (0.05 sec)
mysql> select from dbtest
-> ;
Empty set (0.01 sec)
mysql> begin; 開始事務
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dbtest value(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into dbtest value(6);
Query OK, 1 row affected (0.00 sec)
mysql> commit; 提交事務
Query OK, 0 rows affected (0.00 sec)
mysql> select from dbtest;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)
mysql> begin; 開始事務
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dbtest values(7);
Query OK, 1 row affected (0.00 sec)
mysql> rollback; 回滾
Query OK, 0 rows affected (0.00 sec)
mysql> select from dbtest;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)
mysql>
MariaDB [(none)]> use test;
Database changed
MariaDB [test]> create table tbx(id int);
Query OK, 0 rows affected (0.04 sec)
75/125
MariaDB [test]> insert into tbx values(1),(2);
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> select from tbx;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.01 sec)
MariaDB [test]> begin; 開始一個事務
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> insert into tbx values(3),(4);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> select from tbx;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.01 sec)
MariaDB [test]> rollback; 回滾(相當於word中的ctrl+z撤消)
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select from tbx;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
MariaDB [test]> begin; 開始一個事務
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> insert into tbx values(3),(4);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> select from tbx;
+------+
| id |
+------+
| 1 |
| 2 |
76/125
| 3 |
| 4 |
+------+
4 rows in set (0.01 sec)
MariaDB [test]> commit; 提交(相當於word中的ctrl+s保存)
Query OK, 0 rows affected (0.01 sec)
MariaDB [test]> select from tbx;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.00 sec)
MariaDB [test]>
Mysql觸發器
MySQL觸發器Triggers觸發器簡介
創建觸發器
查看觸發器
刪除觸發器
觸發器案例
一、觸發器簡介
觸發器(trigger)是一個特殊的存儲過程,它的執行不是由程序調用,也不是手工啓動,而是由事件來觸
發,
比如當對A表進行操作事件( insert,delete, update)時就會激活它執行。觸發器經常用於加強數據的
完整性約束和業務規則等。
例如,當學生表中增加了一個學生的信息時,學生的總數就應該同時改變。因此可以針對學生表創建一個
觸發器,每次增加一個學生記錄時,就執行一次學生總數的計算操作,從而保證學生總數與記錄數的一致
性。
二、創建Trigger
語法:
CREATE TRIGGER 觸發器名稱 BEFORE|AFTER 觸發事件
ON 表名 FOR EACH ROW
BEGIN
77/125
觸發器程序體;
END
<觸發器名稱> 最多64個字符,它和MySQL中其他對象的命
名方式一樣
{ BEFORE | AFTER } 觸發器時機
{ INSERT | UPDATE | DELETE } 觸發的事件
ON <表名稱> 標識建立觸發器的表名,即在哪張表上建立
觸發器
FOR EACH ROW 觸發器的執行間隔:FOR EACH ROW子句通知觸發器
每隔一行 執行一次動作,而不是對整個表執行一次
<觸發器程序體> 要觸發的SQL語句:可用順序,判斷,循環等語句
實現一般程序需要的邏輯功能
example1 - 創建表
mysql> use test;
mysql> create table stu(
id int unsigned auto_increment primary key not null,
name varchar(50)
);
mysql> insert into stu(name) values('jack');
mysql> create table stu_total(total int);
mysql> insert into stu_total values(1); - 創建觸發器stu_insert_trigger
mysql> delimiter $$ 臨時定義命令的結束符爲$$號
mysql> create trigger stu_insert_trigger after insert
-> on stu for each row
-> BEGIN
-> update stu_total set total=total+1;
-> END$$
mysql> delimiter ; 臨時定義命令的結束符爲;號 - 創建觸發器stu_delete_trigger
mysql> delimiter $$ 臨時定義命令的結束符爲$$號
mysql> create trigger stu_delete_trigger after delete
-> on stu for each row
-> BEGIN
-> update stu_total set total=total-1;
-> END$$
mysql> delimiter ; 臨時定義命令的結束符爲;號
三、查看觸發器 - 通過SHOW TRIGGERS語句查看
SHOW TRIGGERS\G - 通過系統表triggers查看
USE information_schema
SELECT FROM triggers\G
SELECT FROM triggers WHERE TRIGGER_NAME='觸發器名稱'\G
78/125
3.測試觸發器
說明:插入兩條記錄,然後查stu表、stu_total表中的數據變化,驗證觸發器功能是否生效。
insert into stu values(2,'tom');
insert into stu values(3,'alice');
select from stu;
select from stu_total;
delete from stu where id=3;
select from stu;
select from stu_total;
案例小結:
以上案例是在stu表中插入一條記錄,stu_total表中的total字段的值就會自動加1,
在stu表中刪除一條記錄,stu_total表中的total字段的值就會自動減1。
此例的觸發器故障bug:如果stu_total表中的初始統計數據不正確,以上定義的這個觸發器會導致
stu_total表中統計的total值跟stu表中的總記錄數信息不對稱,所以這個觸發器是有問題的。正確的解法是
用count函數來統計stu表中的記錄數,不應該用加1或減1這種做法。
優化過的正確觸發器:
觸發器stu_insert_trigger_ok
drop triggers stu_insert_trigger;
delimiter $$
create trigger stu_insert_trigger after insert
on stu for each row
BEGIN
update stu_total set total=(select count() from stu);
END$$
delimiter ;
觸發器stu__delete_trigger_ok
drop trigger stu_insert_trigger;
delimiter $$
create trigger stu_delete_trigger after delete
on stu for each row
BEGIN
update stu_total set total=(select count() from stu);
END$$
delimiter ;
四、刪除觸發器 - 通過DROP TRIGGERS語句刪除
DROP TRIGGER 解發器名稱
show triggers\G 查看觸發器的狀態
五、觸發器案例
example2
創建表tab1
DROP TABLE IF EXISTS tab1;
CREATE TABLE tab1(
id int primary key auto_increment,
name varchar(50),
sex enum('m','f'),
79/125
age int
);
創建表tab2
DROP TABLE IF EXISTS tab2;
CREATE TABLE tab2(
id int primary key auto_increment,
name varchar(50),
salary double(10,2)
);
觸發器tab1_after_delete_trigger
作用:tab1表刪除記錄後,自動將tab2表中對應記錄刪除
mysql> \d $$ delimiter和\d表示定義界定符,即命令的結束符
mysql> create trigger tab1_after_delete_trigger
-> after delete on tab1
-> for each row
-> BEGIN
-> delete from tab2 where name=old.name;
-> END$$
觸發器tab1_after_update_trigger 作用:當tab1更新後,自動更新tab2
mysql> create trigger tab1_after_update_trigger
-> after update on tab1
-> for each row
-> BEGIN
-> update tab2 set name=new.name
-> where name=old.name;
-> END$$
Query OK, 0 rows affected (0.19 sec)
觸發器tab1_after_insert_trigger 作用:當tab1增加記錄後,自動增加到tab2
mysql> create trigger tab1_after_insert_trigger
-> after insert on tab1
-> for each row
-> BEGIN
-> insert into tab2(name,salary) values(new.name,5000);
-> END$$
Query OK, 0 rows affected (0.19 sec)
測試觸發器功能
說明::插入兩條記錄,然後查stu表、stu_total表中的數據變化,驗證觸發器功能是否生效。
insert into tab1(name,sex) values('tom','m');
insert into tab1(name,sex) values('lucy','f');
select from tab1;
select from tab2;
delete from tab1 where id=2;
select from tab1;
select from tab2;
80/125
案例3.example3
mysql> create table t1(
-> id int primary key auto_increment,
-> name varchar(50),
-> salary float(10,2)
-> );
Query OK, 0 rows affected (0.63 sec)
mysql> create table t2(
-> id int primary key auto_increment,
-> total_num int, //員工總人數
-> total_salary float(10,2) //員工薪水總和
-> );
Query OK, 0 rows affected (0.64 sec)
mysql> \d $$
mysql> create trigger t1_after_insert_trigger
-> after insert on t1
-> for each row
-> BEGIN
-> update t2 set total_num=total_num+1, total_salary=total_salary+new.salary;
-> END$$
Query OK, 0 rows affected (0.54 sec)
mysql> insert into t2 values('',0,0);
Query OK, 1 row affected (0.10 sec)
mysql> select * from t2;
+-----------+--------------+
| total_num | total_salary |
+-----------+--------------+
| 0 | 0.00 |
+-----------+--------------+
1 row in set (0.00 sec)
Mysql視圖
MySQL視圖VIEW
視圖簡介
創建視圖
查看視圖
修改視圖
通過視圖操作基表
刪除視圖
81/125
一、視圖簡介
通俗理解:就是將一張表中經常要查詢的列和記錄創建成一張虛擬的表。視圖中看到的數據會隨着原始表
格的更新而動態更新。
MySQL視圖是一個虛擬表,其內容由查詢定義。同真實的表一樣,視圖包含一系列帶有名稱的列和行
數據。但是,視圖並不在數據庫中以存儲的數據值集形式存在。行和列數據來自由定義視圖的查詢所
引用的表,並且在引用視圖時動態生成。對其中所引用的基礎表來說,MySQL視圖的作用類似於篩選。
定義視圖的篩選可以來自當前或其它數據庫的一個或多個表,或者其它視圖。通過視圖進行查詢沒有任
何限制,通過它們進行數據修改時的限制也很少。
視圖是存儲在數據庫中的SQL查詢語句,它主要出於兩種原因:
安全原因,視圖可以隱藏一些數據,如:一些敏感的信息
使複雜的查詢易於理解和使用。
三、查看視圖
- SHOW TABLES 查看視圖名
SHOW TABLES; - SHOW TABLE STATUS
示例:查看數據庫mysql中視圖及所有表詳細信息
SHOW TABLE STATUS FROM mysql \G
示例:查看數據庫mysql中視圖名view_user詳細信息
SHOW TABLE STATUS FROM mysql LIKE 'view_user' \G
命令格式:show table status from 庫名 where 條件
例如:show table status from shop where Comment='VIEW'\G
- SHOW CREATE VIEW
示例:查看視圖定義信息
SHOW CREATE VIEW 視圖名\G -
DESCRIBE
示例:查看視圖結構
DESC 視圖名;
四、修改視圖
方法一:刪除後新創建
DROP VIEW view_user ;
CREATE VIEW view_user
AS SELECT user,host FROM mysql.user;
SELECT FROM view_user;
方法二:ALTER修改視圖
語法:
ALTER VIEW 視圖名
AS SELECT語句;
示例:
ALTER VIEW view_user
AS SELECT user,password FROM mysql.user;
82/125
五、通過視圖操作基表
查詢數據SELECT
SELECT FROM view_user;
更新數據UPDATE
刪除數據DELETE
六、刪除視圖
語法:
DROP VIEW view_name [,view_name]…;
示例:
USE mysql;
DROP VIEW view_user ;
二、創建視圖
語法一:
CREATE [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE} ]
VIEW 視圖名 [(字段1,字段2…)]
AS SELECT語句
[WITH [CASCADED | LOCAL] CHECK OPTION ];
語法二:
CREATE VIEW 視圖名
AS SELECT語句;
示例1:
USE mysql
CREATE VIEW view_user AS SELECT user,host,password FROM mysql.user;
SELECT FROM view_user;
示例2:創建視圖案例(單表)
mysql> CREATE TABLE t (qty INT, price INT);
INSERT INTO t VALUES(3, 50);
CREATE VIEW v AS SELECT qty, price, qtyprice AS value FROM t; qtyprice兩者乘積
SELECT FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
| 3 | 50 | 150 |
+------+-------+-------+
示例3:創建視圖案例 (多表)
mysql> create database shop;
Query OK, 1 row affected (0.21 sec)
mysql> use shop
Database changed
mysql> create table product(
id int unsigned auto_increment primary key not null,
83/125
name varchar(60) not null,
price double not null
);
mysql> insert into product(name,price) values
('pear',4.3),
('orange',6.5),
('apple',5.0)
;
mysql> create table purchase(
id int unsigned auto_increment primary key not null,
name varchar(60) not null,
quantity int not null default 0,
gen_time datetime not null
);
mysql> insert into purchase(name,quantity,gen_time) values
('apple',7,now()),
('pear',10,now())
;
mysql> create view purchase_detail
as select
product.name as name, product.price as price,
purchase.quantity as quantity,
product.price purchase.quantity as total_value
from product,purchase
where product.name = purchase.name; 等值連接(即name相同的記錄進行組合)
mysql> select from purchase_detail;
+-------+-------+----------+-------------+
| name | price | quantity | total_value |
+-------+-------+----------+-------------+
| pear | 4.3 | 10 | 43 |
| apple | 5 | 7 | 35 |
+-------+-------+----------+-------------+
2 rows in set (0.04 sec)
mysql> insert into purchase(name,quantity,gen_time) values ('orange',20,now());
Query OK, 1 row affected (0.01 sec)
mysql> select from purchase_detail;
+--------+-------+----------+-------------+
| name | price | quantity | total_value |
+--------+-------+----------+-------------+
| apple | 5 | 7 | 35 |
| pear | 4.3 | 10 | 43 |
| orange | 6.5 | 20 | 130 |
+--------+-------+----------+-------------+
3 rows in set (0.00 sec)
84/125
存儲過程實例
存儲過程:定義數據存儲的過程。存儲過程中允許對庫、表、記錄做增、刪、改、查等操作。
存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL 語句集,存儲在數
據庫中,經過第一次編譯後調用不需要再次編譯,用戶通過指定存儲過程的名字並給出參數(如果該存儲
過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象。
存儲過程(procedure)和函數(function)的主要區別:
存儲過程是針對表中的數據記錄進行處理的SQL語句集合,就類似於shell腳本。
函數通常是針對記錄中的某個字段的值進行處理。
案例要求:創建一個名稱爲dba的庫文件,在dba庫中創建一張名稱爲tb1的表,表中有id、name這兩個字
段。創建一個名稱爲ad1的存儲過程,ad1存儲過程的功能是插入三條記錄到tb1表中。
mysql>create database dba;
mysql>use dba;
mysql>create table tb1(id int,name char(20));
mysql> \d $$ 等同於delimiter $$,設置命令的界定符(也稱結束符)
mysql> create procedure ad1() 創建ad1這個存儲過程(類似於shell腳本)
-> BEGIN
-> declare i int default 1;
-> while(i<=3)do
-> insert into dba.tb1 values(i,'ccc');
-> set i=i+1;
-> end while;
-> END$$
mysql> \d ;
mysql> use dba
Database changed
mysql> select from tb1;
mysql> call ad1(); 調用此存儲過程
mysql> select from tb1;
練習:定義一個名稱爲proc007的存儲過程,功能是實現用2條insert into語句在上文的tb1表中插入2條數
據記錄,並查tb1表中的數據。再定義一個名稱爲proc008的存儲過程,功能是實現用delete命令將
proc007存儲過程插入的2條數據記錄刪除,並查tb1表中的數據。分別測試這兩個存儲過程的調用。
\d $$
MariaDB [dba]> create procedure proc007()
-> begin
-> inset into tb1 values(4,'wl');
-> inset into tb1 values(5,'qqb');
-> end$$
\d ;
call proc007();
select from tb1;
MariaDB [dba]> \d $$
MariaDB [dba]> create procedure proc008()
-> begin
85/125
-> delete from tb1 where id=4;
-> delete from tb1 where id=5;
-> end$$
Query OK, 0 rows affected (0.00 sec)
MariaDB [dba]> \d ;
MariaDB [dba]> call proc008();select from tb1;
練習:定義一個名稱爲ak的存儲過程,功能是實現創建一個名稱爲dbak的庫,在dbak庫中創建tbak表,
tbak表中有id、name這兩個字段,在tbak表中插入2條記錄1、tom和2、alice的信息。測試ak這個存儲過
程的調用。
首先,創建存儲過程。
\d $$
create procedure ak()
BEGIN
create database dbak;
create table dbak.tbak(id int,name char(20));
desc dbak.tbak;
insert into dbak.tbak values(1,'tom'),(2,'alice');
select from dbak.tbak;
END$$
\d ;
然後,調用存儲過程:call ak();常用函數
查看當前的時間:select now();
查看版本號:select version();
Mysql索引
MySQL索引
問題:從中文字面上如何理解“索引”的意思?
答:索引,就是檢索引導的意思。是通過一定的算法將數據庫中的記錄按一定的規律進行分組,查信息時可
以縮小數據的搜索範圍,從而提高了查詢效率。
例如:現實生活中將火鍋菜單上的各種菜進行分類,有海鮮、青菜、肉類等,就是爲了讓食客快速找到某
個食品。 超市中將商品進行類別區域劃分,如化妝品、食品等。
創建索引
創建表時創建索引
CREATE在已存在的表上創建索引
86/125
ALTER TABLE在已存在的表上創建索引
查看並測試索引
刪除索引
一、索引簡介
索引在MySQL中也叫做“鍵”,是存儲引擎用於快速找到記錄的一種數據結構。索引對於良好的性能非常關
鍵,尤其是當表中的數據量越來越大時,索引對於性能的影響愈發重要。
索引優化應該是對查詢性能優化最有效的手段了。索引能夠輕易將查詢性能提高好幾個數量級。
索引相當於字典的音序表,如果要查某個字,如果不使用音序表,則需要從幾百頁中逐頁去查。
二、索引的分類
普通索引 index
唯一索引 unique index
全文索引 fulltext index
單列索引
多列索引
空間索引
三、準備實驗環境
-
準備表(可以不做此表)
create table t2(id int,name varchar(20));
desc t2;
四、創建索引
===創建表時
語法:
CREATE TABLE 表名 (
字段名1 數據類型 [完整性約束條件…],
字段名2 數據類型 [完整性約束條件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(長度)] [ASC |DESC])
);
創建INDEX普通索引示例:
CREATE TABLE dept10 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
INDEX(dept_name) 將表中的dept_name字段指定爲普通索引字段
);
87/125
創建UNIQUE唯一索引示例:
CREATE TABLE dept11 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
UNIQUE INDEX(dept_name)
);
創建全文索引示例:注意,只有MYISAM存儲引擎支持全文索引,innodb存儲引擎不支持全文索引。
CREATE TABLE dept12 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
log text,
FULLTEXT INDEX index_log (log)
)engine=myisam;
88/125
創建多列索引示例:
CREATE TABLE dept13 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
INDEX index_dept_name_comment (dept_name, comment)
);
===CREATE對已存在的表創建索引
語法:
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(長度)] [ASC |DESC]) ;
創建普通索引示例:此方法要指定索引名稱
CREATE INDEX index_dept_name ON dept6 (dept_name);
89/125
創建唯一索引示例:
CREATE UNIQUE INDEX index_dept_name ON dept6 (dept_name);
創建全文索引示例:
CREATE FULLTEXT INDEX index_dept_name ON dept6 (dept_name);
創建多列索引示例:
CREATE INDEX index_deptname comment ON dept6 (dept_name, comment);
===ALTER TABLE在已存在的表上創建索引
語法:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(長度)] [ASC |DESC]) ;
創建普通索引示例:
ALTER TABLE dept ADD INDEX index_dept_name (dept_name);
命令格式:alter table 表名 add index 索引名 (字段名);
創建唯一索引示例:
ALTER TABLE dept ADD UNIQUE INDEX index_dept_name (dept_name);
創建全文索引示例:
ALTER TABLE dept ADD FULLTEXT INDEX index_dept_name (dept_name);
創建多列索引示例:
ALTER TABLE dept ADD INDEX index_dept_name_comment (dept_name, comment);
四、管理索引
查看索引
SHOW CRETAE TABLE 表名\G
測試示例
EXPLAIN SELECT FROM dept WHERE dept_name='hr';
刪除索引
show create table employee6;
DROP INDEX 索引名 ON 表名;
實例:
create database company;
use company;
create table employee6(id int,emp_name varchar(20));
insert into employee6 values(1,'tom'),(2,'jack');
select from company.employee6;
EXPLAIN SELECT FROM employee6 WHERE emp_name='tom';
MariaDB [company]> explain select from employee6 where emp_name='tom';
+------+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | employee6 | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
90/125
+------+-------------+-----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
alter table employee6 add index emp_name(emp_name);
EXPLAIN SELECT FROM employee6 WHERE emp_name='tom';
五、Sphinx
Sphinx是一個基於SQL的全文檢索引擎,可以結合MySQL, PostgreSQL做全文搜索,它可以提供比數據庫
本身更專業的搜索功能,使得應用程序更容易實現專業化的全文檢索。Sphinx特別爲一些腳本語言設計搜
索API接口,
如PHP,Python,Perl,Ruby等,同時爲MySQL也設計了一個存儲引擎插件。Sphinx 單一索引最大可包含1億
條記錄,在1千萬條記錄情況下的查詢速度爲0.x秒(毫秒級)。Sphinx創建索引的速度爲:
創建100萬條記錄的索引只需 3~4分鐘,創建1000萬條記錄的索引可以在50分鐘內完成,而只包含最新
10萬條記錄的增量索引,重建一次只需幾十秒。
Coreseek中文分詞
Coreseek 是一個可供企業使用的、基於Sphinx(可獨立於Sphinx原始版本運行)的中文全文檢索引擎,按
照GPLv2協議發行。商業使用(例如, 嵌入到其他程序中)需要獲得商業授權。
Coreseek是一個支持中文的全文搜索引擎,意圖爲其他應用提供高速、低空間佔用、高相關度結果的中文
全文搜索能力。CoreSeek可以非常容易的與SQL數據庫和腳本語言集成。
Sphinx/Coreseek配置
91/125
索引測試實驗:
mysql> create table school.t2(id int,name varchar(30));
Query OK, 0 rows affected (1.33 sec)
mysql> desc school.t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> delimiter $$ 設置命令的界定符(也稱爲結束符)
mysql> create procedure autoinsert1() 創建autoinsert1這個存儲過程(類似於shell腳本)
-> BEGIN
-> declare i int default 1;
-> while(i<100000)do
-> insert into school.t2 values(i,'ccc');
-> set i=i+1;
-> end while;
-> END$$
mysql> use school
Database changed
mysql> delimiter ;
mysql> call autoinsert1(); 調用此存儲過程
mysql> explain select from school.t2 where id=20000;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 44848 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)
mysql> create index index_id on school.t2(id);
Query OK, 0 rows affected (0.91 sec)
Records: 0 Duplicates: 0 Warnings作用: 0
mysql> explain select from school.t2 where id=20000;
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | t2 | ref | index_id | index_id | 5 | const | 1 | Using where |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)
SHOW CREATE TABLE 表名\G
EXPLAIN: 命令的作用是查看查詢優化器如何決定執行查詢
92/125
花費時間比較:
創建索引前
mysql> select from school.t2 where id=20000;
+-------+------+
| id | name |
+-------+------+
| 20000 | ccc |
+-------+------+
1 row in set (0.03 sec)
創建索引後
mysql> create index index_id on school.t2(id);
Query OK, 0 rows affected (0.39 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from school.t2 where id=20000;
+-------+------+
| id | name |
+-------+------+
| 20000 | ccc |
+-------+------+
1 row in set (0.00 sec)Mysql日誌管理
MySQL日誌管理mysql命令歷史文件 系統當前用戶家目錄下的.mysql_history ,如/root/.mysql_history 文件
錯誤日誌: 記錄 MySQL 服務器啓動、關閉及運行錯誤等信息
二進制日誌: 又稱binlog日誌,以二進制文件的方式記錄數據庫中除 SELECT 以外的操作
查詢日誌: 記錄查詢的信息
慢查詢日誌: 記錄執行時間超過指定時間的操作(做mysql數據庫系統優化時會看此日誌)
中繼日誌: 備庫將主庫的二進制日誌複製到自己的中繼日誌中,從而在本地進行重放
通用日誌: 審計哪個賬號、在哪個時段、做了哪些事件
事務日誌 或稱redo日誌,記錄Innodb事務相關的如事務執行時間、檢查點等93/125
一、bin-log - 啓用
vim /etc/my.cnf
[mysqld]
log-bin[=dir/[filename]] //目錄權限必須mysql用戶可寫service mysqld restart
- 暫停(下面是在MYSQL登錄後做的臨時操作)
//僅當前會話
SET SQL_LOG_BIN=0; 暫停
SET SQL_LOG_BIN=1; 激活
//查看BIN環境變量
show variables like '%BIN%'; - 查看二進制日誌文件的方法
//在/var/lib/mysql目錄中執行
查看全部:cd /var/lib/mysql ; ls
mysqlbinlog mysql.000002
按時間:
mysqlbinlog mysql.000002 --start-datetime="2012-12-05 10:02:56"
mysqlbinlog mysql.000002 --stop-datetime="2012-12-05 11:02:54"
mysqlbinlog mysql.000002 --start-datetime="2012-12-05 10:02:56" --stop-datetime="2012-12-05
11:02:54"
按字節數:mysqlbinlog mysql.000002 --start-position=260
mysqlbinlog mysql.000002 --stop-position=260
mysqlbinlog mysql.000002 --start-position=260 --stop-position=930
- 截斷bin-log(產生新的bin-log文件)
a. 重啓mysql服務器
b. # mysql -uroot -p123 -e 'flush logs'
二、查詢日誌
啓用通用查詢日誌
vim /etc/my.cnf
[mysqld]
log[=dir[filename]]
service mysqld restart
三、慢查詢日誌
啓用慢查詢日誌
vim /etc/my.cnf
[mysqld]
log-slow-queries[=dir[filename]]
long_query_time=n
service mysqld restart
94/125
MySQL 5.6:
slow-query-log=1
slow-query-log-file=slow.log
long_query_time=3
Mysql權限體系
mysql 的權限體系介紹
MYSQL權限管理:是指數據庫的管理員對某個用戶賬號在某臺主機允許對某些庫中的某些表執行某些操
作。
grant授權命令:
grant all on 庫名.表名 to 用戶名@'主機名或IP' identified by '密碼' [ with 附加權
限選項 ]
revoke收回(註銷)權限命令:
revoke all on 庫名.表名 to 用戶名@'主機名或IP'
mysql 的權限體系大致分爲5個層級:
全局層級
全局權限適用於一個給定服務器中的所有數據庫。這些權限存儲在mysql.user表中。GRANT ALL ON .和
REVOKE ALL ON .只授予和撤銷全局權限。
95/125
數據庫層級(即給庫中的全部表授權)
數據庫權限適用於一個給定數據庫中的所有目標。這些權限存儲在mysql.db和mysql.host表中。GRANT
ALL ON db_name.和REVOKE ALL ON db_name.只授予和撤銷數據庫權限。
表層級(即給庫中的某張表授權)
表權限適用於一個給定表中的所有列。這些權限存儲在mysql.talbes_priv表中。GRANT ALL ON
db_name.tbl_name和REVOKE ALL ON db_name.tbl_name只授予和撤銷表權限。
列層級(即字段級)
列權限適用於一個給定表中的單一列。這些權限存儲在mysql.columns_priv表中。當使用REVOKE時,您必
須指定與被授權列相同的列。
子程序層級
CREATE ROUTINE, ALTER ROUTINE, EXECUTE和GRANT權限適用於已存儲的子程序。這些權限可以被
授予爲全局層級和數據庫層級。而且,除了CREATE ROUTINE外,這些權限可以被授予爲子程序層級,並
存儲在
mysql.procs_priv表中。
這些權限信息存儲在下面的系統表中:
mysql.user 用戶表
mysql.db 庫表
mysql.host 主機表
mysql.table_priv 表的權限表
mysql.column_priv 列的權限表
當用戶連接進來,mysqld會通過上面的這些表對用戶權限進行驗證!
注意:
當後續目標是一個表、一個已存儲的函數或一個已存儲的過程時,object_type子句應被指定爲TABLE、
FUNCTION或PROCEDURE。當從舊版本的MySQL升級時,要使用本子句,您必須升級您的授權表。請我們
可以用 CREATE
USER 或 GRANT 創建用戶,後者還同時分配相關權限。而 REVOKE 則用於刪除用戶權限,DROP USER 刪
除賬戶。
MySQL 賦予用戶權限命令語法爲:
grant 權限 on 數據庫對象 to 用戶;
grant 權限 on 數據庫對象 to 用戶 identified by "密碼";
grant 權限 on 數據庫對象 to 用戶@"ip" identified by "密碼"
GRANT 語法:
GRANT privileges (columns) ON what TO user IDENTIFIED BY "password" WITH GRANT
OPTION; (表示該用戶可以爲其他用戶分配權限)
privileges 列表:
- ALTER: 修改表和索引。
- CREATE: 創建數據庫和表。
- DELETE: 刪除表中已有的記錄。
- DROP: 拋棄(刪除)數據庫和表。
- INDEX: 創建或拋棄索引。
- INSERT: 向表中插入新行。
- REFERENCE:未使用。
- SELECT: 檢索表中的記錄。
96/125 - UPDATE: 修改現存表記錄。
- FILE: 讀或寫服務器上的文件。
- PROCESS: 查看服務器中執行的線程信息或殺死線程。
- RELOAD: 重載授權表或清空日誌、主機緩存或表緩存。
- SHUTDOWN: 關閉服務器。
- ALL: 所有權限,ALL PRIVILEGES同義詞。
-
grant 操作 MySQL 外鍵權限,官方文檔上說未使用!
grant references on test.* to yangql402@'10.250.7.225';
grant 操作 MySQL 臨時表權限。
grant create temporary tables on test.* to yangql402@'10.250.7.225';grant 操作 MySQL 索引權限。
grant index on test.* to yangql402@'10.250.7.225';grant 操作 MySQL 視圖、查看視圖源代碼 權限。
grant create view on test. to yangql402@'10.250.7.225';grant show view on test. to
yangql402@'10.250.7.225';grant 操作 MySQL 存儲過程、函數 權限。
grant create routine on test. to yangql402@'10.250.7.225';
grant alter routine on test. to yangql402@'10.250.7.225';
grant execute on test. to yangql402@'10.250.7.225';
三 grant 普通DBA管理某個MySQL數據庫(test)的權限。grant all privileges on test to dba@'localhost'其
中,關鍵字 “privileges” 可以省略。
四 grant 高級 DBA 管理 MySQL 中所有數據庫的權限。grant all on . to dba@'localhost'
97/125
五 MySQL grant 權限,分別可以作用在多個層次上。
a. grant 作用在整個 MySQL 服務器上:
grant select on . to dba@localhost; -- dba 可以查詢 MySQL 中所有數據庫中的表。
grant all on . to dba@localhost; -- dba 可以管理 MySQL 中的所有數據庫
b. grant 作用在單個數據庫上:
grant select on test. to dba@localhost; -- dba 可以查詢 test 中的表。
c. grant 作用在單個數據表上:
grant select, insert, update, delete on test.yql8 to dba@localhost;
d. grant 作用在表中的列上:
grant select(id, se, rank) on test.yql8 to dba@localhost;
e. grant 作用在存儲過程、函數上:
grant execute on procedure test.yql8 to 'dba'@'localhost';
grant execute on function test.yql8 to 'dba'@'localhost';
六 查看用戶權限查看當前用戶自己的權限:show grants;查看其他 MySQL 用戶權限:show grants for br/>dba@localhost;
七 撤銷用戶權限使用revoke 命令來註銷用戶的權限,具體語法:要撤銷所有權限,需使用以下語法。此語
法用於取消對於已命名的用戶的所有全局層級、數據庫層級、表層級和列層級的權限。REVOKE ALL
PRIVILEGES, GRANT OPTION FROM user [, user] ...也可以指定具體的權限比如:REVOKE SELECT
FROM yangql402@"10.250.7.249";注意:1 使用GRANT或REVOKE,操作者必須擁有GRANT OPTION權
限,並且您必須用於您正在授予或撤銷的權限。2 使用REVOKE撤銷全部權限,操作者必須擁有mysql數據庫
的全局CREATE USER權限或UPDATE權限。
八 刪除用戶:DROP USER user;其中user 賬戶包括 "username" 和 "host" 兩部分 即是username@host;
如果創建的時候爲 yangql@"10.250.7.225",則刪除的時候必須使用drop user yangql@"10.250.7.225",
否則會報錯!mysql> drop user yangql402;ERROR 1396 (HY000): Operation DROP USER failed for
'yangql402'@'10.250.7.225'mysql> drop user yangql402@'10.250.7.225';Query OK, 0 rows affected
(0.01 sec)
參考; MYSQL 官方文檔http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#accountmanagement-sql
98/125
權限 權限級別 權限說明
CREATE 數據庫、表或索引 創建數據庫、表或索引權限
DROP 數據庫或表 刪除數據庫或表權限
GRANT OPTION 數據庫、表或保存的程序 賦予權限選項
REFERENCES 數據庫或表
ALTER 表 更改表,比如添加字段、索引等
DELETE 表 刪除數據權限
INDEX 表 索引權限
INSERT 表 插入權限
SELECT 表 查詢權限
UPDATE 表 更新權限
CREATE VIEW 視圖 創建視圖權限
SHOW VIEW 視圖 查看視圖權限
ALTER ROUTINE 存儲過程 更改存儲過程權限
CREATE ROUTINE 存儲過程 創建存儲過程權限
EXECUTE 存儲過程 執行存儲過程權限
FILE 服務器主機上的文件訪問 文件訪問權限
CREATE TEMPORARY TABLES 服務器管理 創建臨時表權限
LOCK TABLES 服務器管理 鎖表權限
CREATE USER 服務器管理 創建用戶權限
PROCESS 服務器管理 查看進程權限
點擊這裏 點擊這裏 點擊這裏
99/125
RELOAD
服務器管理
執行flush-hosts, flush-logs, flush-privileges, flush-status, flushtables, flush-threads, refresh, reload等命令的權限
REPLICATION CLIENT 服務器管理 複製權限
REPLICATION SLAVE 服務器管理 複製權限
SHOW DATABASES 服務器管理 查看數據庫權限
SHUTDOWN 服務器管理 關閉數據庫權限
SUPER 服務器管理 執行kill線程權限
點擊這裏 點擊這裏 點擊這裏
MYSQL的權限如何分佈,就是針對表可以設置什麼權限,針對列可以設置什麼權限等等,這個可以從官
方文檔中的一個表來說明:
點擊這裏 點擊這裏
權限分佈 可能的設置的權限
表權限 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant',
'References', 'Index', 'Alter'
列權限 'Select', 'Insert', 'Update', 'References'
過程權限 'Execute', 'Alter Routine', 'Grant'
二、MySQL權限經驗原則:
權限控制主要是出於安全因素,因此需要遵循一下幾個經驗原則:
1、只授予能滿足需要的最小權限,防止用戶幹壞事。比如用戶只是需要查詢,那就只給select權限就可
以了,不要給用戶賦予update、insert或者delete權限。
2、創建用戶的時候限制用戶的登錄主機,一般是限制成指定IP或者內網IP段。
3、初始化數據庫的時候刪除沒有密碼的用戶。安裝完數據庫的時候會自動創建一些用戶,這些用戶默
認沒有密碼。
4、爲每個用戶設置滿足密碼複雜度的密碼。
5、定期清理不需要的用戶。回收權限或者刪除用戶。
三、MySQL權限實戰:
1、GRANT命令使用說明:
先來看一個例子,創建一個只允許從本地登錄的超級用戶jack,並允許將權限賦予別的用戶,密碼爲:
jack.
mysql> grant all privileges on . to jack@'localhost' identified by "jack" with grant option;
Query OK, 0 rows affected (0.01 sec) GRANT命令說明:
ALL PRIVILEGES 是表示所有權限,你也可以使用select、update等權限。
ON 用來指定權限針對哪些庫和表。
. 中前面的號用來指定數據庫名,後面的號用來指定表名。
TO 表示將權限賦予某個用戶。
100/125
jack@'localhost' 表示jack用戶,@後面接限制的主機,可以是IP、IP段、域名以及%,%表示任何地
方。注意:這裏%有的版本不包括本地,以前碰到過給某個用戶設置 了%允許任何地方登錄,但是在本地
登錄不了,這個和版本有關係,遇到這個問題再加一個localhost的用戶就可以了。
IDENTIFIED BY 指定用戶的登錄密碼。
WITH GRANT OPTION 這個選項表示該用戶可以將自己擁有的權限授權給別人。注意:經常有人在創
建操作用戶的時候不指定WITH GRANT OPTION選項導致後來該用戶不能使用GRANT命令創建用戶或者給
其它用戶授權。
備註:可以使用GRANT重複給用戶添加權限,權限疊加,比如你先給用戶添加一個select權限,然後又給
用戶添加一個insert權限,那麼該用戶就同時擁有了select和insert權限。
2、刷新權限
使用這個命令使權限生效,尤其是你對那些權限表user、db、host等做了update或者delete更新的時
候。以前遇到過使用grant後權限沒有更新的情況,只要對權限做了更改就使用FLUSH PRIVILEGES命令來
刷新權限。
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec) 3、查看權限
查看當前用戶的權限:
mysql> show grants;
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON . TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
查看某個用戶的權限:
mysql> show grants for 'jack'@'%';
+-----------------------------------------------------------------------------------------------------+
| Grants for jack@% |
+-----------------------------------------------------------------------------------------------------+
| GRANT USAGE ON . TO 'jack'@'%' IDENTIFIED BY PASSWORD
'9BCDC990E611B8D852EFAF1E3919AB6AC8C8A9F0' |
+-----------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec) 4、回收權限
mysql> revoke delete on . from 'jack'@'localhost';
Query OK, 0 rows affected (0.01 sec) 5、刪除用戶
mysql> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host | user | password |
+-----------+------+-------------------------------------------+
| localhost | root | |
| rhel5.4 | root | |
| 127.0.0.1 | root | |
| ::1 | root | |
| localhost | | |
| rhel5.4 | | |
| localhost | jack | 9BCDC990E611B8D852EFAF1E3919AB6AC8C8A9F0 |
+-----------+------+-------------------------------------------+
7 rows in set (0.00 sec)
mysql> drop user 'jack'@'localhost';
Query OK, 0 rows affected (0.01 sec) 6、對賬戶重命名
101/125
mysql> rename user 'jack'@'%' to 'jim'@'%';
Query OK, 0 rows affected (0.00 sec) 7、修改密碼
1、用set password命令
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');
Query OK, 0 rows affected (0.00 sec)
2、用mysqladmin
[root@rhel5 ~]# mysqladmin -uroot -p123456 password 1234abcd
備註:
格式:mysqladmin -u用戶名 -p舊密碼 password 新密碼
3、用update直接編輯user表
mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> update user set PASSWORD = PASSWORD('1234abcd') where user = 'root';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
4、在丟失root密碼的時候:
[root@rhel5 ~]# mysqld_safe --skip-grant-tables &
[1] 15953
[root@rhel5 ~]# 130911 09:35:33 mysqld_safe Logging to '/mysql/mysql5.5/data/rhel5.4.err'.
130911 09:35:33 mysqld_safe Starting mysqld daemon with databases from /mysql/mysql5.5/data
[root@rhel5 ~]# mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.22 Source distribution
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> \smysql Ver 14.14 Distrib 5.5.22, for Linux (i686) using EditLine wrapper
Connection id: 2
Current database:
Current user: root@
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.5.22 Source distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8
102/125
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /tmp/mysql.sock
Uptime: 36 sec
Threads: 1 Questions: 5 Slow queries: 0 Opens: 23 Flush tables: 1 Open tables: 18 Queries per
second avg: 0.138mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> update user set password = PASSWORD('123456') where user = 'root';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
Mysql函數
一、數學函數
ABS(x) 返回x的絕對值。例: select ABS(-15);
BIN(x) 返回x的二進制(OCT返回八進制,HEX返回十六進制).例select BIN(8);
CEILING(x) 返回大於x的最小整數值
EXP(x) 返回值e(自然對數的底)的x次方
FLOOR(x) 返回小於x的最大整數值
GREATEST(x1,x2,...,xn)返回集合中最大的值
LEAST(x1,x2,...,xn) 返回集合中最小的值
LN(x) 返回x的自然對數
LOG(x,y)返回x的以y爲底的對數
MOD(x,y) 返回x/y的模(餘數)
PI()返回pi的值(圓周率)。例: select PI();
RAND()返回0到1內的隨機值,可以通過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。
ROUND(x,y)返回參數x的四捨五入的有y位小數的值
SIGN(x) 返回代表數字x的符號的值
SQRT(x) 返回一個數的平方根
TRUNCATE(x,y) 返回數字x截短爲y位小數的結果
2的冪: 7 6 5 4 3 2 1 0
十進制:128 64 32 16 8 4 2 1
二、聚合函數(常用於GROUP BY從句的SELECT查詢中)
AVG(col)返回指定列的平均值
COUNT(col)返回指定列中非NULL值的個數
MIN(col)返回指定列的最小值
MAX(col)返回指定列的最大值
103/125
SUM(col)返回指定列的所有值之和
GROUP_CONCAT(col) 返回由屬於一組的列值連接組合而成的結果
三、字符串函數
ASCII(char)返回字符的ASCII碼值
BIT_LENGTH(str)返回字符串的比特長度
CONCAT(s1,s2...,sn)將s1,s2...,sn連接成字符串
CONCAT_WS(sep,s1,s2...,sn)將s1,s2...,sn連接成字符串,並用sep字符間隔
INSERT(str,x,y,instr) 將字符串str從第x位置開始,y個字符長的子串替換爲字符串instr,返回結果
FIND_IN_SET(str,list)分析逗號分隔的list列表,如果發現str,返回str在list中的位置
LCASE(str)或LOWER(str) 返回將字符串str中所有字符改變爲小寫後的結果
LEFT(str,x)返回字符串str中最左邊的x個字符
LENGTH(s)返回字符串str中的字符數
LTRIM(str) 從字符串str中切掉開頭的空格
POSITION(substr,str) 返回子串substr在字符串str中第一次出現的位置
QUOTE(str) 用反斜槓轉義str中的單引號
REPEAT(str,srchstr,rplcstr)返回字符串str重複x次的結果
REVERSE(str) 返回顛倒字符串str的結果
RIGHT(str,x) 返回字符串str中最右邊的x個字符
RTRIM(str) 返回字符串str尾部的空格
STRCMP(s1,s2)比較字符串s1和s2
TRIM(str)去除字符串首部和尾部的所有空格
UCASE(str)或UPPER(str) 返回將字符串str中所有字符轉變爲大寫後的結果
四、日期和時間函數
CURDATE()或CURRENT_DATE() 返回當前的日期
CURTIME()或CURRENT_TIME() 返回當前的時間
DATE_ADD(date,INTERVAL int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行
格式化),如:SELECTDATE_ADD(CURRENT_DATE,INTERVAL 6 MONTH);
DATE_FORMAT(date,fmt) 依照指定的fmt格式格式化日期date值
DATE_SUB(date,INTERVAL int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行格
式化),如:SELECTDATE_SUB(CURRENT_DATE,INTERVAL 6 MONTH);
DAYOFWEEK(date) 返回date所代表的一星期中的第幾天(1~7)
DAYOFMONTH(date) 返回date是一個月的第幾天(1~31)
DAYOFYEAR(date) 返回date是一年的第幾天(1~366)
DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE);
FROM_UNIXTIME(ts,fmt) 根據指定的fmt格式,格式化UNIX時間戳ts
HOUR(time) 返回time的小時值(0~23)
MINUTE(time) 返回time的分鐘值(0~59)
MONTH(date) 返回date的月份值(1~12)
MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE);
NOW() 返回當前的日期和時間
QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE);
WEEK(date) 返回日期date爲一年中第幾周(0~53)
YEAR(date) 返回日期date的年份(1000~9999)
一些示例:
獲取當前系統時間:SELECT FROM_UNIXTIME(UNIX_TIMESTAMP());
SELECT EXTRACT(YEAR_MONTH FROM CURRENT_DATE);
SELECT EXTRACT(DAY_SECOND FROM CURRENT_DATE);
SELECT EXTRACT(HOUR_MINUTE FROM CURRENT_DATE);
104/125
返回兩個日期值之間的差值(月數):SELECT PERIOD_DIFF(200302,199802);
在Mysql中計算年齡:
SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthday)),'%Y')+0 AS age
FROM employee;
這樣,如果Brithday是未來的年月日的話,計算結果爲0。
下面的SQL語句計算員工的絕對年齡,即當Birthday是未來的日期時,將得到負值。
SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(birthday, '%Y') -(DATE_FORMAT(NOW(),
'00-%m-%d') <DATE_FORMAT(birthday, '00-%m-%d')) AS age from employee
五、加密函數
AES_ENCRYPT(str,key) 返回用密鑰key對字符串str利用高級加密標準算法加密後的結果,調用
AES_ENCRYPT的結果是一個二進制字符串,以BLOB類型存儲
AES_DECRYPT(str,key) 返回用密鑰key對字符串str利用高級加密標準算法解密後的結果
DECODE(str,key) 使用key作爲密鑰解密加密字符串str
ENCRYPT(str,salt) 使用UNIXcrypt()函數,用關鍵詞salt(一個可以惟一確定口令的字符串,就像鑰匙一樣
)加密字符串str
ENCODE(str,key) 使用key作爲密鑰加密字符串str,調用ENCODE()的結果是一個二進制字符串,它以
BLOB類型存儲
MD5() 計算字符串str的MD5校驗和
PASSWORD(str) 返回字符串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不
同的算法。
SHA() 計算字符串str的安全散列算法(SHA)校驗和
示例:
SELECT ENCRYPT('root','salt');
SELECT ENCODE('xufeng','key');
SELECT DECODE(ENCODE('xufeng','key'),'key');#加解密放在一起
SELECT AES_ENCRYPT('root','key');
SELECT AES_DECRYPT(AES_ENCRYPT('root','key'),'key');
SELECT MD5('123456');
SELECT SHA('123456');
六、控制流函數
MySQL有4個函數是用來進行條件操作的,這些函數可以實現SQL的條件邏輯,允許開發者將一些應用程序
業務邏輯轉換到數據庫後臺。
MySQL控制流函數:
CASE WHEN[test1] THEN [result1]...ELSE [default] END如果testN是真,則返回resultN,否則返回
default
CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 如果test和valN相等,則返回resultN,否
則返回default
IF(test,t,f) 如果test是真,返回t;否則返回f
IFNULL(arg1,arg2) 如果arg1不是空,返回arg1,否則返回arg2
NULLIF(arg1,arg2) 如果arg1=arg2返回NULL;否則返回arg1
這些函數的第一個是IFNULL(),它有兩個參數,並且對第一個參數進行判斷。如果第一個參數不是NULL,
函數就會向調用者返回第一個參數;如果是NULL,將返回第二個參數。
如:SELECT IFNULL(1,2), IFNULL(NULL,10),IFNULL(4*NULL,'false');
NULLIF()函數將會檢驗提供的兩個參數是否相等,如果相等,則返回NULL,如果不相等,就返回第一個參
數。
如:SELECT NULLIF(1,1),NULLIF('A','B'),NULLIF(2+3,4+1);
和許多腳本語言提供的IF()函數一樣,MySQL的IF()函數也可以建立一個簡單的條件測試,這個函數有三個
參數,第一個是要被判斷的表達式,如果表達式爲真,IF()將會返回第二個參數,如果爲假,IF()將會返回
第三個參數。
105/125
如:SELECTIF(1<10,2,3),IF(56>100,'true','false');
IF()函數在只有兩種可能結果時才適合使用。然而,在現實世界中,我們可能發現在條件測試中會需要多
個分支。在這種情況下,MySQL提供了CASE函數,它和PHP及Perl語言的switch-case條件例程一樣。
CASE函數的格式有些複雜,通常如下所示:
CASE [expression to be evaluated]
WHEN [val 1] THEN [result 1]
WHEN [val 2] THEN [result 2]
WHEN [val 3] THEN [result 3]
......
WHEN [val n] THEN [result n]
ELSE [default result]
END
這裏,第一個參數是要被判斷的值或表達式,接下來的是一系列的WHEN-THEN塊,每一塊的第一個參數
指定要比較的值,如果爲真,就返回結果。所有的WHEN-THEN塊將以ELSE塊結束,當END結束了所有外
部的CASE塊時,如果前面的每一個塊都不匹配就會返回ELSE塊指定的默認結果。如果沒有指定ELSE塊,
而且所有的WHEN-THEN比較都不是真,MySQL將會返回NULL。
CASE函數還有另外一種句法,有時使用起來非常方便,如下:
CASE
WHEN [conditional test 1] THEN [result 1]
WHEN [conditional test 2] THEN [result 2]
ELSE [default result]
END
這種條件下,返回的結果取決於相應的條件測試是否爲真。
示例:
mysql>SELECT CASE 'green'
WHEN 'red' THEN 'stop'
WHEN 'green' THEN 'go' END;
SELECT CASE 9 WHEN 1 THEN 'a' WHEN 2 THEN 'b' ELSE 'N/A' END;
SELECT CASE WHEN (2+2)=4 THEN 'OK' WHEN(2+2)<>4 THEN 'not OK' END ASSTATUS;
SELECT Name,IF((IsActive = 1),'已激活','未激活') AS RESULT FROMUserLoginInfo;
SELECT fname,lname,(math+sci+lit) AS total,
CASE WHEN (math+sci+lit) < 50 THEN 'D'
WHEN (math+sci+lit) BETWEEN 50 AND 150 THEN 'C'
WHEN (math+sci+lit) BETWEEN 151 AND 250 THEN 'B'
ELSE 'A' END
AS grade FROM marks;
SELECT IF(ENCRYPT('sue','ts')=upass,'allow','deny') AS LoginResultFROM users WHERE uname =
'sue';#一個登陸驗證
七、格式化函數
DATE_FORMAT(date,fmt) 依照字符串fmt格式化日期date值
FORMAT(x,y) 把x格式化爲以逗號隔開的數字序列,y是結果的小數位數
INET_ATON(ip) 返回IP地址的數字表示
INET_NTOA(num) 返回數字所代表的IP地址
TIME_FORMAT(time,fmt) 依照字符串fmt格式化時間time值
其中最簡單的是FORMAT()函數,它可以把大的數值格式化爲以逗號間隔的易讀的序列。
示例:
SELECT FORMAT(34234.34323432,3);
SELECT DATE_FORMAT(NOW(),'%W,%D %M %Y %r');
SELECT DATE_FORMAT(NOW(),'%Y-%m-%d');
SELECT DATE_FORMAT(19990330,'%Y-%m-%d');
SELECT DATE_FORMAT(NOW(),'%h:%i %p');
SELECT INET_ATON('10.122.89.47');
SELECT INET_NTOA(175790383);
106/125
八、類型轉化函數
爲了進行數據類型轉化,MySQL提供了CAST()函數,它可以把一個值轉化爲指定的數據類型。類型有:
BINARY,CHAR,DATE,TIME,DATETIME,SIGNED,UNSIGNED
示例:
SELECT CAST(NOW() AS SIGNED INTEGER),CURDATE()+0;
SELECT 'f'=BINARY 'F','f'=CAST('F' AS BINARY);
九、系統信息函數
DATABASE() 返回當前數據庫名
BENCHMARK(count,expr) 將表達式expr重複運行count次
CONNECTION_ID() 返回當前客戶的連接ID
FOUND_ROWS() 返回最後一個SELECT查詢進行檢索的總行數
USER()或SYSTEM_USER() 返回當前登陸用戶名
VERSION() 返回MySQL服務器的版本
示例:
SELECT DATABASE(),VERSION(),USER();
SELECTBENCHMARK(9999999,LOG(RAND()PI()));#該例中,MySQL計算LOG(RAND()PI())表達式
9999999次。
Mysql存儲引擎
存儲引擎
在mysql中配置有許多不同的存儲引擎,用戶可以靈活的選擇適用於服務器、數據庫和表格的存儲引擎,以
便獲得最大的性能和最大的靈活性。這也是 mysql不同於其他大型數據庫以及mysql爲何如此受歡迎的主要
因素。一些大型的數據庫僅採用了一種存儲引擎,以一種尺碼滿足所有需求也就意味着會犧 牲一些性能。
存儲引擎的作用:決定數據的存儲和讀取的處理方式。
107/125
在命令行中可以通過命令顯示其支持的存儲引擎:
(1)MyISAM: Mysql的默認數據庫,最爲常用。擁有較高的插入,查詢速度,但不支持事務
.frm: 存儲表結構
.myd: 存儲數據,MYData的縮寫
.myi: 存儲索引,MYIndex的縮寫
(2)InnoDB :事務型數據庫的首選引擎,支持ACID事務,支持行級鎖定
(3)BDB:源自Berkeley DB,事務型數據庫的另一種選擇,支持COMMIT和ROLLBACK等其他事務特性
(4)Memory :所有數據置於內存的存儲引擎,擁有極高的插入,更新和查詢效率。但是會佔用和數據量成
正比的內存空間。並且其內容會在Mysql重新啓動時丟失
(5)Merge:將一定數量的MyISAM表聯合而成一個整體,在超大規模數據存儲時很有用
(6)Archive :非常適合存儲大量的獨立的,作爲歷史記錄的數據。因爲它們不經常被讀取。Archive擁有高
效的插入速度,但其對查詢的支持相對較差
(7)Federated:將不同的Mysql服務器聯合起來,邏輯上組成一個完整的數據庫。非常適合分佈式應用
Cluster/NDB :高冗餘的存儲引擎,用多臺數據機器聯合提供服務以提高整體性能和安全性。適合數據量
大,安全和性能要求高的應用
(8)CSV:邏輯上由逗號分割數據的存儲引擎。它會在數據庫子目錄裏爲每個數據表創建一個.CSV文件。這
是一種普通文本文件,每個數據行佔用一個文本行。CSV存儲引擎不支持索引。
(9)BlackHole:黑洞引擎,寫入的任何數據都會消失,一般用於記錄binlog做複製的中繼
每種存儲引擎都有各自的優勢,不能籠統的說誰的性能更好,只有合適不合適。
(1)MyISAM存儲引擎:主要用於管理非事物表,它提供了高速的存儲與檢索,以及全文搜索能力。該存
儲引擎插入數據快,但是空間和內存的使用效率較低。如果表主要適用於插入新紀錄和讀出記錄,那麼選
擇MyISAM存儲引擎可以實現處理的高效率。
(2)InnoDB存儲引擎:它主要用於事務處理應用程序,支持外鍵,同時還支持奔潰修復能力和併發控
制。如果對事物的完整性要求比較高,要求實現併發通知,那麼選擇InnoDB存儲引擎比較有優勢。如果需
要頻繁的進行更新、刪除操作,也可以選擇該存儲引擎,因爲該存儲引擎可以實現事物的提交和回滾。
(3)Memory存儲引擎:Memory存儲引擎提供“內存中”表,該存儲引擎的所有數據都存儲在內存中,數據
的處理速度很快但是安全性不高。108/125
存儲引擎說白了就是如何存儲數據、如何爲存儲的數據建立索引和如何更新、查詢數據等技術的實現方
法。因爲在關係數據庫中數據
的存儲是以表的形式存儲的,所以存儲引擎也可以稱爲表類型(即存儲和操作此表的類型)
在Oracle 和SQL Server等數據庫中只有一種存儲引擎,所有數據存儲管理機制都是一樣的。而MySql數據
庫提供了多種存儲引擎。
用戶可以根據不同的需求爲數據表選擇不同的存儲引擎,用戶也可以根據自己的需要編寫自己的存儲引
擎。
存儲引擎
存儲引擎:不同的存儲引擎可以給數據庫帶來不同的功能和性能。存儲引擎是針對表的設置。
109/125
行鎖:A用戶操作表中的第3行數據時,B用戶就不能操作這行數據。
表鎖:A用戶操作表1時,B用戶就不能操作表1。
B TREE樹狀算法(瞭解):https://blog.csdn.net/chuixue24/article/details/80027689
選擇存儲引擎- 查看存儲引擎
SHOW ENGINES;
SHOW ENGINES\G 查看MYSQL支持的存儲引擎
SHOW VARIABLES LIKE 'storage_engine%'; 查看當前的存儲引擎
SHOW VARIABLES LIKE 'auto_inc%'; 查看自增長的設置狀態
show global variables like '%connet%' 查看connet環境變量設置
mysql> show variables\G 查看所有的環境變量
show variables當前的會話
show global variables\G全局 - 選擇存儲引擎
方法1.
mysql> create table innodb1(
-> id int
-> )engine=innodb;
mysql> show create table innodb1;
create table test100(id init)engine=innodb;
方法2.
/etc/my.cnf
[mysqld] 在此行下添加下面的一行內容
default-storage-engine=INNODB
MySQL常用的存儲引擎
MyISAM存儲引擎
110/125
由於該存儲引擎不支持事務、也不支持外鍵,所以訪問速度較快。因此當對事務完整性沒有要求並以訪問
爲主的應用適合使用該存儲引擎。
InnoDB存儲引擎(MYSQL默認用此存儲引擎)
由於該存儲引擎在事務上具有優勢,即支持具有提交、回滾及崩潰恢復能力等事務特性,所以比MyISAM存
儲引擎佔用更多的磁盤空間。
因此當需要頻繁的更新、刪除操作,同時還對事務的完整性要求較高,需要實現併發控制,建議選擇。
MEMORY
MEMORY存儲引擎存儲數據的位置是內存,因此訪問速度最快,但是安全上沒有保障。適合於需要快速的
訪問或臨時表。
BLACKHOLE
黑洞存儲引擎,可以應用於主備複製中的分發主庫。
使用BLACKHOLE存儲引擎的表不存儲任何數據,但如果mysql啓用了二進制日誌,SQL語句被寫入日誌
(並被複制到從服務器)。這樣使用BLACKHOLE存儲引擎的mysqld可以作爲主從複製中的中繼重複器或在
其上面添加過濾器機制。
練習: - 建立四張表,存儲引擎分別爲MyISAM、InnoDB、MEMORY、BLACKHOLE。
- 通過show create table 表名查看錶的創建過程
- 插入數據(插入前要查看錶的結構)
create database save;
use save;
show engines;
create table isam1(id int,name varchar(20))engine=myisam;
create table inno1(id int,name varchar(20))engine=innodb;
create table mem1(id int,name varchar(20))engine=memory;
create table blk1(id int,name varchar(20))engine=blackhole;
show create table isam1;
show create table inno1;
show create table mem1;
show create table blk1;
desc isam1;
insert into isam1(id,name)values(1,'jim'),(2,'tom');
......
警告:當創建表時指定的存儲引擎不存在,系統會使用默認的存儲引擎。
警告:只有innodb存儲引擎支持外鍵功能。
外鍵:一個表的數據依賴於另一張表的主鍵列的數據,如果在主鍵列沒有出現的值,是不能夠出現在外鍵
字段的。
通俗理解:B表(子表)中的某列數據(外鍵)的值必須是A表(父表)中某列(主鍵)中的值。
外鍵解決的問題:1、將多張表通過外鍵聯繫起來。
2、減少數據的冗餘。
111/125
Mysql字符集
最近,在項目組使用的mysql數據庫中,插入數據出現亂碼,關於這個問題做了下總結,我們從最基本的地
方說起,到錯誤產生的深層次原因和解決辦法。
基本概念
• 字符(Character)是指人類語言中最小的表義符號。例如’A'、’B'等;
• 給定一系列字符,對每個字符賦予一個數值,用數值來代表對應的字符,這一數值就是字符的編碼
(Encoding)。例如,我們給字符’A'賦予數值0,給字符’B'賦予數值1,則0就是字符’A'的編碼;
• 給定一系列字符並賦予對應的編碼後,所有這些字符和編碼對組成的集合就是字符集(Character Set)。
例如,給定字符列表爲{’A',’B'}時,{’A'=>0, ‘B’=>1}就是一個字符集;
• 字符序(Collation)是指在同一字符集內字符之間的比較規則;
• 確定字符序後,才能在一個字符集上定義什麼是等價的字符,以及字符之間的大小關係;
• 每個字符序唯一對應一種字符集,但一個字符集可以對應多種字符序,其中有一個是默認字符序(Default
Collation);
• MySQL中的字符序名稱遵從命名慣例:以字符序對應的字符集名稱開頭;以_ci(表示大小寫不敏感)、_cs
(表示大小寫敏感)或_bin(表示按編碼值比較)結尾。例如:在字符序“utf8_general_ci”下,字符“a”和“A”是
等價的;
MySQL字符集設置
• 系統變量:
– character_set_server:默認的內部操作字符集
– character_set_client:客戶端來源數據使用的字符集
– character_set_connection:連接層字符集
– character_set_results:查詢結果字符集
– character_set_database:當前選中數據庫的默認字符集
– character_set_system:系統元數據(字段名等)字符集
– 還有以collation_開頭的同上面對應的變量,用來描述字符序。
• 用introducer指定文本字符串的字符集:
– 格式爲:[_charset] ’string’ [COLLATE collation]
– 例如:
SELECT _latin1 ’string’;
SELECT _utf8 ‘你好’ COLLATE utf8_general_ci;
– 由introducer修飾的文本字符串在請求過程中不經過多餘的轉碼,直接轉換爲內部字符集處理。
MySQL中的字符集轉換過程 - MySQL Server收到請求時將請求數據從character_set_client轉換爲character_set_connection;
- 進行內部操作前將請求數據從character_set_connection轉換爲內部操作字符集,其確定方法如下:
- 查看存儲引擎
- 使用每個數據字段的CHARACTER SET設定值;
- 若上述值不存在,則使用對應數據表的DEFAULT CHARACTER SET設定值(MySQL擴展,非SQL標
準); - 若上述值不存在,則使用對應數據庫的DEFAULT CHARACTER SET設定值;
- 若上述值不存在,則使用character_set_server設定值。
- 將操作結果從內部操作字符集轉換爲character_set_results。
112/125
我們現在回過頭來分析下我們產生的亂碼問題:
a 我們的字段沒有設置字符集,因此使用表的數據集
b 我們的表沒有指定字符集,默認使用數據庫存的字符集
c 我們的數據庫在創建的時候沒有指定字符集,因此使用character_set_server設定值
d 我們沒有特意去修改character_set_server的指定字符集,因此使用mysql默認
e mysql默認的字符集是latin1,因此,我們使用了latin1字符集,而我們character_set_connection
的字符集是UTF-8,插入中文亂碼也再所難免了。
常見問題解析
• FAQ-1 向默認字符集爲utf8的數據表插入utf8編碼的數據前沒有設置連接字符集,查詢時設置連接字符
集爲utf8
– 插入時根據MySQL服務器的默認設置,character_set_client、character_set_connection和
character_set_results均爲latin1;
– 插入操作的數據將經過latin1=>latin1=>utf8的字符集轉換過程,這一過程中每個插入的漢字都會從
原始的3個字節變成6個字節保存;
– 查詢時的結果將經過utf8=>utf8的字符集轉換過程,將保存的6個字節原封不動返回,產生亂碼。參
考下圖:
• 向默認字符集爲latin1的數據表插入utf8編碼的數據前設置了連接字符集爲utf8(我們遇到的錯誤就是屬
於這一種)
– 插入時根據連接字符集設置,character_set_client、character_set_connection和
character_set_results均爲utf8;
--插入數據將經過utf8=>utf8=>latin1的字符集轉換,若原始數據中含有\u0000~\u00ff範圍以外的
Unicode字符,會因爲無法在latin1字符集中表示而被轉換爲“?”(0×3F)符號,以後查詢時不管連接字符集
設置如何都無法恢復其內容了。轉 換過程如下圖:
檢測字符集問題的一些手段
• SHOW CHARACTER SET;
• SHOW COLLATION;
• SHOW VARIABLES LIKE ‘character%’;
• SHOW VARIABLES LIKE ‘collation%’;
• SQL函數HEX、LENGTH、CHAR_LENGTH
• SQL函數CHARSET、COLLATION
使用MySQL字符集時的建議
• 建立數據庫/表和進行數據庫操作時儘量顯式指出使用的字符集,而不是依賴於MySQL的默認設置,否
則MySQL升級時可能帶來很大困擾;
• 數據庫和連接字符集都使用latin1時,雖然大部分情況下都可以解決亂碼問題,但缺點是無法以字符爲
單位來進行SQL操作,一般情況下將數據庫和連接字符集都置爲utf8是較好的選擇;
• 使用mysql CAPI(mysql提供C語言操作的API)時,初始化數據庫句柄後馬上用mysql_options設定
MYSQL_SET_CHARSET_NAME屬性爲utf8,這樣就不用顯式地用SET NAMES語句指定連接字符集,且用
mysql_ping重連斷開的長連接時也會把連接字符集重置爲utf8;
• 對於mysql PHP API,一般頁面級的PHP程序總運行時間較短,在連接到數據庫以後顯式用SET
NAMES語句設置一次連接字符集即可;但當使用長連接時,請注意保持連接通暢並在斷開重連後用SET
NAMES語句顯式重置連接字符集。
其他注意事項
• my.cnf中的default_character_set設置隻影響mysql命令連接服務器時的連接字符集,不會對使用
libmysqlclient庫的應用程序產生任何作用!
• 對字段進行的SQL函數操作通常都是以內部操作字符集進行的,不受連接字符集設置的影響。
• SQL語句中的裸字符串會受到連接字符集或introducer設置的影響,對於比較之類的操作可能產生完全
113/125
不同的結果,需要小心!
總結
根 據上面的分析和建議,我們解決我們遇到問題應該使用什麼方法大家心裏應該比較清楚了。對,就
是在創建database的時候指定字符集,不要去通過修改默 認配置來達到目的,當然你也可以採用指定表的
字符集的形式,但很容易出現遺漏,特別是在很多人都參與設計的時候,更容易紕漏。
雖然不提倡通過修改mysql的默認字符集來解決,但對於如何去修改默認字符集,我這裏還是給出一些
方法,僅供大家參考。
MySQL默認字符集
MySQL對於字符集的指定可以細化到一個數據庫,一張表,一列.傳統的程序在創建數據庫和數據表時並沒
有使用那麼複雜的配置,它們用的是默認的配置.
(1)編譯MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;
(2)安裝MySQL 時,可以在配置文件 (my.ini) 中指定一個默認的的字符集,如果沒指定,這個值繼承自
編譯時指定的;
(3)啓動mysqld 時,可以在命令行參數中指定一個默認的的字符集,如果沒指定,這個值繼承自配置文
件中的配置,此時 character_set_server 被設定爲這個默認的字符集;
(4)安裝 MySQL選擇多語言支持,安裝程序會自動在配置文件中把default_character_set 設置爲
UTF-8,保證缺省情況下所有的數據庫所有表的所有列的都用 UTF-8 存儲。
查看默認字符集
(默認情況下,mysql的字符集是latin1(ISO_8859_1),如何查看在上面我們已經給出了相關命令
修改默認字符集
(1) 最簡單的修改方法,就是修改mysql的my.ini或/etc/my.cnf文件中的字符集鍵值,
如 default-character-set = utf8
character_set_server = utf8
修改完後,重啓mysql的服務
(2) 還有一種修改字符集的方法,就是使用mysql的命令
mysql> SET character_set_client = utf8 ;
mysql> SET character_set_connection = utf8 ;
mysql> SET character_set_database = utf8 ;
mysql> SET character_set_results = utf8 ;
mysql> SET character_set_server = utf8 ;
mysql> SET collation_connection = utf8 ;
mysql> SET collation_database = utf8 ;
mysql> SET collation_server = utf8 ;
設置了表的默認字符集爲utf8並且通過UTF-8編碼發送查詢,存入數據庫的仍然是亂碼。那connection
連接層上可能出了問題。解決方法是在發送查詢前執行一下下面這句: SET NAMES 'utf8';它相當於下面
的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
技術回顧
Q:mysql的root密碼忘了,如何處理?
A:首先,修改/etc/my.cnf主配置文件。
vim /etc/my.cnf
114/125
[mysqld]
skip-grant-table 跳過權限表驗證(添加此行)
然後,重啓mariadb服務:systemctl restart mariadb
然後,在mysql-server服務器本地免密碼登錄,做更新root密碼的操作。
mysql
update mysql.user set password=password("127") where user='root' and host='localhost';
flush privileges;
exit
然後,,修改/etc/my.cnf主配置文件。
vim /etc/my.cnf
[mysqld]
#skip-grant-table 註釋或刪除此行
然後,重啓mariadb服務:systemctl restart mariadb
然後,在mysql-server服務器本地使用root賬號和新密碼登錄。
mysql -uroot -p127 登錄成功,就說明密碼重設成功
Q:mysql的庫文件、表文件默認的保存路徑是?分別是以什麼類型的文件存儲在硬盤上?
A:保存路徑/var/lib/mysql
庫文件類型:以目錄的形式存儲在/var/lib/mysql目錄中
表文件:以普通文件的形式存儲字庫的目錄中
Q:SQL語言的三種類別的語句?
A:DDL 數據定義語言,如庫、表的創建、刪除、存儲等
DML 數據操縱語言,如?
DCL 數據控制語言,如?
Q:庫、表的增、刪、改、查命令?數據記錄的增、刪、改、查命令?
A:庫(database)的操作
查:show databases;
增(創建):create database 庫名 選項;
刪:drop database 庫名;
表(table)的操作
查:show tables;
增(創建):create table 表名(字段名1 數據類型,字段2 數據類型,...)engine=innodb 編碼設置;
查表結構:desc 表名;
刪:drop table 表名;
顯示修改表的命令幫助:help alter table;(插入或刪除一列,修改某列的屬性[即字段名和數據類型])
在表中最後新增指定的列字段:alter table 表名 add 字段名 數據類型;
在表中第一列或字段名A列之後新增指定的列字段:alter table 表名 add 字段名 數據類型 [first|
after 字段名A];
刪除表中的某列字段:alter table 表名 drop 字段名;
修改某列的屬性[即字段名和數據類型])
修改某列的數據類型:alter table 表名 modify 字段名 新數據類型 [first| after 字段名A];;
修改某列的字段名和數據類型:alter table 表名 change 舊字段名 新字段名 新數據類型 [first|
after 字段名A];;
115/125
記錄(record)的操作(插入一行):
查:select from 表名 [where 條件]
增(插入):insert into 表名[(字段1,字段2,...)] values(值1,值2,...),(值1,值2,...);
更新:update [庫名.]表名 set 字段名='新值' [where 條件];
刪:delete from [庫名.]表名 [where 條件];
mysql -uroot -p456
use test;
create table tba(id int,name char(15));
desc tba;
help alter table;
alter table tba add sex char(25);
desc tba;
alter table tba add xxx int first;
desc tba;
alter table tba change xxx num char(30) after sex;
desc tba;
alter table tba modify sex char(50) after num;
desc tba;
alter table tba drop num;
desc tba;
Q:如何在select查詢時對錶中的某列數據進行排序(升序、降序)?
A:用order by 字段名 [asc升序|desc降序]
練習:在test庫中創建tbx表,在tbx表中插入4條記錄,分別按常規、降序、升序查詢表中的數據。
use test;
create table tbx(id int not null auto_increment primary key,name char(10))engine=innodb
CHARACTER SET utf8;
#在tbx表中插入4行記錄。
insert into tbx(name) values
('tom'),
('jack'),
('lucy'),
('alice');
#常規、降序、升序查詢表中的數據。[order by 字段名 相當於excel中的"排序"功能]
select from tbx;
select from tbx order by id desc; 查詢tbx表中的全部記錄並且按id字段排降序
select from tbx order by name asc; 查詢tbx表中的全部記錄並且按name字段排升序
#按指定的條件查詢表中的數據記錄。[where 條件 相當於excel中的"篩選"功能]
select from tbx where id=3;
select from tbx where id>=3;
select from tbx where id<=3;
select from tbx where id<3;
select from tbx where name='jack';
select from tbx where id=1 or id=3;
select from tbx where id between 2 and 7; 查詢tbx表中id字段的值等於2~7之間的記錄
select from tbx where id>=2 and id<=7;
select from tbx where id!=2; 查詢tbx表中id字段的值不等於2的記錄
select from tbx where not id=2; 查詢tbx表中id字段的值不等於2的記錄
select from tby where id in (1,3,6,7); 查詢tbx表中id字段的值爲1、3、6、7的記錄
select from tby where not id in (1,3,6,7); 查詢tbx表中id字段的值不等於1、3、6、7的記錄
116/125
#在tbx表中插入5行記錄。
insert into tbx(name) values
('周濤'),
('周子皓'),
('周杰倫'),
('李振'),
('李小龍');
#按指定的條件查詢表中的數據記錄。[在where中用like做值的模糊匹配,_匹配任意單個字符,%匹配任意
一串字符]
select from tbx where name like '周%'; 查詢tby表中name字段的值 以周開頭 的所有記錄
select from tbx where name like '周__'; 查詢tby表中name字段的值 以周開頭且三個字 的所有
記錄
select * from tbx where name like '%龍'; 查詢tbx表中name字段的值 以龍字結尾的信息 的所有記
錄
#mysql庫和表的邏輯備份工具mysqldump
Q:什麼是邏輯備份?什麼是物理備份?
A:邏輯備份就是將數據中的表備份成create table、insert into等表和數據記錄的SQL語句。
物理備份就是就是將數據庫、表的源文件(/var/lib/mysql/庫名目錄)複製或tar打包壓縮一份到別的目錄
中。
- 將操作結果從內部操作字符集轉換爲character_set_results。
物理備份的模式:
冷備份:首先,停止數據庫的服務,然後用cp、tar命令對數據庫文件進行備份。
熱備份:直接在數據庫服務運行的狀態下做備份,需要用mysql的第三方備份和恢復工具進行操作。
單庫全表備份:mysqldump -uroot -p'密碼' 庫名 > 備份文件名.sql
例:mysqldump -uroot -p456 test > test_all.sql
more test_all.sql 會發現備份文件中主要是create table、insert into等SQL語句
單庫全表恢復:
首先,創建一個空庫:mysql -uroot -p456 -e 'create database 庫名;show databases;'
例:mysql -uroot -p456 -e 'create database test_all;show databases;'
然後,恢復所有表到庫中:mysql -uroot -p456 庫名 < 備份文件名.sql
例:mysql -uroot -p456 test_all < test_all.sql
mysql -uroot -p456 -e 'use test_all;show tables;'
單庫單表備份:mysqldump -uroot -p'密碼' 庫名 表名 > 備份文件名.sql
例:mysqldump -uroot -p456 test tby > tby.sql
more tby.sql 會發現備份文件中主要是create table、insert into等SQL語句
單庫單表恢復:
首先,創建一個空庫:mysql -uroot -p456 -e 'create database 庫名;show databases;'
例:mysql -uroot -p456 -e 'create database ku_tby;show databases;'
然後,恢復tby表到ku_tby庫中:mysql -uroot -p456 庫名 < 備份文件名.sql
例:mysql -uroot -p456 ku_tby < tby.sql
mysql -uroot -p456 -e 'use ku_tby;show tables;select * from tby;'
物理備份的模式:
冷備份:首先,停止數據庫的服務,然後用cp、tar命令對數據庫文件進行備份。
117/125
熱備份:直接在數據庫服務運行的狀態下做備份,需要用mysql的第三方備份和恢復工具進行操作。
練習:將192.168.11.11主機上的mysql的所有庫做冷備份,備份到/opt/mysql-2019-03-07目錄中。
grep 'datadir' /etc/my.cnf 查看mysql主配置文件中的數據庫文件存儲路徑
mkdir -pv /opt/data/mysql-$(date +%F)
systemctl stop mariadb && systemctl status mariadb
cp -arv /var/lib/mysql/ /opt/data/mysql-$(date +%F)
#刪除mysql的所有庫和表,重啓服務後,查庫、查表,發現test庫中沒有表。()
rm -rfv /var/lib/mysql/
systemctl restart mariadb
mysql -uroot -e 'show databases;use test;show tables;'
#冷恢復數據庫、表。
systemctl stop mariadb
\cp -afrv /opt/data/mysql-$(date +%F)/ /var/lib/mysql/
chown -Rv mysql:mysql /var/lib/mysql/
systemctl restart mariadb
mysql -uroot -p456 -e 'show databases;use test;show tables;'
技術回顧:
所講的技術內容:觸發器、視圖、存儲過程、索引、多表查詢(連接查詢、子查詢……)
Q.觸發器(trigger)的作用是什麼?
A.對A表做增insert、刪delete、改update操作,B表自動會執行某個SQL操作。
Q.視圖(view)的本質作用是什麼?
A.視圖其實就是將一條SQL的select查詢語句取個名字保存起來,當用select語句查詢這個視圖時,數據庫
底層就是執行視圖中所保存的select語句。可以用視圖來提高數據庫的安全性。
Q.存儲過程(procedure)的本質作用是什麼?
A.定義數據存儲的過程。存儲過程中允許對庫、表、記錄做增、刪、改、查等操作。
Q.索引(index)爲什麼可以提高數據查詢速度(效率高)?索引的類別有哪些?
A.索引底層的工作是會將表中的數據記錄按一定算法(規律)進行分組,用戶在查數據時會自動到所對應的
組中去查,這樣就縮小了查詢範圍,所以提高了效率。
索引的類別:
普通索引
唯一索引
全文索引
單列索引
多列索引
空間索引
Q.什麼是子查詢(sub select)?
A.將一個select查詢語句的結果作爲另一個select查詢語句的條件。
例:select from A表 where id in (select id from B表 where id=3)
Q.連接查詢(笛卡爾集[交叉連接]、左連接、右連接、等值連接)?
118/125
A.在下方寫出連接查詢相關的命令:
紅帽認證的考試全部是上機考試,當場考完後考試系統會自動通過腳本出成績結果。
RHCSA : RedHat Certified system administrator紅帽認證系統管理員。需要熟練掌握linux的系統安
裝、文件和目錄管理、用戶管理、權限、vim編輯器、磁盤存儲、進程、rpm軟件包、系統啓動故障修復。
RHCE :Red Hat Certified Engineer紅帽認證工程師。需要熟練掌握Linux的網卡網絡設置、網絡服務(文
件共享、apache、ssh、dhcp、tftp-server、dns、mariadb-server、postfix等)配置、shell腳本、firewalld
防火牆、tcpwrapper等。
RHCA :Red Hat Certified Architect 紅帽認證架構師。
Q:系統架構師?
A:系統的組織結構圖,即體現系統中各種功能軟件的結構圖。
Q:公司架構?
A:公司的組織結構圖,即公司的CEO、經理、員工等組成的結構。
作業
練習:編寫一個名稱爲/sh/mariadb_install.sh的腳本,實現在本機上用yum自動部署mariadb-server服務器
端,並給mariadb-server的root賬號設置本地和遠程登錄管理的密碼爲rootpass,並自動做本地測試的查
庫、查mysql庫中的user表的user、host、password字段的數據記錄信息。
vim /sh/mariadb_install.sh
#!/bin/bash
#Author:jim
#Date:2019-03-08
#company: http://jx.1000phone.net
SOFT='mariadb-server mariadb'
read -p 'input mariadb-server root user password:' PASS
rpm -q $SOFT && echo "$SOFT exsits." || yum install -y $SOFT > /dev/null
systemctl restart mariadb && systemctl enable mariadb || echo 'mariadb start error.'
mysql -e "grant all on . to root@'%' identified by \"$PASS\";flush privileges;"
mysql -e "update mysql.user set password=password(\"$PASS\") where user='root' and
host='localhost';flush privileges;"
mysql -uroot -p -e 'show databases;select user,host,password from mysql.user;'
119/125
練習:編寫mysql主從複製配置的腳本,實現在A主機上執行腳本能自動配置好mariadb的master主服務器
設置,在B主機上執行腳本能自動配置好mariadb的slave從服務器設置,然後在master上用create
database dbx建庫,在slave上用show database查庫來做手動做數據同步驗證。
首先,在master、slave主機上分別做ssh的雙機互信(即用ssh的公鑰和私鑰認證功能)
master主機上的操作:
1.生成祕鑰對(即公鑰和私鑰):echo | ssh-keygen -t rsa -P ""
2.上傳公鑰給slave主機:ssh-copy-id [email protected]
3.安裝nfs服務:
yum install -y nfs-utils rpcbind
systemctl restart nfs && systemctl enable nfs
chmod -v 777 /nfs
echo '/nfs (rw,no_root_squash)' > /etc/exports
exportfs -rav
showmount -e 127.0.0.1
4.在master上遠程給slave安裝nfs服務:
ssh [email protected] 'yum install -y nfs-utils rpcbind;systemctl restart nfs && systemctl
enable nfs'
ssh [email protected] 'mkdir -pv /gua_nfs;mount -t nfs 192.168.11.11:/nfs /gua_nfs'
5.在master主機上編寫/nfs/mariadb_install.sh腳本。
vim /nfs/mariadb_install.sh 腳本內容如下
#!/bin/bash
#Author:jim
#Date:2019-03-08
#company: http://jx.1000phone.net
SOFT='mariadb-server mariadb'
read -p 'input mariadb-server root user password:' PASS
rpm -q $SOFT && echo "$SOFT exsits." || yum install -y $SOFT > /dev/null
systemctl restart mariadb && systemctl enable mariadb || echo 'mariadb start error.'
mysql -e "grant all on . to root@'%' identified by \"$PASS\";flush privileges;"
mysql -e "update mysql.user set password=password(\"$PASS\") where user='root' and
host='localhost';flush privileges;"
mysql -uroot -p -e 'show databases;select user,host,password from mysql.user;'
6.在master主機上編寫/nfs/master.sh腳本。
vim /nfs/master.sh 腳本內容如下
#!/bin/bash
cat > /etc/my.cnf.d/master.cnf <<EOF
[mysqld]
server-id=11
log-bin=master-bin
skip_name_resolv=1
EOF
systemctl restart mariadb
mysql -uroot -p -e "grant replication slave on . to rep@'%' identified by 'rep';flush
privileges;reset master;show master status;"
7.在master主機上編寫/nfs/slave.sh腳本。
vim /nfs/slave.sh 腳本內容如下
#!/bin/bash
rpm -q mariadb-server mariadb && echo mariadb-server installed ||. /gua_nfs/mariadb_install.sh
120/125
cat > /etc/my.cnf.d/slave.cnf <<EOF
[mysqld]
server-id=12
log-bin=slave-bin
skip_name_resolv=1
EOF
systemctl restart mariadb
mysql -uroot -e "
CHANGE MASTER TO
MASTER_HOST='192.168.11.11',
MASTER_USER='rep',
MASTER_PASSWORD='rep',
MASTER_PORT=3306,
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=245,
MASTER_CONNECT_RETRY=10;"
mysql -uroot -e "start slave;show slave status\G"
8.在master上運行master.sh腳本。
chmod -v +x /nfs/.sh
. /nfs/master.sh
9.在master上對slave主機遠程執行/gua_nfs/slave.sh腳本。
ssh [email protected] '. /gua_nfs/slave.sh'
10.在master上執行如下建庫操作,遠程執行從庫的查庫操作。
mysql -uroot -p -e 'create database dbx;show databases;'
ssh [email protected] "mysql -uroot -p -e 'show databases;';"
練習:編寫一個名稱爲/sh/atlas.sh的腳本,實現全自動部署atlas代理服務器軟件。
Mysql 單實例部署
PHP+Mysql
LAMP環境準備:Linux+Apache+Mysql(mariadb)+P(PHP/Perl/Python)
yum install -y httpd mariadb-server mariadb php
systemctl restart httpd mariadb
systemctl enable httpd mariadb
案例:在MYSQL中創建一個名稱爲pdb的數據庫文件,在數據庫中創建一張名稱爲t1的表格。用PHP語言
打開此數據庫,並顯示錶中的記錄。表格內容如下圖。
#在服務器本地登錄到mysql-server服務
121/125
mysql
#庫的查詢、創建、打開
show databases;
create database pdb;
use pdb
#表的查詢、創建,在表中插入數據記錄。
show tables;
create table t1(id int,name char(20),tel int);
desc t1;
insert into t1 values
(1,'tom',1234567890),
(2,'jack',1358798),
(3,'alice',1594893);
select from t1;
122/125
#給mariadb-server的root用戶設置本地登錄密碼
mysql -e "grant all on .* to root@'localhost' identified by '01';flush privileges;"
mysql -uroot -p01 -e 'show databases;'
創建如下test.php測試頁面:
vi /var/www/html/test.php 網頁代碼如下
<?php phpinfo() ?>
訪問此測試頁面:elinks http://192.168.100.6/test.php 或 curl 192.168.100.6/test.php
用火狐瀏覽器訪問:firefox 192.168.100.6/test.php &
用index.php網頁查詢pdb.t1的結果如下圖所示:
vi /var/www/html/index.php 網頁代碼如下,以下藍色字應該根據數據庫的實際情況來修改。
<html>
<head>
<title>welcome to my info system! </title>
</head>