mysql基础知识(mysql新手教程)(使用方法简单教程)
本篇文章主要介紹MySQL基礎(chǔ)知識(shí),數(shù)據(jù)庫(kù)它是一個(gè)以某種有組織的方式存儲(chǔ)的數(shù)據(jù)集合,保存有組織的數(shù)據(jù)的容器(通常是一個(gè)文件或一組文件),感興趣的朋友可以移步風(fēng)君子博客mysql視頻教程頻道了解一下。Mysql 數(shù)據(jù)庫(kù)必須在Mysql服務(wù)下啟動(dòng)。
在windows 下 啟動(dòng)Mysql cd到mysql\bin 目錄下 在dos窗口下 啟動(dòng)\關(guān)閉mysql服務(wù)
//啟動(dòng)mysql服務(wù) mysqld --console //關(guān)閉mysql服務(wù) mysqladmin -uroot shutdown
登錄后復(fù)制
SQL分類
SQL 主要語(yǔ)句可以劃分為一下3類
-
DDL:數(shù)據(jù)定義語(yǔ)言,這些語(yǔ)句定義不同的數(shù)據(jù)段、數(shù)據(jù)庫(kù)、表、列、索引等數(shù)據(jù)庫(kù)對(duì)象。常用語(yǔ)句關(guān)鍵字主要包括create,drop,alter等
-
DML:數(shù)據(jù)操作語(yǔ)句,用于添加、刪除、更新和查詢數(shù)據(jù)庫(kù)記錄,并檢查數(shù)據(jù)完整性。常用語(yǔ)句關(guān)鍵字主要包括 insert,delete,update和select等。
-
DCL數(shù)據(jù)控制語(yǔ)句,用于控制不同數(shù)據(jù)段直接的許可和訪問(wèn)級(jí)別的語(yǔ)句。這些語(yǔ)句定義了數(shù)據(jù)庫(kù)、表、字段、用戶的訪問(wèn)權(quán)限和安全級(jí)別。主要 的語(yǔ)句包括關(guān)鍵字grant、revoke等
DDL語(yǔ)句
是對(duì)數(shù)據(jù)庫(kù)內(nèi)部的對(duì)象進(jìn)行創(chuàng)建 、刪除、修改等操作語(yǔ)言,它和DML語(yǔ)句最大的區(qū)別是DML只是對(duì)表內(nèi)部數(shù)據(jù)操作,而不涉及表的定義、結(jié)構(gòu)的修改,更不會(huì)涉及其他對(duì)象。DDL更多地由數(shù)據(jù)庫(kù)管理員(DBA)使用。
連接mysql服務(wù)器 mysql -uroot -p 創(chuàng)建數(shù)據(jù)庫(kù)test1 create database test1; 顯示有哪些數(shù)據(jù)庫(kù) show databases; //mysql 自動(dòng)創(chuàng)建的表有 information_schema:主要存儲(chǔ)了系統(tǒng)中的一些數(shù)據(jù)庫(kù)信息,比如用戶表信息、列信息、權(quán)限信息、字符集信息、分區(qū)信息等等 cluster:存儲(chǔ)了系統(tǒng)的集群信息 mysql:存儲(chǔ)了系統(tǒng)的用戶權(quán)限信息。 test:系統(tǒng)自動(dòng)創(chuàng)建的測(cè)試數(shù)據(jù)庫(kù),任何用戶都可以訪問(wèn) 選擇數(shù)據(jù)庫(kù) use test1 顯示test1數(shù)據(jù)庫(kù)中創(chuàng)建的所有表 show tables 刪除數(shù)據(jù)庫(kù) drop database test1; 創(chuàng)建表 create table emp(ename varchar(10),hiredata date,sal decimal(10,2),deptno int(2)); 查看表定義 desc emp; 查看創(chuàng)建表的定義 show create table emp; 刪除表 drop table emp; 修改表 alter table emp modify ename varchar(20); 增加表字段 alter table emp add column age int(3); 刪除表字段 alter table emp drop column age; 字段改名 alter table emp change age age1 int(4); change 和modify都可以修改表的定義,不同的是change后面需要寫(xiě)兩次列名,不方便,但是change的優(yōu)點(diǎn)是可以修改列名稱,則modify則不能 修改字段排序 alter table emp add birth date after ename; alter table emp modify age int(3) first; 更改表名 alter table emp rename emp1;
登錄后復(fù)制
DML語(yǔ)句
是指對(duì)數(shù)據(jù)庫(kù)中表記錄的操作,主要包括表記錄的插入(insert)、更新(update)、刪除(delete)和查詢(select)。
插入記錄
insert into emp(ename,hiredate,sal,deptno)values('zzx1','2000-01-01','2000',1);
也可以不用指定字段名稱,但是values后面的順序要和字段的排列順序一致
inset into emp('zzx1','2000-01-01','2000',1);
含可空字段、非空但是含有默認(rèn)值的字段、自增字段、可以不用再insert后的字段列表里面出現(xiàn),values后面只寫(xiě)對(duì)應(yīng)字段名稱的value,沒(méi)寫(xiě)的字段可以自動(dòng)設(shè)置為null、默認(rèn)值、自增的下一個(gè)數(shù)字
批量增加用逗號(hào)隔開(kāi)
insert into dept values(5,'xxx'),(8,'xxx');
更新記錄
update emp set sal=4000 where ename='xxx';
刪除記錄
delete from emp where ename='doney';
查詢記錄
select * from emp;
*表示所有記錄,也可以用逗號(hào)隔開(kāi)的字段來(lái)選擇查詢
查詢不重復(fù)的記錄
select distinct deptno from emp;
條件查詢
用where關(guān)鍵字來(lái)實(shí)現(xiàn),可以使用<>!=等多條件可以使用or、and等
排序和限制
desc和asc是排序關(guān)鍵字,desc是降序、asc是升序排列 ORDER BY 排序,默認(rèn)是升序
select * from emp order by sal;
如果排序字段的值一樣,則值相同的字段按照第二個(gè)排序字段進(jìn)行排序,如果只有一個(gè)排序字段,則相同字段將會(huì)無(wú)序排序
select * from emp order by deptno,sal desc;
限制
select * from emp order by sal limit 3;
//前者是起始偏移量,后者是顯示行數(shù)
select * from emp order by sal limit 1,3;
limit 和order by 一起使用來(lái)做分頁(yè)
聚合
用戶做一下些匯總操作
sum(求和),count(*)(記錄數(shù)),max(最大值),min(最小值)
with rollup 是可選語(yǔ)法,表示是否對(duì)分類聚合后的結(jié)果進(jìn)行再匯總
having 表示對(duì)分類后的結(jié)果在進(jìn)行條件的過(guò)濾。
select deptno,count(1) from emp group by deptno having count(1)>=1;
登錄后復(fù)制
表連接
大類上分為外連接和內(nèi)連接
外鏈接 又分為左連接和右連接
左連接:包含所以的左邊表中的記錄甚至是右邊表中沒(méi)有和它匹配的記錄。
右連接:同上
select ename,detname from emp left join dept on emp.deptno=dept.deptno; 左連接和右連接可以相互轉(zhuǎn)換
登錄后復(fù)制
子查詢
select * from emp where deptno in(select deptno from dept); 如果子查詢記錄唯一,可以使用=替代in select * from emp where deptno =(select deptno from dept limit 1);
登錄后復(fù)制
記錄查詢
將兩個(gè)表的數(shù)據(jù)按照一定的查詢出來(lái)后,將結(jié)果合在一起顯示
union all 是將結(jié)果集合并在一起,而union是將union all后的結(jié)果在進(jìn)行一次distinct,去除重復(fù)
select deptno from emp union all select deptno from dept; select demtno from emp union select deptno from dept;
登錄后復(fù)制
? xxx 來(lái)查看
如果要查看類別 ? data types 具體的 ? int 查看語(yǔ)法 如 ? create table
登錄后復(fù)制
數(shù)據(jù)類型
對(duì)于整形數(shù)據(jù),MySql還支持在類型名稱后面的小括號(hào)設(shè)置寬度,默認(rèn)設(shè)置為int(11),配合zerofill, 當(dāng)數(shù)字位數(shù)不夠的時(shí)候,用字符‘0’填充 alter table t1 modify id1 int zerofill
登錄后復(fù)制
對(duì)于小數(shù),MySql 分為兩種,浮點(diǎn)數(shù)和定點(diǎn)數(shù)。浮點(diǎn)數(shù)包括float和double,而定點(diǎn)數(shù)只有decimal,定點(diǎn)數(shù)在Mysql內(nèi)部是以字符串形式存放,比浮點(diǎn)數(shù)更精確,適合用于貨幣等精度高的數(shù)據(jù)
浮點(diǎn)數(shù)和定點(diǎn)數(shù)可以用類型名稱加(M,D) M是幾位,D是位于小數(shù)點(diǎn)后面幾位。
日期類型
-
DATE來(lái)表示年月日
-
DATETIME來(lái)表示年月日時(shí)分秒
-
TIME來(lái)表示時(shí)分秒
-
當(dāng)前系統(tǒng)時(shí)間,通常用TIMESTAMP來(lái)表示
TIMESTAMP
創(chuàng)建一個(gè)字段為TIMESTAMP類型,系統(tǒng)自動(dòng)創(chuàng)建了默認(rèn)值為CURRENT_TIMESTAMP(系統(tǒng)日期)。同時(shí)MySql規(guī)定TIMESTAMP類型字段一列只能有一個(gè)默認(rèn)值current_timestamp。如果修改會(huì)報(bào)錯(cuò).
TIMESTAMP 另一個(gè)重要特點(diǎn)是與時(shí)區(qū)有關(guān)。當(dāng)插入時(shí)間時(shí),先轉(zhuǎn)換為本地時(shí)區(qū)后存放,而從數(shù)據(jù)庫(kù)取出時(shí),同樣會(huì)將日期轉(zhuǎn)換為本地時(shí)區(qū)后顯示,這樣兩個(gè)時(shí)區(qū)的用戶看到同一個(gè)時(shí)區(qū)可能就不一樣
查看當(dāng)前時(shí)區(qū) show variables like 'time_zone'; 修改時(shí)區(qū) set time_zone='+9.00';
登錄后復(fù)制
DATETIME插入的格式
YYYY-MM-DD HH:MM:SS 或YY-MM-DD HH:MM:SS 的字符串允許任何標(biāo)點(diǎn)符號(hào)用來(lái)做時(shí)間部分的間隔符 如92@12@31 11^30^45 YYYYMMDDHHMMSS 或YYMMDDHHMMSS的格式?jīng)]有間隔符的字符串
登錄后復(fù)制
字符串類型
CHAR和VARCHAR類型
兩者的主要區(qū)別是存儲(chǔ)方式不同:CHAR列的長(zhǎng)度固定為創(chuàng)建表時(shí)聲明的長(zhǎng)度,長(zhǎng)度可以為0-255;二VARCHAR列中的值是可變長(zhǎng)度。同時(shí)在檢索的時(shí)候,CHAR列刪除尾部的空格 ,而VARCHAR保留空格,由于CHAR是固定長(zhǎng)度,所以它的處理速度別VARCHAR快很多,但是其缺點(diǎn)是浪費(fèi)內(nèi)存,在使用中VARCHAR被更多的使用
create table vc (v varchar(4),c char(4))
insert into vc values('ab ','ab ');
selelct length(v),length(c) from vc
//4,2
登錄后復(fù)制登錄后復(fù)制
枚舉
create table vc (v varchar(4),c char(4))
insert into vc values('ab ','ab ');
selelct length(v),length(c) from vc
//4,2
登錄后復(fù)制登錄后復(fù)制
set類型
set類型可以一次選取多個(gè)成員
create table t2 (col set('a','b','c','d'));
INSERT into t2 VALUE ('a,b'),('a,d,a'),('a,b'),('a,c'),('a');
對(duì)于(a,d,a)這個(gè)包含重復(fù)成員的集合只取一次 結(jié)果為’a,d'
登錄后復(fù)制
運(yùn)算符
p==/==除法獲取商 MOD==%==除法獲取余數(shù)
登錄后復(fù)制
=和<=>區(qū)別
不能用于null比較,后者可以
between 使用格式 a between min and max 等價(jià)于 a>=min and a<=max in的使用格式 a in(value1,value2...); like 使用格式如 a like %123%,當(dāng)字符串含有123則返回1 否則返回0 REGEXP 使用格式 str REGEXP str_pat 當(dāng)str字符串中含有str_pat 相匹配的字符串,則返回1
登錄后復(fù)制
位運(yùn)算
| 運(yùn)算符 | 作用 |
|---|---|
| & | and |
| | | or |
| ^ | xor |
| ~ | 位異或 |
| > | 位右移 |
| << | 位左移 |
常用函數(shù)
字符串函數(shù)
| 函數(shù) | 功能 |
|---|---|
| CONCAT(s1,s2,s3…) | 連接s1到sn的字符串(任何字符串和null拼接都是null) |
| insert(str,x,y,instr) | 將字符串str從x位置開(kāi)始,y字符長(zhǎng)的子串替換為字符串instr |
| lower(str) | 將字符串str中所有字符變?yōu)樾?xiě) |
| UPPER(str) | 大寫(xiě) |
| LEFT(str,x) | 返回字符串str最左邊x個(gè)字符 |
| RIGHT(str,x) | 返回字符串str最右邊的x個(gè)字符 |
| LPAD(str,n,pad) | 用字符串pad對(duì)str最左邊進(jìn)行填充,直到長(zhǎng)度為n個(gè)字符串長(zhǎng)度 |
| PRPAD(str,n,pad) | 用字符串pad對(duì)str最右邊進(jìn)行填充,直到長(zhǎng)度為n個(gè)字符串長(zhǎng)度 |
| LTRIM(str) | 去掉字符串str左側(cè)的空格 |
| RIGHT(str) | 去掉字符串str行尾的空格 |
| REPEAT(str,x) | 返回str重復(fù)x次的結(jié)果 |
| REPLACE(Str,a,b) | 用字符串b替換字符串str中所有出現(xiàn)的字符串a(chǎn) |
| STRCMP(s1,s2) | 比較字符串s1和s2 |
| TRIM(str) | 去掉行尾和行頭的空格 |
| SUBSTRING(str,x,y) | 返回字符串str x位置起y字符串長(zhǎng)度的字串 |
數(shù)字函數(shù)
| 函數(shù) | 功能 |
|---|---|
| ABS(X) | 返回x的絕對(duì)值 |
| CEIL(X) | 返回大于x的最小整數(shù)值 |
| FLOOR(X) | 返回小于x的最大整數(shù)值 |
| MOD(x,y) | 返回x/y的模 |
| RAND() | 返回0-1內(nèi)的隨機(jī)值 |
| ROUND(x,y) | 返回參數(shù)x的四舍五入的有y位小數(shù)的值 |
| TRUNCATE(x,y) | 返回?cái)?shù)值x截?cái)酁閥位小樹(shù)的結(jié)果 |
日期和時(shí)間函數(shù)
| 函數(shù) | 功能 |
|---|---|
| CURDATE() | 返回當(dāng)前日期 |
| CURTIME() | 返回當(dāng)前時(shí)間 |
| NOW() | 返回當(dāng)前的日期和時(shí)間 |
| UNIX_TIMESTAMP(date) | 返回date的unix時(shí)間戳 |
| FROM_UNIXTIME | 返回UNIX時(shí)間戳的日期值 |
| WEEK(date) | 返回日期date為一年中的第幾周 |
| YEAR(date) | 返回日期date的年份 |
| HOUR(time) | 返回time的小時(shí)值 |
| MINUTE(time) | 返回time的分鐘值 |
| MONTHNAME(date) | 返回date的月份名 |
| DATE_FROMATE(date,fmt) | 返回按字符串fmt格式化日期date值 |
| DATE_ADD(date,interval expr type) | 返回一個(gè)日期或時(shí)間值加上一個(gè)時(shí)間間隔的時(shí)間值 |
| DATEDIFF(expr,expr2) | 返回起始時(shí)間expr和結(jié)束時(shí)間expr2之間的天數(shù) |
流程函數(shù)
| 函數(shù) | 功能 |
|---|---|
| IF(value,t f) | 如果value是真 返回 t;否則返回f |
| IFNULL(value1,value2) | 如果value1不為空,返回value1,負(fù)責(zé)返回value2 |
| CASE WHEN[value1] THEN[value2]…ELSE[default] END | 如果value1是真,返回result1否則返回defalut |
| case [expr] WHEN[value1] THEN[value2]…ELSE[default] END | 如果expr等于value1,返回result1否則返回defalut |
實(shí)例
create table salary(userid int ,salary decimal(9,2)); insert into salary values(1,1000),(2,2000),(3,3000),(4,4000),(5,5000),(1,null); select * from salary select if(salary>2000,'high','low') from salary; select ifnull(salary,0) from salary; select case when salary <=2000 then 'low' else 'high' end from salary; select case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end from salary;
登錄后復(fù)制登錄后復(fù)制
其他函數(shù)
| 函數(shù) | 功能 |
|---|---|
| DATABASE() | 返回的確數(shù)據(jù)庫(kù)庫(kù)名 |
| VERSION() | 返回當(dāng)前數(shù)據(jù)庫(kù)版本 |
| USER() | 返回當(dāng)前登錄用戶名 |
| INET_ATON(IP) | 返回ip地址的數(shù)字表示 |
| INET_NTOA(num) | 返回?cái)?shù)字代表的ip地址 |
| PASSWORD(str) | 返回字符串str加密版本 |
| MD5() | 返回字符串的md5值 |
MySql引擎
MySql支持的存儲(chǔ)引擎包括MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等,其中InnoDB和BDB提供事務(wù)安全表,用戶可以選擇不同的數(shù)據(jù)存儲(chǔ)引擎來(lái)提高應(yīng)用的效率
創(chuàng)建表如果不指定存儲(chǔ)引擎,系統(tǒng)默認(rèn)使用默認(rèn)存儲(chǔ)引擎,MySql5.5之前的默認(rèn)引擎是MyISAM,5.5之后改為InnoDB。如果要修改默認(rèn)的存儲(chǔ)引擎,可以在參數(shù)文件中設(shè)置default-table-type.
create table salary(userid int ,salary decimal(9,2)); insert into salary values(1,1000),(2,2000),(3,3000),(4,4000),(5,5000),(1,null); select * from salary select if(salary>2000,'high','low') from salary; select ifnull(salary,0) from salary; select case when salary <=2000 then 'low' else 'high' end from salary; select case salary when 1000 then 'low' when 2000 then 'mid' else 'high' end from salary;
登錄后復(fù)制登錄后復(fù)制
MyISAM
MyISAM 不支持事務(wù)、也不 不支持外鍵,其優(yōu)點(diǎn)是速度快,對(duì)事務(wù)完整性沒(méi)有要求。以SELECT和INSERT為主的應(yīng)用基本上都就可以使用這個(gè)表
InnoDB
InnoDB存儲(chǔ)引擎提供了具有提交、回滾和崩潰恢復(fù)能力的事務(wù)安全。但是對(duì)比MyISAM的存儲(chǔ)引擎,InnoDB寫(xiě)的處理效率差一些,并且會(huì)占用更多的磁盤空間以保留數(shù)據(jù)和索引。
create table autoincre_demo (i smallint not null auto_increment,name varchar(10),primary key(i))engine=innodb;insert into autoincre_demo values(1,'1'),(0,'2'),(null,'3')
登錄后復(fù)制
如果插入空或者0,則實(shí)際插入的將是自動(dòng)增長(zhǎng)后的值。
可以通過(guò)以下語(yǔ)句強(qiáng)制設(shè)置自動(dòng)增加列的初始值,默認(rèn)從1開(kāi)始,但是該強(qiáng)制的默認(rèn)值是保留到內(nèi)存中,如果數(shù)據(jù)庫(kù)從起,這個(gè)強(qiáng)制的默認(rèn)值會(huì)丟失,就需要數(shù)據(jù)庫(kù)啟動(dòng)后重新設(shè)置
ALTER TABLE *** auto_increment =n
登錄后復(fù)制
MEMORY
memory 存儲(chǔ)引擎使用存在于內(nèi)存中的內(nèi)容來(lái)創(chuàng)建表,每個(gè)MEMORY表實(shí)際對(duì)應(yīng)一個(gè)磁盤文件,格式是.fm,MEMORY表的訪問(wèn)非常快,因?yàn)樗臄?shù)據(jù)是放在內(nèi)存中,并且默認(rèn)使用HASH索引,但是一旦服務(wù)關(guān)閉,表中的數(shù)據(jù)就會(huì)
alter table t2 engine=memory; show TABLE status like 't2' 給memory表創(chuàng)建索引。可以指定hash索引還是btree索引 create index mem_hash using hash on tab_memory(city_id);
登錄后復(fù)制
在啟動(dòng)MySql服務(wù)的時(shí)候使用–init-file選項(xiàng),把INSERT INTO … SELECT或LOAD DATA INFILE這樣的語(yǔ)句放入這個(gè)文件中,就可以在服務(wù)啟動(dòng)時(shí)從持久穩(wěn)固的數(shù)據(jù)源裝載表
服務(wù)器需要足夠的內(nèi)存來(lái)維持同一時(shí)間使用的MEMORY表,當(dāng)不需要MEMORY表的內(nèi)容,要釋放MEMORY表的內(nèi)存,執(zhí)行DELETE FROM或 TRUNCATE TABLE 或者是DROP TABLE
每個(gè)MEMORY表中可以放置的數(shù)據(jù)量的大小,受max_heap_table_size系統(tǒng)變量的約束,初始值是16mb,可以根據(jù)需要加大、
MEMORY類型的存儲(chǔ)引擎主要用在那些內(nèi)容變化不平凡的表,或作為統(tǒng)計(jì)操作的中間結(jié)果表,便于高效的對(duì)中間結(jié)果進(jìn)行分析并得到最終的統(tǒng)計(jì)結(jié)果。
TokuDB
TokuDB是第三方的存儲(chǔ)引擎,是一個(gè)高性能、支持事務(wù)處理的MySql和MariaDB的存儲(chǔ)引擎,具有高擴(kuò)展性、高壓縮、高效率的寫(xiě)入性能,支持大多數(shù)在線的DDL操作
TokuDB 特別適用的場(chǎng)景
-
日志數(shù)據(jù),因?yàn)槿罩緮?shù)據(jù)通常插入頻繁且儲(chǔ)存量大
-
歷史數(shù)據(jù),通常不會(huì)有在寫(xiě)的操作,可以利用TokuDB的高壓縮特性進(jìn)行存儲(chǔ)
-
在線DDL頻繁的場(chǎng)景
幾種常用存儲(chǔ)引擎的適用環(huán)境
-
MyISAM:如果應(yīng)用是以讀操作和插入操作為主,只有很少的更新和刪除操作,并且對(duì)事務(wù)的完整性,并發(fā)性要求不高,那么選擇這個(gè)引擎非常合適
-
Innodb:用于事務(wù)的處理,支持外鍵。如果應(yīng)用對(duì)事務(wù)的完整性較高的要求,在并發(fā)條件下要求數(shù)據(jù)的一致性,數(shù)據(jù)除了插入和查詢外,還包括很多的更新和刪除操作,那么Innodb存儲(chǔ)引擎比較適合
-
MEMORY:將所有數(shù)據(jù)都存在RAM中,如果需要快速定位記錄和其他類似數(shù)據(jù)的環(huán)境下,可以提供極快的訪問(wèn),缺陷在于對(duì)表大小的限制,太大的表無(wú)法緩存在內(nèi)存中,其次是要確保表的數(shù)據(jù)是可恢復(fù)的.
-
MERGE:用于將一系列等同MyISAM表以邏輯方式組合在一起,并作為一個(gè)對(duì)象引用它們。MERGE表的優(yōu)點(diǎn)在于可以突破單個(gè)MyISAM表大小的限制,并且通過(guò)將不同的表分布在多個(gè)磁盤上,可以有效的改善MERGE表的訪問(wèn)效率
Text與BLOB
如果保存少量字符串會(huì)選擇CHAR和VARCHAR 但是保存較大文本時(shí),選擇text或blob,兩者主要差別是blob能用來(lái)保存二進(jìn)制數(shù)據(jù)如圖片;而text只能保存字符數(shù)據(jù)
BLOB與TEXT引起的性能問(wèn)題,特別是在執(zhí)行大量的刪除數(shù)據(jù)時(shí),刪除操作會(huì)留下很大的空洞,以后填入這些空洞的記錄在插入的性能上會(huì)有影響,建立定期使用OPTIMIZE TABLE對(duì)這類表進(jìn)行碎屏整理
optimize table t
登錄后復(fù)制
使用合成的索引來(lái)提供大文本字段的查詢性能
合成索引就是根據(jù)大文本字段的內(nèi)容建立一個(gè)散列值,并把值存儲(chǔ)在單獨(dú)的數(shù)據(jù)列中,接下來(lái)就是通過(guò)檢索散列值找到數(shù)據(jù)行,但是只能做到精確匹配不能使用范圍搜索??梢允褂肕D5,SHA1,CRC32 等生成散列值,使用精確匹配,在一定程度上減少了I/O,提高了查詢效率。如果散列算法生成的字符串帶有尾部空格,就不要存儲(chǔ)在CHAR或VARCHAR列中,它會(huì)受尾部空格的影響
如果需要對(duì)BLOB或CLOB字段進(jìn)行模糊查詢,MySQL提高前綴索引,也就是只為字段的前n列創(chuàng)建索引 desc select * from t where context like 'beijing%' \G;
登錄后復(fù)制
注意事項(xiàng)
-
在不必要的時(shí)候避免檢索大型的BLOB或TEXT:如SELECT * 查詢,盡量從符合條件的數(shù)據(jù)行中檢索BLOB或TEXT指
-
把BLOB或TEXT列分離到單獨(dú)表中:在某些環(huán)境下,如果把這些數(shù)據(jù)列移動(dòng)到第二張數(shù)據(jù)表中,可以把原數(shù)據(jù)表中的數(shù)據(jù)列轉(zhuǎn)換為固定長(zhǎng)度的數(shù)據(jù)行格式,減少主表的碎片,可以得到固定長(zhǎng)度數(shù)據(jù)行的性能優(yōu)勢(shì)。還可以在運(yùn)行SELECT * 查詢的時(shí)候不會(huì)通過(guò)網(wǎng)絡(luò)傳輸大量的BLOB或TEXT指
設(shè)計(jì)索引的原則
-
搜索的索引列,不一定是所要選擇的列。最適合索引的列是出現(xiàn)在where字句中的列,或連接字句中指定的列,而不是出現(xiàn)在select關(guān)鍵字后的列表中的列
-
使用唯一索引.考慮到某列中的值分布,索引的列基礎(chǔ)越大,索引的效果越好。入存放出生日期的列具有各部相同的值,很容易區(qū)分,但是記錄性別的列,只含有男和女對(duì)此類進(jìn)行索引沒(méi)有多大好處
-
使用短檢索。如果對(duì)字符串進(jìn)行檢索,應(yīng)該指定一個(gè)前綴長(zhǎng)度。例如:一個(gè)CHAR(200)列,如果前10個(gè)或20個(gè)字符內(nèi),多數(shù)值是唯一的,那么就不要對(duì)整個(gè)列進(jìn)行檢索。對(duì)前10個(gè)或20個(gè)字符進(jìn)行檢索能夠節(jié)省大量索引空間,是查詢更快。
-
利用最左前綴。在創(chuàng)建一個(gè)n列索引時(shí),實(shí)際是創(chuàng)建了MySQL可利用的n個(gè)索引。多列索引可起幾個(gè)索引的作用,因?yàn)榭衫盟饕钭筮叺牧屑?jí)來(lái)匹配。
-
不要過(guò)度索引。每個(gè)索引都是占用額外的磁盤空間,并降低寫(xiě)操作的性能。在修改表內(nèi)容的時(shí)候,索引必須進(jìn)行相應(yīng)的更新,有時(shí)候需要重構(gòu)。如果有一個(gè)索引很少被用到,那么會(huì)不必要的減緩表的修改速度。此外,mysql在生成一個(gè)執(zhí)行計(jì)劃時(shí),要考慮各個(gè)索引,這也要花費(fèi)時(shí)間。創(chuàng)建多余的索引給查詢優(yōu)化帶來(lái)了更多的工作
-
對(duì)于Innodb,記錄默認(rèn)會(huì)按照一定的順序排序,如果有明確的定義主鍵,則按照主鍵排序順序保存。
存儲(chǔ)過(guò)程和函數(shù)
什么是存儲(chǔ)過(guò)程和函數(shù)
存儲(chǔ)過(guò)程和函數(shù)是事先經(jīng)過(guò)編譯并存儲(chǔ)在數(shù)據(jù)庫(kù)中的一段SQL語(yǔ)句的集合,調(diào)用存儲(chǔ)過(guò)程和函數(shù)
可以簡(jiǎn)化應(yīng)用開(kāi)發(fā)人員的很多工作,減少數(shù)據(jù)在數(shù)據(jù)庫(kù)和應(yīng)用服務(wù)器之間的傳輸,對(duì)于提供數(shù)據(jù)處理的效率是有好處的。
存儲(chǔ)過(guò)程很函數(shù)的區(qū)別在于函數(shù)必須有返回值,而存儲(chǔ)過(guò)程沒(méi)有,儲(chǔ)存過(guò)程的參數(shù)可以使用IN,OUT,INOUT類型,而函數(shù)的參數(shù)只能是IN類型的。如果有函數(shù)從其他類型的數(shù)據(jù)庫(kù)遷移到MySQL,那么就可能因此需要將函數(shù)改造成存儲(chǔ)過(guò)程。
存儲(chǔ)過(guò)程和函數(shù)的相關(guān)操作
在對(duì)儲(chǔ)存過(guò)程和函數(shù)操作時(shí),需要首先確認(rèn)用戶是否具有相應(yīng)的權(quán)限。例如,創(chuàng)建存儲(chǔ)過(guò)程或者函數(shù)需要CREATE ROUTINE權(quán)限,修改或者刪除存儲(chǔ)過(guò)程或者函數(shù)需要ALTER ROUTINE權(quán)限,執(zhí)行過(guò)程或者函數(shù)需要EXECUTE權(quán)限
創(chuàng)建一個(gè)新的過(guò)程 film_in_stock,該過(guò)程用來(lái)檢查 film_id和store_id對(duì)應(yīng)的inventory是否滿足要求,并且返回滿足的inventory_id 以及滿足要求的記錄數(shù)
CREATE PROCEDURE film_in_stock(in p_fim_id int,in p_store_id int,out p_film_count int) READS sql data begin select inventory_id from inventory where film_id =p_film_id and store_id=p_store_id and inventory_in_stock(inventory_id); SELECT found_rows() into p_film_count; end $$
登錄后復(fù)制
通常在創(chuàng)建過(guò)程和函數(shù)之前,都會(huì)通過(guò)DELIMITE $$命令將語(yǔ)句的結(jié)束符從';'修改成其他符號(hào),這里使用‘$$’,這樣在過(guò)程和函數(shù)中的';'就不會(huì)被MySql,解釋成語(yǔ)句的結(jié)束而錯(cuò)誤。在存儲(chǔ)過(guò)程或者函數(shù)創(chuàng)建完成 通過(guò)‘DELIMITER;'命令在將結(jié)束符改回成';'
調(diào)用過(guò)程
CALL film_in_stock(2,2,@a);
登錄后復(fù)制
存儲(chǔ)過(guò)程的好處在于處理邏輯都封裝在數(shù)據(jù)庫(kù)端,調(diào)用者不需要了解中間的處理邏輯,一旦邏輯改變,只需要修改存儲(chǔ)過(guò)程,對(duì)調(diào)用者的程序沒(méi)有影響
刪除存儲(chǔ)過(guò)程或者函數(shù)
一次只能刪除一個(gè)存儲(chǔ)過(guò)程或者函數(shù),刪除需要ALTER ROUTINE權(quán)限
drop procedure film_in_stock;
登錄后復(fù)制
查看存儲(chǔ)過(guò)程或者函數(shù)狀態(tài)
show procedure status like 'film_in_stock';
登錄后復(fù)制
查看存儲(chǔ)過(guò)程的函數(shù)定義
show create procedure film_in_stock
登錄后復(fù)制
變量使用
存儲(chǔ)過(guò)程和函數(shù)中可以使用變量,在MySql 5.1版本中,變量不區(qū)分大小寫(xiě)
變量的定義
通過(guò)DECLARE可以定義一個(gè)局部變量,該變量的作用范圍只能在BEGIN...END中,可以用在嵌套塊中
定義一個(gè)DATE類型的變量
DECLARE last_month_start date;
登錄后復(fù)制
變量賦值 可以直接賦值,或者通過(guò)查詢賦值。直接賦值使用set,可以賦常量或者賦表達(dá)式
set var_name=expr [,var_name=expr]... set last_month_start=date_sub(current_date(),interval month); select col_name[,...] into var_name[,...] table_expr;
登錄后復(fù)制
定義條件和處理
delimiter $$ create procedure actor_insert() begin declare continue handler for sqlstate '23000' set @x2=1; set @x=1; insert into actor(actor_id,first_name,last_name) values(201,'test','201'); set @x=2; insert into actor(actor_id,first_name,last_name) values(1,'test','1'); set @x=3; end ; $$
登錄后復(fù)制
調(diào)用處理函數(shù)時(shí)遇到主鍵重的錯(cuò)誤會(huì)按照定義的處理方式去處理,由于定義的是CONTINUE 會(huì)繼續(xù)執(zhí)行下面的語(yǔ)句
還支持EXIT表示終止
光標(biāo)使用
聲明光標(biāo)
declare cursor_name cursor for select_statement
open光標(biāo)
open cursor_name
fetch光標(biāo)
fetch cursor_name into var_name[,var_name]...
close光標(biāo)
close cursor_name
delimiter $$
create procedure payment_stat()
begin
declare i_staff_id int;
declare d_amount decimal(5,2);
declare cur_payment cursor for select staff_id,amount from payment;
declare exit handler for not found close cur_payment;
set @x1=0;
set @x2=0;
open cur_payment;
REPEAT
FETCH cur_payment into i_staff_id,d_amount;
if i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
end if;
until 0 end repeat;
close cur_payment;
end;
$$
登錄后復(fù)制
變量,條件,處理程序,光標(biāo)都是通過(guò)DECLARE定義的,她們之間是有先后順序要求的。變量和條件必須在最前面聲明,然后才能是光標(biāo)的聲明,最后才可以是處理程序的聲明
控制語(yǔ)句
case
when i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
loop 和leave結(jié)合
create procedure actor_insert()
begin
set @x=0;
ins:loop
set @x=@x+1;
if @x=100 then
leave ins;
end if;
insert into actor(first_name,last_name) values('Test','201');
end loop ins;
end;
$$
inerate 語(yǔ)句作用是跳過(guò)當(dāng)前循環(huán)的剩下語(yǔ)句,直接進(jìn)入下一輪循環(huán)
create procedure actor_insert()
begin
set @x=0;
ins:loop
set @x=@x+1;
if @x=10 then
leave ins;
elseif mod(@x,2)=0 then
iterate ins;
end if;
insert into actor(actor_id,first_name,last_name) values(@x+200,'test',@x);
end loop ins;
end;
$$
repeat 語(yǔ)句 有條件的循環(huán)控制語(yǔ)句,當(dāng)滿足條件的時(shí)候退出循環(huán)
repeat
fetch cur_payment into i_staff_id,d_amount;
if i_staff_id =2 then
set @x1=@x1+d_amount;
else
set @x2=@x2+d_amount;
end if;
until 0 end repeat;
while
delimiter $$
create procedure loop_demo()
begin
set @x=1,@x1=1;
repeat
set @x=@x+1;
until @x>0 end repeat;
while @x<1 do
set @x=@x+1;
end while;
end;
$$
//創(chuàng)建事件調(diào)度器
CREATE EVEN test_event_1 ON SCHEDULE
EVERY 5 SECOND
DO
INSERT INTO dept(deptno,deptname)
VALUES(3,'3');
//查看本地調(diào)度器狀態(tài)
show variables like '%scheduler%';
//打開(kāi)調(diào)度器
set global event_scheduler=1;
//查看后臺(tái)進(jìn)程
show processlist;
//創(chuàng)建一個(gè)新的定時(shí)器 定時(shí)清空表,防止表變大,這類觸發(fā)器非常適合去定期清空臨時(shí)表或者日志表
create event trunc_test
on schedule every 1 minute
do truncate table test;
禁用調(diào)度器或者刪除
alter event test_event_1 disable;
drop event test_event_1;
登錄后復(fù)制
| 事件調(diào)度器 | 說(shuō)明 |
|---|---|
| 優(yōu)勢(shì) | MySQL事件調(diào)度器部署在數(shù)據(jù)庫(kù)內(nèi)部由DBA或?qū)H私y(tǒng)一維護(hù)和管理,避免將一些數(shù)據(jù)庫(kù)相關(guān)的定時(shí)任務(wù)部署到操作系統(tǒng)層,減少操作系統(tǒng)管理員產(chǎn)生誤操作的風(fēng)險(xiǎn),對(duì)后續(xù)的管理和維護(hù)也非常有益。例如,后續(xù)進(jìn)行數(shù)據(jù)庫(kù)遷移時(shí)無(wú)需再遷移操作系統(tǒng)層的定時(shí)任務(wù),數(shù)據(jù)庫(kù)遷移本身已經(jīng)包含了調(diào)度事件的遷移 |
| 使用場(chǎng)景 | 事件調(diào)度器適用于定期收集統(tǒng)計(jì)信息,定期清理歷史數(shù)據(jù),定期數(shù)據(jù)庫(kù)檢查(例如,自動(dòng)監(jiān)控和回復(fù)slave失敗進(jìn)程) |
| 注意事項(xiàng) | 在繁忙且要求性能的數(shù)據(jù)庫(kù)服務(wù)器上要慎重部署和啟用調(diào)度去;過(guò)于復(fù)雜的處理更適合程序?qū)崿F(xiàn);開(kāi)啟和關(guān)閉事件調(diào)度器需要具有超級(jí)用戶權(quán)限 |
事務(wù)控制和鎖定語(yǔ)句
-
MySQL支持對(duì)MyISAM和MEMORY存儲(chǔ)引擎的表進(jìn)行表級(jí)鎖定,對(duì)InnoDB存儲(chǔ)引擎的表進(jìn)行行集鎖定。默認(rèn)情況下是自動(dòng)獲得。
-
LOCK TABLES 可以用于鎖定當(dāng)前線程獲得的表,如果表被其他線程鎖定,當(dāng)前線程一直等待到可以獲取現(xiàn)有鎖定為止。
-
UNLOCK TABLES 可以釋放當(dāng)前線程獲得的任何鎖定,當(dāng)前線程執(zhí)行另一個(gè)LOCK TABLES時(shí),或當(dāng)與服務(wù)器的連接被關(guān)閉時(shí),所有由當(dāng)前線程鎖定的表被隱式地解鎖。
| session_1 | session_2 |
|---|---|
| 獲取表film_text 的read鎖定 lock table fim_text read | |
| 當(dāng)前seesion可以查詢記錄 select * from fim_text | 其他seesion也可以查詢select * from fim_text |
| 其他session更新鎖定表會(huì)等待鎖 update fim_text …. 處于等待狀態(tài) | |
| 釋放鎖 unlock tables | 等待 |
| sesion獲取鎖,更新成功 |
事務(wù)控制
mysql 通過(guò)set autocommit ,start transaction ,commit ,rollback等語(yǔ)句支持本地事務(wù)。默認(rèn)情況下,mysql是自動(dòng)提交(autocommit)的,如果需要明確的commit和rollback來(lái)提交和回滾事務(wù),那么就需要通過(guò)明確的事務(wù)控制命令來(lái)開(kāi)始事務(wù),這是和Oracle的事務(wù)管理明顯不同的地方。
-
start transaction 或 begin語(yǔ)句可以開(kāi)始一項(xiàng)新的事務(wù)
-
commit 和rollback用來(lái)提交或者回滾事務(wù)。
-
chain和release字句分別用來(lái)定義在事務(wù)提交或回滾之后的操作,chain會(huì)立即啟動(dòng)一個(gè)新事務(wù),并且和剛才的事務(wù)具有相同的隔離級(jí)別,release則會(huì)斷開(kāi)和客戶端的連接。
-
set autocommit可以修改當(dāng)前連接的提交方式,如果設(shè)置了set autocommit=0,則設(shè)置之后的所有事務(wù)讀需要通過(guò)明確的命令進(jìn)行提交或者回滾。
如果只是對(duì)某些語(yǔ)句需要進(jìn)行事務(wù)控制,則使用start transaction語(yǔ)句開(kāi)始一個(gè)事務(wù)比較方便,這樣事務(wù)結(jié)束之后可以自動(dòng)回到自動(dòng)提交的方式,如果希望所有的事務(wù)都不是自動(dòng)提交的,那么通過(guò)修改autocommit來(lái)控制事務(wù)比較方便。
start transation和commit and chain
| session_1 | session_2 |
|---|---|
| 從表actor查詢 select * from actor 沒(méi)有數(shù)據(jù) | 從表actor查詢 select * from actor 沒(méi)有數(shù)據(jù) |
| 啟動(dòng)一個(gè)事務(wù)start transaction; insert into actor… | |
| 查詢actor select * from actor 仍然為空 | |
| commit | |
| 再次查詢 就有 了 select * from actor… |
| session_1 | session_2 |
|---|---|
| 自動(dòng)提交 inset into actor… | |
| 可以從表中查詢到剛插入 select *from actor | |
| 重新用star transaction 啟動(dòng)一個(gè)事務(wù) start transaction; insert into actor…;用commit and chain命令提交 commit and chain;此時(shí)啟動(dòng)一個(gè)新的事務(wù), insert into… | |
| 剛插入的數(shù)據(jù)查不到 select * from actor… | |
| 用commit 提交 commit; | |
| 剛插入的可以查詢到 |
如果在鎖表的期間,用start transaction 命令開(kāi)始一個(gè)新的事務(wù),會(huì)造成一個(gè)unlock tables被執(zhí)行
| session_1 | session_2 |
|---|---|
| 查詢一個(gè)actor_id=201,結(jié)果為空 select * from actor where actor_id=201; | 從表里查詢 同理結(jié)果為空 |
| 對(duì)表加寫(xiě)鎖 lock table actor write | |
| 對(duì)表actor 的讀操作被阻塞 select * from actor where actor_id=201 | |
| 插入數(shù)據(jù) insert into actor(actor_id,..)values(201,..) | 等待 |
| 回滾記錄 rollback | 等待 |
| 用start transaction命令重新啟動(dòng)一個(gè)事務(wù) | 等待 |
| 開(kāi)始一個(gè)事務(wù),表鎖被釋放,可以查詢;select …where actor_id=201 | |
| 查到數(shù)據(jù) |
因此,在同一個(gè)事務(wù)中,最好不使用不同的存儲(chǔ)引擎,否則rollback時(shí)需要對(duì)非事務(wù)類型的表進(jìn)行特別的處理。因?yàn)椋琧ommit ,rollback 只能對(duì)事務(wù)類型的表進(jìn)行提交和回滾。
通常情況下,只對(duì)提交的事務(wù)記錄到二進(jìn)制的日志中,但是如果一個(gè)事務(wù)中包含非事務(wù)類型的表,那么回滾操作也會(huì)被記錄到二進(jìn)制日志中,以確保非事務(wù)類型表的更新可以被復(fù)制到從數(shù)據(jù)庫(kù)(slave)中。
在事務(wù)中可以通過(guò)定義savepoint,指定回滾事務(wù)部分,但是不能指定提交事務(wù)的一個(gè)部分。對(duì)于復(fù)雜的應(yīng)用,可以定義多個(gè)不同的savepoint,滿足不同的條件時(shí),回滾不同的savepoint,需要注意的是,如果定義了相同名字的savepoint,則后面定義的savepoint會(huì)覆蓋之前的定義。對(duì)于不需要使用的savepoint,可以通過(guò)release savepoint命令刪除。
事務(wù)回滾
| session_1 | session_2 |
|---|---|
| 從表中查詢first_name=’Simon’的記錄為空 select * from….where first_name=’simon’ | 從表中查詢first_name=’Simon’的記錄為空 select * from….where first_name=’simon’ |
| 啟動(dòng)一個(gè)事務(wù)插入 一條數(shù)據(jù) start transaction; inset ….values(‘simon’…) | |
| 查詢到剛插入的數(shù)據(jù) select * from…where first_name=’simon’ | 無(wú)法從actor查到session1剛插入的記錄 select * from … where first_name=’simon’ |
| 有數(shù)據(jù) | 無(wú)數(shù)據(jù) |
| 定義一個(gè) savepoint,名稱為test savepoint test; insert into …values(…,tom) | |
| 查詢到兩條數(shù)據(jù)select *… | 仍然查詢不到數(shù)據(jù) select * … |
| 回滾到剛才定義的savepoint rollback to savepoint test | |
| 從表actor查詢到一條數(shù)據(jù) 第二天被回滾 select * from …. | 仍然查詢不到數(shù)據(jù) |
| 提交commit | |
| 查詢的到 | 查詢的到 |
分布式事務(wù)的使用
MySql從5.0.3開(kāi)始支持分布式事務(wù),當(dāng)前分布式事務(wù)只支持InnoDb存儲(chǔ)引擎。一個(gè)分布式事務(wù)會(huì)涉及多個(gè)行動(dòng),這些行動(dòng)本身是事務(wù)性。所有行動(dòng)都必須一起成功完成,或者一起被回滾
在mysql中,使用分布式事務(wù)的應(yīng)用程序涉及一個(gè)或多個(gè)資源管理器和一個(gè)事務(wù)管理器。
-
資源管理器(rm)用于提供通向事務(wù)資源的途徑。數(shù)據(jù)庫(kù)服務(wù)器是一種資源管理器,該管理器必須可以提交或回滾由rm管理的事務(wù)。如:多臺(tái)mysql數(shù)據(jù)庫(kù)作為多臺(tái)資源管理器或者幾臺(tái)mysql服務(wù)器和幾臺(tái)oracle服務(wù)器作為資源管理器。
-
事務(wù)管理器(tm)用于協(xié)調(diào)作為一個(gè)分布式事務(wù)一部分的事務(wù)。tm與管理每個(gè)事務(wù)的rm s進(jìn)行通信。在分布式事務(wù)中,各個(gè)單個(gè)事務(wù)均是分布式事務(wù)的“分支事務(wù)”。分布式事務(wù)和各個(gè)分支通過(guò)一種命名方法進(jìn)行標(biāo)示。
執(zhí)行分布式的過(guò)程分為兩階段提交,發(fā)生時(shí)間有分布式事務(wù)的各個(gè)分支需要進(jìn)行的行動(dòng)已經(jīng)被執(zhí)行之后
-
在第一階段,所有分支唄預(yù)備好,即它們被TM告知要準(zhǔn)備提交。通常,這意味著用于管理分支的每個(gè)RM會(huì)記錄對(duì)于被穩(wěn)定保存的分支的行動(dòng)。分支指示是否它們可以這么做,這些結(jié)果被用于第二階段
-
在第二階段,TM告知Rms是否要提交或回滾,如果在預(yù)備分支時(shí),所有的分支指示它們將能夠提交,則所有的分支被告知要提交。如果在預(yù)備時(shí),有任何分支指示它將不能提交,則所有分支唄告知回滾。
語(yǔ)法
xa start xid 用于啟動(dòng)一個(gè)帶給定xid值的xa事務(wù)。每個(gè)xa事務(wù)必須有一個(gè)唯一的xid值,因此該值當(dāng)前不能被其他xa事務(wù)使用
xa grtid[,beual[,formatId]] grtid 是一個(gè)分布式事務(wù)比較符,相同的分布式事務(wù)應(yīng)該使用相同的gtrid,這樣可以明確知道XA事務(wù)屬于哪個(gè)分布式事務(wù)
bequal 是一個(gè)分支限定符,默認(rèn)值是空值。對(duì)于一個(gè)分布式事務(wù)中的每個(gè)分支事務(wù),bqual指是唯一的
formatId是一個(gè)數(shù)值,要用來(lái)標(biāo)志 由gtrid和bqual值使用的格式,默認(rèn)是1
xa end xid[suspend [for migrate]] xa prepare xid
登錄后復(fù)制
使事務(wù)進(jìn)入prepare 狀態(tài),也就是兩階段提交的第一個(gè)提交階段
xa commit xid[one phase] xa rollback xid
登錄后復(fù)制
用來(lái)提交和回滾具體的分支事務(wù)
xa recover 返回當(dāng)前數(shù)據(jù)庫(kù)中處于PREPARE狀態(tài)的分支事務(wù)的具體信息
分布式的關(guān)鍵在于如何確保分布式事務(wù)的完整性,以及在某個(gè)分支出現(xiàn)問(wèn)題時(shí)的故障解決,xa的相關(guān)命令就是提供給應(yīng)用如何在多個(gè)獨(dú)立的數(shù)據(jù)庫(kù)之間進(jìn)行分布式事務(wù)的管理,包括啟動(dòng)一個(gè)分支事務(wù)、使事務(wù)進(jìn)入準(zhǔn)備階段以及事務(wù)的實(shí)際提交回滾操作等,
例子
| session_1 in DB1 | session_2 in DB2 |
|---|---|
| 在數(shù)據(jù)庫(kù)DB1 啟動(dòng)一個(gè)分布式的一個(gè)分支事務(wù),xid 的gtrid 為 “test”,bqual為”db1”: xa start ‘test’,’db1’;分支事務(wù)插入一個(gè)數(shù)據(jù) insert into actor(…)values(…) 對(duì)分支事務(wù)1進(jìn)行第一階段提交,進(jìn)入prepare狀態(tài) :xa end ‘test’,’db1’; xa prepare ‘test’,’db1’ | 在數(shù)據(jù)庫(kù)DB2 啟動(dòng)分布式事務(wù) “test”的另外一個(gè)分支事務(wù),xid的gtrid為”test”.bqual為”db2”; xa start ‘test’,’db2’: 分支事務(wù)2在表film_actor 更新數(shù)據(jù) 最后 xa end ‘test’,’db2’ xa prepare ‘test’,’db2’ |
| xa recover 查看當(dāng)前分支事務(wù)狀態(tài) | xa recover 查看當(dāng)前分支事務(wù)狀態(tài) |
| 兩個(gè)事務(wù)進(jìn)入準(zhǔn)備提交狀態(tài),如果之前遇到任何錯(cuò)誤,都應(yīng)該回滾到所有分支,以確保事務(wù)的正確 | |
| xa commit ‘test’,’db1’ | xa commit ‘test’,’db2’ |
如果分支事務(wù)在執(zhí)行到prepare狀態(tài)是,數(shù)據(jù)庫(kù)異常,且不能再支持啟動(dòng),需要備份和binlog來(lái)回復(fù)數(shù)據(jù),
SQL Mode
在MySql中,SQLMode常用來(lái)解決下面幾類問(wèn)題
-
通過(guò)設(shè)置SQL Mode,可以完成不同嚴(yán)格程度的數(shù)據(jù)校驗(yàn),有效的保障數(shù)據(jù)準(zhǔn)確性。
-
通過(guò)設(shè)置SQL Mode,為ANSI模式,來(lái)保證大多數(shù)SQL符合標(biāo)準(zhǔn)的Sql語(yǔ)法,這樣應(yīng)用在不同數(shù)據(jù)庫(kù)之間進(jìn)行遷移時(shí),則不需要對(duì)業(yè)務(wù)SQL進(jìn)行較大的修改
-
在不同數(shù)據(jù)庫(kù)之間進(jìn)行數(shù)據(jù)遷移之前,通過(guò)設(shè)置SQL Mode可以使MySQL上的數(shù)據(jù)更方便地遷移到目標(biāo)數(shù)據(jù)庫(kù)中
查看 SQL Mode命令
select @@sql_mode
登錄后復(fù)制
插入一個(gè)出國(guó)實(shí)際定義值的大小varchar(10)
insert into value('123400000000000000000000000000000');
//查看warning內(nèi)容
show warnings
select * from t 這里對(duì)插入的數(shù)據(jù)進(jìn)行截取前10位
登錄后復(fù)制
設(shè)置SQL Mode為 嚴(yán)格模式
set session sql_mode='STRICT_TRANS_TABLES'
登錄后復(fù)制
再次插入insert into value('123400000000000000000000000000000'); 直接給出ERROR,而不是warning
SQL Mode常見(jiàn)功能
校驗(yàn)日期是合法性
set seesion sql_mode='ANSI'
insert into t values('2007-04-31')
登錄后復(fù)制
結(jié)果是 插入值變成'0000-00-00 00:00:00' 并且系統(tǒng)給出warning 而在TRADITIONAL模式下,直接提示日期非法,拒絕插入,同時(shí)Mode(x,0)也會(huì)報(bào)錯(cuò)
qidon NO_BACKSLASH_ESCAPES模式,使反斜杠成為普通字符,在導(dǎo)入數(shù)據(jù)時(shí),如果數(shù)據(jù)含有反斜杠字符,你們啟動(dòng)NO_BACKSLASH_ESCAPES模式,保證數(shù)據(jù)的正確性
啟動(dòng)PIPES_AS_CONCAT。將||視為字符串連接符,在Oracle等數(shù)據(jù)庫(kù)中,||被視為字符串的連接操作符,所以在其他數(shù)據(jù)庫(kù)中含有||操作符的sql在MySql將無(wú)法執(zhí)行,為了解決這個(gè)問(wèn)題mysql提供了PIPES_AS_CONCAT模式、
MySql分區(qū)
MySql從5.1版本開(kāi)始支持分區(qū),分區(qū)是指按照一定的規(guī)則,數(shù)據(jù)庫(kù)把一個(gè)表分解成多個(gè)更小的,更容易管理的部分。就訪問(wèn)數(shù)據(jù)庫(kù)的應(yīng)用而言,邏輯上只有一個(gè)表或一個(gè)索引,但是實(shí)際上這個(gè)表可能由數(shù)10個(gè)物理分區(qū)對(duì)象組成,每個(gè)分區(qū)都是一個(gè)獨(dú)立的對(duì)象,可以獨(dú)自處理,可以作為表的一部分進(jìn)行處理。分區(qū)對(duì)應(yīng)用而言是完全透明的,不影響應(yīng)用的業(yè)務(wù)邏輯
優(yōu)點(diǎn)
-
和單個(gè)磁盤或者文件系統(tǒng)分區(qū)相比,可以存儲(chǔ)更多數(shù)據(jù)
-
優(yōu)化查詢。在where子句中包含分區(qū)條件,可以只掃描必要的一個(gè)或多個(gè)分區(qū)來(lái)提高查詢效率;同時(shí)在涉及SUM()和COUNT()這類聚合函數(shù)的查詢時(shí),可以容易的在每個(gè)分區(qū)上并行處理,最終只需要匯總所有分區(qū)的結(jié)果
-
對(duì)于已經(jīng)過(guò)期或者不需要保存的數(shù)據(jù),可以通過(guò)刪除與這些數(shù)據(jù)有關(guān)的分區(qū)來(lái)快速刪除數(shù)據(jù)
-
跨多個(gè)磁盤來(lái)分散數(shù)據(jù)查詢,以獲得更大的查詢吞吐量
分區(qū)有利于管理非常大的表,它采用 分而治之的邏輯,分區(qū)引入分區(qū)鍵的概念,分區(qū)鍵用于根據(jù)某個(gè)區(qū)間鍵,特定值列表或者HASH函數(shù)執(zhí)行數(shù)據(jù)的聚集,讓數(shù)據(jù)根據(jù)規(guī)則分布在不同的分區(qū)中,讓一個(gè)大對(duì)象變成一些小對(duì)象
show VARIABLES like '%partition%' 查看是否支持分區(qū)
登錄后復(fù)制
Mysql支持大部分存儲(chǔ)引起如MyISAM,INNODb,Memory等存儲(chǔ)引擎,創(chuàng)建分區(qū),在5.1版本中,同一個(gè)分區(qū)表的所以分區(qū)必須使用同一個(gè)存儲(chǔ)引擎;在同要給表上,不能對(duì)一個(gè)分區(qū)使用MyISAM引擎和Innodb引擎,但是在同一個(gè)MySQL服務(wù)器服務(wù)器上,甚至同一個(gè)數(shù)據(jù)庫(kù)中,對(duì)于不同的分區(qū)表使用不同的存儲(chǔ)引擎
分區(qū)類型
-
range分區(qū):基于一個(gè)給定連續(xù)區(qū)間范圍,把數(shù)據(jù)分配到不同的分區(qū)。
-
LIST分區(qū):類似RANGE分區(qū),區(qū)別在LIST分區(qū)是基于枚舉出的值列表分區(qū),RANGE是基于給定的連續(xù)區(qū)間范圍分區(qū)
-
HASH分區(qū):基于給定的分區(qū)個(gè)數(shù),把數(shù)據(jù)分配到不同的分區(qū)
-
KEY分區(qū):類似HASH分區(qū)
在5.1版本中,RANGE分區(qū),LIST分區(qū),HASH分區(qū)要求分區(qū)鍵都是int類型,key分區(qū),可以使用其他類型(除了BLOB和TEXT類除外)作為分區(qū)鍵
分區(qū)表的主鍵/唯一鍵必須包含分區(qū)鍵,不能使用主鍵/唯一鍵,要么分區(qū)表的主鍵/唯一鍵都必須包含分區(qū)鍵,分區(qū)的名字是不區(qū)分大小寫(xiě)的
range分區(qū)
CREATE TABLE emp(
id int not null,
ename varchar(30),
hired date not null DEFAULT '1970-01-01',
separated date NOT null DEFAULT '9999-12-21',
job varchar(30) not null,
store_id int not null
)
partition by range(store_id)(
PARTITION p0 VALUES less than (10),
PARTITION p1 VALUES less than (20),
PARTITION p2 VALUES less than (30)
);
//上述的分區(qū)方案將storid,1-9分到p0區(qū),10-19分到p1區(qū),等如果插入大于30,會(huì)出現(xiàn)錯(cuò)誤,因?yàn)闆](méi)有規(guī)則保護(hù)大于30的
INSERT into emp VALUES('2322','milk','1993-12-23','1993-12-23','click',19);//可以
//Table has no partition for value 40
INSERT into emp VALUES('2322','milk','1993-12-23','1993-12-23','click',40);
添加分區(qū)
alter table emp add partition(partition p3 values less than maxvalue);
maxvalue表示最大的可能的整數(shù)值
mysql 支持在values less than 語(yǔ)句中加入表達(dá)式
比如以日期作為分區(qū)
CREATE TABLE emp(
id int not null,
ename varchar(30),
hired date not null DEFAULT '1970-01-01',
separated date NOT null DEFAULT '9999-12-21',
job varchar(30) not null,
store_id int not null
)
partition by range(year(separated ))(
PARTITION p0 VALUES less than (1995),
PARTITION p1 VALUES less than (2000),
PARTITION p2 VALUES less than (2005)
);
MySQl 5.5改進(jìn)了range分區(qū)給你,通過(guò)支持非整數(shù)分區(qū),創(chuàng)建日期分區(qū)就不需要通過(guò)函數(shù)進(jìn)行轉(zhuǎn)換
partition by range(separated )(
PARTITION p0 VALUES less than ('1996-01-01'),
PARTITION p1 VALUES less than ('2001-01-01'),
PARTITION p2 VALUES less than ('2006-01-01')
);
登錄后復(fù)制
rang分區(qū)的功能適用一下情況
- 當(dāng)需要?jiǎng)h除過(guò)期的數(shù)據(jù),只需要簡(jiǎn)單的alter table emp drop partition p0 來(lái)刪除p0 分區(qū)中的數(shù)據(jù)。對(duì)于具有上百萬(wàn)條記錄的表來(lái)說(shuō),刪除分區(qū)要比運(yùn)行一個(gè)delete語(yǔ)句有效的多
- 經(jīng)常運(yùn)行包含分區(qū)鍵的查詢,MyySql可以很快地確定只有某一個(gè)或者某些分區(qū)需要掃描,因?yàn)槠渌謪^(qū)不可能包含有符合該where字句的任何記錄。例如檢索id大于25的記錄數(shù),MySql只需要掃描p2分區(qū)即可
explain partition select count(1) from emp where store_id>=25
登錄后復(fù)制
List分區(qū)
List分區(qū)是建立離散的值列表告訴數(shù)據(jù)庫(kù)特定的值屬于哪個(gè)分區(qū),LIST分區(qū)在很多方面類似于RANGE分區(qū),區(qū)別在于LIST分區(qū)是從屬于一個(gè)枚舉列表,RANGE分區(qū)是從屬于一個(gè)連續(xù)區(qū)間值的集合
create table expenses( expense_date date not null, category int, amount decimal(10,3) )partition by list (category)( partition p0 values in(3,5), partition p1 values in(1,10), partition p2 values in(4,9), partition p3 values in(2), partition p4 values in(6) )
登錄后復(fù)制
LIST分區(qū)不存在類似于VALUES LESS THAN MAXVALUE這樣的值 在MYSQL5.5支持非整數(shù)分
Columns分區(qū)
Column分區(qū)是5.5引入的分區(qū)類型,引入Columns分區(qū)解決了MySQL5.5版本之前RANGE和LIST分區(qū)值值支持整數(shù)分區(qū),從而導(dǎo)致需要額外的函數(shù)計(jì)算得到整數(shù)值或者通過(guò)額外的轉(zhuǎn)換表來(lái)轉(zhuǎn)換為整數(shù)在分區(qū)的問(wèn)題
Column分區(qū)可以細(xì)分為RANGE Columns分區(qū)和LIST Columns分區(qū),RANGE Columns分區(qū)和LIST Columns分區(qū)都支持整數(shù),日期時(shí)間,字符串三大數(shù)據(jù)類型
對(duì)于Range分區(qū)和List分區(qū),Colums分區(qū)的亮點(diǎn)除了支持?jǐn)?shù)據(jù)類型增加之外,還支持多列分區(qū)
create table rc3(a int,b int) parition by range columns(a,b)( parition p01 values less than(0,10), parition p01 values less than(10,10), parition p01 values less than(10,20), parition p01 values less than(maxvalue,maxvalue) )
登錄后復(fù)制
Hash分區(qū)
hash分區(qū)主要是分?jǐn)?shù)熱點(diǎn)讀,確保數(shù)據(jù)在預(yù)先確定個(gè)數(shù)的分區(qū)中盡可能平均分布。對(duì)一個(gè)表執(zhí)行HASH分區(qū)時(shí),Mysql會(huì)對(duì)分區(qū)間應(yīng)用一個(gè)散列函數(shù),以確定數(shù)在n個(gè)分區(qū)中的那個(gè)分區(qū)中。
mysql支持兩種hash分區(qū),常規(guī)的hash分區(qū)和線性hash分區(qū),常規(guī)的hash使用取模算法,線性hash分區(qū)使用的一個(gè)線性的2的冪的運(yùn)算法則
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by hash(store_id)partitions 4;
登錄后復(fù)制
這里創(chuàng)建了一個(gè)常規(guī)的hash 使用 partition by hash(expr)其中expr是某列值或一個(gè)整數(shù)值的表達(dá)式返回值。 partition num 對(duì)分區(qū)類型,分區(qū)鍵,分區(qū)個(gè)數(shù)進(jìn)行定義,上述基于store_id列hash分區(qū),表被分為4個(gè)分區(qū)
我們可以計(jì)算出它被保存在哪個(gè)分區(qū)中假設(shè),假設(shè)記錄的分區(qū)編號(hào)為N,那么N=MOD(expr,num),例如emp表中有4個(gè)分區(qū),插入一個(gè)store_id為234的 mod(234,4)=2,倍保存在第二個(gè)分區(qū)
表達(dá)式‘expr’可以是MySQL中有效的任何函數(shù)或者是其他表達(dá)式,只要它們返回一個(gè)既非常數(shù)也非隨機(jī)數(shù)的整數(shù)。每當(dāng)插入更新刪除一行數(shù)據(jù),這個(gè)表達(dá)式就需要計(jì)算一次,意味著非常復(fù)雜的表達(dá)式可能會(huì)引起性能問(wèn)題
常規(guī)的HASH分區(qū)通過(guò)去模的方式去講數(shù)據(jù)平均分布在每個(gè)分區(qū)上,讓每個(gè)分區(qū)管理的數(shù)據(jù)都減少,提高了查詢的效率;可是當(dāng)我們需要增加分區(qū)或者合并分區(qū)的時(shí)候,問(wèn)題就出現(xiàn)了,假設(shè)原來(lái)是5個(gè)常規(guī)hash分區(qū),現(xiàn)在需要新增一個(gè)常規(guī)hash分區(qū),原來(lái)的去模算法是mod(expr,5)根據(jù)余數(shù)0-4分布在5個(gè)分區(qū)上,現(xiàn)在新增一個(gè)分區(qū),取模算法變?yōu)閙od(expr,6)根據(jù)余數(shù)0-5分區(qū)在6個(gè)分區(qū)中,原來(lái)5個(gè)分區(qū)的數(shù)據(jù)大部分都需要通過(guò)重新計(jì)算重新分區(qū),常規(guī)的hash在分區(qū)管理上帶來(lái)的代價(jià)太大了。不適合靈活變動(dòng)分區(qū)的需求,Mysql提供了線性hash分區(qū)
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by linear hash(store_id)partitions 4; 計(jì)算編號(hào)為n的分區(qū) 首先找到下一個(gè)大于等于num的2的冪,這個(gè)值設(shè)為v,v的計(jì)算公司 v=power(2,ceiling(log(2,num))) =power(2,ceiling(log(2,4))) =power(2,ceiling(2)) =power(2,2) =4 其次設(shè)置n=f(column_list)&(v-1),現(xiàn)在計(jì)算store_id=234對(duì)應(yīng)的n值 n=f(column_list)&(4-1) =234&(4-1) =2 當(dāng)n》=num設(shè)置n=n&(v-1) 對(duì)于store_id=234由于n=2《4,所以直接判斷這個(gè)會(huì)被存放到第二分區(qū)
登錄后復(fù)制
線性hash分區(qū)的優(yōu)點(diǎn)在于,在分區(qū)維護(hù)上(包含增加,刪除,合并,拆分分區(qū))時(shí),Mysql能夠處理得更加迅速;缺點(diǎn)是對(duì)比常規(guī)hash分區(qū)的時(shí)候,線性hash分布不太均衡
key分區(qū)
按照key分區(qū)進(jìn)行分區(qū)非常類似于按照hash進(jìn)行分區(qū),只不過(guò)hash分區(qū)允許使用用戶自定義的表達(dá)式,而KEY分區(qū)不行使用用戶自定義的表達(dá)式,需要使用MySQl服務(wù)器提供的hash函數(shù);同時(shí)hash分區(qū)只支持整數(shù)分區(qū),而key分區(qū)支持除了blob
or text類型外其他類型的列作為分區(qū)鍵
create table emp(id int not null.ename varchar(30),hired date not null default '1907-01-01',sparated date null null default '8888-12-31',job varchar(30) not null,store_id int not null) partition by key (job)partitions 4; 如果不知道分區(qū)鍵,默認(rèn)為主鍵,沒(méi)有主鍵會(huì)選擇非空唯一鍵作為分區(qū)鍵
登錄后復(fù)制
子分區(qū)
子分區(qū)是分區(qū)表對(duì)每個(gè)分區(qū)的再次分割。又被稱為復(fù)合分區(qū),mysql5.1開(kāi)始支持對(duì)已經(jīng)通過(guò)range或者list分區(qū)了的表在進(jìn)行子分區(qū)
create table ts(id int,purchased date) partition by range(year(purchased)) subpartition by hash(to_days(purchased))subpartitions 2(partition p0 values less than (1900),partition p0 values less than (2000),partition p0 values less than (maxvalue))
登錄后復(fù)制
在分區(qū)中的null值
在mysql不禁止分區(qū)鍵上使用null,分區(qū)鍵可能是一個(gè)字段或者一個(gè)用戶定義的表達(dá)式,一般情況下,mysql的分區(qū)把null當(dāng)做零值,或者一個(gè)最小值處理
分區(qū)管理
刪除分區(qū) alter table emp_date drop partition p2; 增加分區(qū) alter table emp_date add partition(partition p5 value less than(2025)) 拆分p3分區(qū),分為p2和p3分區(qū) 分區(qū) alter table emp_date reorganize partition p3 into(partition p2 values less than(2005),parition p3 values less than (2015)); 合并分區(qū) alter table emp_date reogranize partition p1,p2,p3 into(partition p1 values less than (2015)) 重新定義list分區(qū)時(shí),只能重新定義相鄰的分區(qū),不能跳過(guò)list分區(qū)進(jìn)行重新定義
登錄后復(fù)制
hash&key管理
不能以range和list分區(qū)表刪除分區(qū)的方式,而是跳過(guò)alter table coalesce partition 來(lái)合并或分區(qū) 以原先4個(gè)分區(qū)為例 alter table emp coalesce partition 2 //減少分區(qū)到2個(gè) alter table emp coalesc partition 8 //不能增加分區(qū) 要增加分區(qū) alter table emp add partition partitions 8;
登錄后復(fù)制
相關(guān)推薦:
關(guān)于mysql 基礎(chǔ)知識(shí)的總結(jié)
PHP 和 MySQL 基礎(chǔ)教程(一)
PHP 和 MySQL 基礎(chǔ)教程(二)
PHP 和 MySQL 基礎(chǔ)教程(三)
PHP 和 MySQL 基礎(chǔ)教程(四)
mysql手冊(cè)教程:http://www.php.cn/course/37.html
mysql視頻教程:http://www.php.cn/course/list/51.html
以上就是mysql基礎(chǔ)知識(shí)(mysql新手教程)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注風(fēng)君子博客其它相關(guān)文章!
總結(jié)
以上是生活随笔為你收集整理的mysql基础知识(mysql新手教程)(使用方法简单教程)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql group 分页_【MySQ
- 下一篇: MySQL字符串函数:字符串截取总结