1、InnoDB存儲引擎
創(chuàng)新互聯(lián)公司服務(wù)項目包括湖里網(wǎng)站建設(shè)、湖里網(wǎng)站制作、湖里網(wǎng)頁制作以及湖里網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,湖里網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到湖里省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
Mysql版本=5.5 默認(rèn)的存儲引擎,MySQL推薦使用的存儲引擎。支持事務(wù),行級鎖定,外鍵約束。事務(wù)安全型存儲引擎。更加注重數(shù)據(jù)的完整性和安全性。
存儲格式 : 數(shù)據(jù),索引集中存儲,存儲于同一個表空間文件中。
InnoDB的行鎖模式及其加鎖方法: InnoDB中有以下兩種類型的行鎖:共享鎖(讀鎖: 允許事務(wù)對一條行數(shù)據(jù)進(jìn)行讀?。┖?互斥鎖(寫鎖: 允許事務(wù)對一條行數(shù)據(jù)進(jìn)行刪除或更新), 對于update,insert,delete語句,InnoDB會自動給設(shè)計的數(shù)據(jù)集加互斥鎖,對于普通的select語句,InnoDB不會加任何鎖。
InnoDB行鎖的實現(xiàn)方式: InnoDB行鎖是通過給索引上的索引項加鎖來實現(xiàn)的,如果沒有索引,InnoDB將通過隱藏的聚簇索引來對記錄加鎖。InnoDB這種行鎖實現(xiàn)特點意味著:如果不通過索引條件檢索數(shù)據(jù),那么InnoDB將對表中的所有記錄加鎖,實際效果跟表鎖一樣。
(1)在不通過索引條件查詢時,InnoDB會鎖定表中的所有記錄。
(2)Mysql的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果使用相同的索引鍵,是會出現(xiàn)沖突的。
(3)當(dāng)表有多個索引的時候,不同的事務(wù)可以使用不同的索引鎖定不同的行,但都是通過行鎖來對數(shù)據(jù)加鎖。
優(yōu)點:
1、支持事務(wù)處理、ACID事務(wù)特性;
2、實現(xiàn)了SQL標(biāo)準(zhǔn)的四種隔離級別( 原子性( Atomicity )、一致性( Consistency )、隔離性(Isolation )和持續(xù)性(Durability ));
3、支持行級鎖和外鍵約束;
4、可以利用事務(wù)日志進(jìn)行數(shù)據(jù)恢復(fù)。
5、鎖級別為行鎖,行鎖優(yōu)點是適用于高并發(fā)的頻繁表修改,高并發(fā)是性能優(yōu)于 MyISAM。缺點是系統(tǒng)消耗較大。
6、索引不僅緩存自身,也緩存數(shù)據(jù),相比 MyISAM 需要更大的內(nèi)存。
缺點:
因為它沒有保存表的行數(shù),當(dāng)使用COUNT統(tǒng)計時會掃描全表。
使用場景:
(1)可靠性要求比較高,或者要求事務(wù);(2)表更新和查詢都相當(dāng)?shù)念l繁,并且表鎖定的機(jī)會比較大的情況。
2、 MyISAM存儲引擎
MySQL= 5.5 MySQL默認(rèn)的存儲引擎。ISAM:Indexed Sequential Access Method(索引順序存取方法)的縮寫,是一種文件系統(tǒng)。擅長與處理,高速讀與寫。
功能:
(1)支持?jǐn)?shù)據(jù)壓縮存儲,但壓縮后的表變成了只讀表,不可寫;如果需要更新數(shù)據(jù),則需要先解壓后更新。
(2)支持表級鎖定,不支持高并發(fā);
(3)支持并發(fā)插入。寫操作中的插入操作,不會阻塞讀操作(其他操作);
優(yōu)點:
1.高性能讀??;
2.因為它保存了表的行數(shù),當(dāng)使用COUNT統(tǒng)計時不會掃描全表;
缺點:
1、鎖級別為表鎖,表鎖優(yōu)點是開銷小,加鎖快;缺點是鎖粒度大,發(fā)生鎖沖動概率較高,容納并發(fā)能力低,這個引擎適合查詢?yōu)橹鞯臉I(yè)務(wù)。
2、此引擎不支持事務(wù),也不支持外鍵。
3、INSERT和UPDATE操作需要鎖定整個表;
使用場景:
(1)做很多count 的計算;(2)插入不頻繁,查詢非常頻繁;(3)沒有事務(wù)。
InnoDB和MyISAM一些細(xì)節(jié)上的差別:
1、InnoDB不支持FULLTEXT類型的索引,MySQL5.6之后已經(jīng)支持(實驗性)。
2、InnoDB中不保存表的 具體行數(shù),也就是說,執(zhí)行select count() from table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數(shù)即可。注意的是,當(dāng)count()語句包含 where條件時,兩種表的操作是一樣的。
3、對于AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯(lián)合索引。
4、DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5、LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導(dǎo)入數(shù)據(jù)后再改成InnoDB表,但是對于使用的額外的InnoDB特性(例如外鍵)的表不適用。
6、另外,InnoDB表的行鎖也不是絕對的,如果在執(zhí)行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表。
1.索引概述
利用關(guān)鍵字,就是記錄的部分?jǐn)?shù)據(jù)(某個字段,某些字段,某個字段的一部分),建立與記錄位置的對應(yīng)關(guān)系,就是索引。索引的關(guān)鍵字一定是排序的。索引本質(zhì)上是表字段的有序子集,它是提高查詢速度最有效的方法。一個沒有建立任何索引的表,就相當(dāng)于一本沒有目錄的書,在每次查詢時就會進(jìn)行全表掃描,這樣會導(dǎo)致查詢效率極低、速度也極慢。如果建立索引,那么就好比一本添加的目錄,通過目錄的指引,迅速翻閱到指定的章節(jié),提升的查詢性能,節(jié)約了查詢資源。
2.索引種類
從索引的定義方式和用途中來看:主鍵索引,唯一索引,普通索引,全文索引。
無論任何類型,都是通過建立關(guān)鍵字與位置的對應(yīng)關(guān)系來實現(xiàn)的。索引是通過關(guān)鍵字找對應(yīng)的記錄的地址。
以上類型的差異:對索引關(guān)鍵字的要求不同。
關(guān)鍵字:記錄的部分?jǐn)?shù)據(jù)(某個字段,某些字段,某個字段的一部分)。
普通索引,index:對關(guān)鍵字沒有要求。
唯一索引,unique index:要求關(guān)鍵字不能重復(fù)。同時增加唯一約束。
主鍵索引,primary key:要求關(guān)鍵字不能重復(fù),也不能為NULL。同時增加主鍵約束。
全文索引,fulltext key:關(guān)鍵字的來源不是所有字段的數(shù)據(jù),而是從字段中提取的特別關(guān)鍵詞。
PS:這里主鍵索引和唯一索引的區(qū)別在于:主鍵索引不能為空值,唯一索引允許空值;主鍵索引在一張表內(nèi)只能創(chuàng)建一個,唯一索引可以創(chuàng)建多個。主鍵索引肯定是唯一索引,但唯一索引不一定是主鍵索引。
3.索引原則
如果索引不遵循使用原則,則可能導(dǎo)致索引無效。
(1)列獨立
如果需要某個字段上使用索引,則需要在字段參與的表達(dá)中,保證字段獨立在一側(cè)。否則索引不會用到索引, 例如這條sql就不會用到索引:select * from A where id+1=10;
(2)左原則
Like:匹配模式必須要左邊確定不能以通配符開頭。例如:select * from A where name like '%小明%' ,不會用到索引,而select * from A where name like '小明%' 就可以用到索引(name字段有建立索引),如果業(yè)務(wù)上需要用到'%小明%'這種方式,有兩種方法:1.可以考慮全文索引,但mysql的全文索引不支持中文;2.只查詢索引列或主鍵列,例如:select name from A where name like '%小明%' 或 select id from A where name like '%小明%' 或 select id,name from A where name like '%小明%' 這三種情況都會用到name的索引;
復(fù)合索引:一個索引關(guān)聯(lián)多個字段,僅僅針對左邊字段有效果,添加復(fù)合索引時,第一個字段很重要,只有包含第一個字段作為查詢條件的情況才會使用復(fù)合索引(必須用到建索引時選擇的第一個字段作為查詢條件,其他字段的順序無關(guān)),而且查詢條件只能出現(xiàn)and拼接,不能用or,否則則無法使用索引.
(3)OR的使用
必須要保證 OR 兩端的條件都存在可以用的索引,該查詢才可以使用索引。
(4)MySQL智能選擇
即使?jié)M足了上面說原則,MySQL也能棄用索引,例如:select * from A where id 1;這里棄用索引的主要原因:查詢即使使用索引,會導(dǎo)致出現(xiàn)大量的隨機(jī)IO,相對于從數(shù)據(jù)記錄的第一條遍歷到最后一條的順序IO開銷,還要大。
4.索引的使用場景
(1)索引檢索:檢索數(shù)據(jù)時使用索引。
(2)索引排序: 如果order by 排序需要的字段上存在索引,則可能使用到索引。
(3)索引覆蓋: 索引擁有的關(guān)鍵字內(nèi)容,覆蓋了查詢所需要的全部數(shù)據(jù),此時,就不需要在數(shù)據(jù)區(qū)獲取數(shù)據(jù),僅僅在索引區(qū)即可。覆蓋就是直接在索引區(qū)獲取內(nèi)容,而不需要在數(shù)據(jù)區(qū)獲取。例如: select name from A where name like '小明%';
建立索引索引時,不能僅僅考慮where檢索,同時考慮其他的使用場景。(在所有的where字段上增加索引,就是不合理的)
5.前綴索引
前綴索引是建立索引關(guān)鍵字一種方案。通常會使用字段的整體作為索引關(guān)鍵字。有時,即使使用字段前部分?jǐn)?shù)據(jù),也可以去識別某些記錄。就比如一個班級里,我要找王xx,假如姓王的只有1個人,那么就可以建一個關(guān)鍵字為'王'的前綴索引。語法:Index `index_name` (`index_field`(N))使用index_name前N個字符建立的索引。
6.索引失效
(1) 應(yīng)盡量避免在 where 子句中使用 != 或 操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描;
(2) 應(yīng)盡量避免在 where 子句中使用 or 來連接條件,如果一個字段有索引,一個字段沒有索引,將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;
(3) 應(yīng)盡量避免在 where 子句中對字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;
(4)應(yīng)盡量避免在 where 子句中對字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;如select id from t where num/2 = 100;
(5) 應(yīng)盡量避免在where子句中對字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;如:select id from t where substring(name,1,3) = ’abc’ ;
(6)應(yīng)盡量避免在where子句中對字段進(jìn)行類型轉(zhuǎn)換,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描; 如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號引用起來,如select id from t where id = 1;如果id字段在表設(shè)計中是varchar類型,那么即使id列上存的是數(shù)字,在查詢時也一定要用varchar去匹配,sql應(yīng)改為select id from t where id = '1';
(7)應(yīng)盡量避免在where子句中單獨引用復(fù)合索引里非第一位置的索引;
join 的兩種算法:BNL 和 NLJ
NLJ(Nested Loop Join)嵌套循環(huán)算法;以如下 SQL 為例:
select * from t1 join t2 on t1.a=t2.a
SQL 執(zhí)行時內(nèi)部流程是這樣的:
1. 先從 t1(假設(shè)這里 t1 被選為驅(qū)動表)中取出一行數(shù)據(jù) X;
2. 從 X 中取出關(guān)聯(lián)字段 a 值,去 t2 中進(jìn)行查找,滿足條件的行取出;
3. 重復(fù)1、2步驟,直到表 t1 最后一行循環(huán)結(jié)束。
這就是一個嵌套循環(huán)的過程,如果在被驅(qū)動表上查找數(shù)據(jù)時可以使用索引,總的對比計算次數(shù)等于驅(qū)動表滿足 where 條件的行數(shù)。假設(shè)這里 t1、t2都是1萬行,則只需要 1萬次計算,這里用到的是Index Nested-Loops Join(INLJ,基于索引的嵌套循環(huán)聯(lián)接)。
如果 t1、t2 的 a 字段都沒有索引,還按照上述的嵌套循環(huán)流程查找數(shù)據(jù)呢?每次在被驅(qū)動表上查找數(shù)據(jù)時都是一次全表掃描,要做1萬次全表掃描,掃描行數(shù)等于 1萬+1萬*1萬,這個效率很低,如果表行數(shù)更多,掃描行數(shù)動輒幾百億,所以優(yōu)化器肯定不會使用這樣的算法,而是選擇 BNL 算法;
BNLJ(Block Nested Loop Join)塊嵌套循環(huán)算法;
1. 把 t1 表(假設(shè)這里 t1 被選為驅(qū)動表)滿足條件的數(shù)據(jù)全部取出放到線程的 join buffer 中;
2. 每次取 t2 表一行數(shù)據(jù),去 joinbuffer 中進(jìn)行查找,滿足條件的行取出,直到表 t2 最后一行循環(huán)結(jié)束。
這個算法下,執(zhí)行計劃的 Extra 中會出現(xiàn) Using join buffer(Block Nested Loop),t1、t2 都做了一次全表掃描,總的掃描行數(shù)等于 1萬+1萬。但是由于 joinbuffer 維護(hù)的是一個無序數(shù)組,每次在 joinbuffer 中查找都要遍歷所有行,總的內(nèi)存計算次數(shù)等于1萬*1萬。另外如果 joinbuffer 不夠大放不下驅(qū)動表的數(shù)據(jù),則要分多次執(zhí)行上面的流程,會導(dǎo)致被驅(qū)動表也做多次全表掃描。
BNLJ相對于NLJ的優(yōu)點在于,驅(qū)動層可以先將部分?jǐn)?shù)據(jù)加載進(jìn)buffer,這種方法的直接影響就是將大大減少內(nèi)層循環(huán)的次數(shù),提高join的效率。
例如:
如果內(nèi)層循環(huán)有100條記錄,外層循環(huán)也有100條記錄,這樣的話,每次外層循環(huán)先將10條記錄放到buffer中,內(nèi)層循環(huán)的100條記錄每條與這個buffer中的10條記錄進(jìn)行匹配,只需要匹配內(nèi)層循環(huán)總記錄數(shù)次即可結(jié)束一次循環(huán)(在這里,即只需要匹配100次即可結(jié)束),然后將匹配成功的記錄連接后放入結(jié)果集中,接著,外層循環(huán)繼續(xù)向buffer中放入10條記錄,同理進(jìn)行匹配,并將成功的記錄連接后放入結(jié)果集。后續(xù)循環(huán)以此類推,直到循環(huán)結(jié)束,將結(jié)果集發(fā)給client為止。
可以發(fā)現(xiàn),若用NLJ,則需要100 * 100次才可結(jié)束,BNLJ則需要100 / block_size * 100 = 10 * 100次就可結(jié)束,大大減少了循環(huán)次數(shù)。
JOIN 按照功能大致分為如下三類:
JOIN、STRAIGHT_JOIN、INNER JOIN(內(nèi)連接,或等值連接):取得兩個表中存在連接匹配關(guān)系的記錄。
LEFT JOIN(左連接):取得左表(table1)完全記錄,即是右表(table2)并無對應(yīng)匹配記錄。
RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)并無匹配對應(yīng)記錄。
注意:mysql不支持Full join,不過可以通過UNION 關(guān)鍵字來合并 LEFT JOIN 與 RIGHT JOIN來模擬FULL join。
mysql 多表連接查詢方式,因為mysql只支持NLJ算法,所以如果是小表驅(qū)動大表則效率更高;反之則效率下降;因此mysql對內(nèi)連接或等值連接的方式做了一個優(yōu)化,會去判斷join表的數(shù)據(jù)行大小,然后取數(shù)據(jù)行小的表為驅(qū)動表。
INNER JOIN、JOIN、WHERE等值連接和STRAIGHT_JOIN都能表示內(nèi)連接,那平時如何選擇呢?一般情況下用INNER JOIN、JOIN或者WHERE等值連接,因為MySQL 會按照"小表驅(qū)動大表的策略"進(jìn)行優(yōu)化。當(dāng)出現(xiàn)需要排序時,才考慮用STRAIGHT_JOIN指定某張表為驅(qū)動表。
兩表JOIN優(yōu)化
a.當(dāng)無order by條件時,根據(jù)實際情況,使用left/right/inner join即可,根據(jù)explain優(yōu)化 ;
b.當(dāng)有order by條件時,如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解釋語句;
1)如果第一行的驅(qū)動表為a,則效率會非常高,無需優(yōu)化;
2)否則,因為只能對驅(qū)動表字段直接排序的緣故,會出現(xiàn)using temporary,所以此時需要使用STRAIGHT_JOIN明確a為驅(qū)動表,來達(dá)到使用a.col上index的優(yōu)化目的;或者使用left join且Where條件中不含b的過濾條件,此時的結(jié)果集為a的全集,而STRAIGHT_JOIN為inner join且使用a作為驅(qū)動表。注:使用STRAIGHT_JOIN雖然不會using temporary,但也不是一定就能提高效率,如果a表數(shù)據(jù)遠(yuǎn)遠(yuǎn)超過b表,那么有可能使用STRAIGHT_JOIN時比原來的sql效率更低,所以怎么使用STRAIGHT_JOIN,還是要視情況而定。
在使用left join(或right join)時,應(yīng)該清楚的知道以下幾點:
(1). on與 where的執(zhí)行順序
ON 條件(“A LEFT JOIN B ON 條件表達(dá)式”中的ON)用來決定如何從 B 表中檢索數(shù)據(jù)行。如果 B 表中沒有任何一行數(shù)據(jù)匹配 ON 的條件,將會額外生成一行所有列為 NULL 的數(shù)據(jù),在匹配階段 WHERE 子句的條件都不會被使用。僅在匹配階段完成以后,WHERE 子句條件才會被使用。它將從匹配階段產(chǎn)生的數(shù)據(jù)中檢索過濾。
所以我們要注意:在使用Left (right) join的時候,一定要在先給出盡可能多的匹配滿足條件,減少Where的執(zhí)行。
(2).注意ON 子句和 WHERE 子句的不同
即使右表的數(shù)據(jù)不滿足ON后面的條件,也會在結(jié)果集拼接一條為NULL的數(shù)據(jù)行,但WHERE后面的條件不一樣,右表不滿足WHERE的條件,左表關(guān)聯(lián)的數(shù)據(jù)也會被過濾掉。
(3).盡量避免子查詢,而用join
往往性能這玩意兒,更多時候體現(xiàn)在數(shù)據(jù)量比較大的時候,此時,我們應(yīng)該避免復(fù)雜的子查詢。
(1)in 和 not in 要慎用,如:select id from t where num in(1,2,3)對于連續(xù)的數(shù)值,能用 between 就不要用 in:select id from t where num between 1 and 3很多時候用 exists 代替 in 是一個好的選擇:select num from a where num in(select num from b)用下面的語句替換:select num from a where exists(select 1 from b where num=a.num)
(2)Update 語句,如果只更改1、2個字段,不要Update全部字段,否則頻繁調(diào)用會引起明顯的性能消耗,同時帶來大量日志。
(3)join語句,MySQL里面的join是用小表去驅(qū)動大表,而由于MySQL join實現(xiàn)的原理就是做循環(huán),比如left join就是對左邊的數(shù)據(jù)進(jìn)行循環(huán)去驅(qū)動右邊的表,左邊有m條記錄匹配,右邊有n條記錄那么就是做m次循環(huán),每次掃描n行數(shù)據(jù),總掃面行數(shù)是m*n行數(shù)據(jù)。左邊返回的結(jié)果集的大小就決定了循環(huán)的次數(shù),故單純的用小表去驅(qū)動大表不一定的正確的,小表的結(jié)果集可能也大于大表的結(jié)果集,所以寫join的時候盡可能的先估計兩張表的可能結(jié)果集,用小結(jié)果集去驅(qū)動大結(jié)果集.值得注意的是在使用left/right join的時候,從表的條件應(yīng)寫在on之后,主表應(yīng)寫在where之后.否則MySQL會當(dāng)作普通的連表查詢;
(4)select count(*) from table;這樣不帶任何條件的count會引起全表掃描,并且沒有任何業(yè)務(wù)意義,是一定要杜絕的;
(5)select * from t 這種語句要盡量避免,使用具體的字段代替*,更有實際意義,需要什么字段就返回什么字段;
(6)數(shù)據(jù)量大的情況下,limit要慎用,因為使用limit m,n方式分頁時,mysql每次都是查詢前m+n條,然后舍棄前m條,所以m越大,偏移量越大,性能就越差。比如:select * from A limit 1000000,20這鐘,查詢效率就會非常低,當(dāng)分頁的頁數(shù)大于一定的數(shù)量之后,就可以換種方式來分頁:select * from A a join (select id from A limit 1000000,20) b on a.id=b.id;
先簡單介紹一下事務(wù)吧!事務(wù)是DBMS得執(zhí)行單位。它由有限得數(shù)據(jù)庫操作序列組成得。但不是任意得數(shù)據(jù)庫操作序列都能成為事務(wù)。一般來說,事務(wù)是必須滿足4個條件(ACID)
原子性(Autmic):事務(wù)在執(zhí)行性,要做到“要么不做,要么全做!”,就是說不允許事務(wù)部分得執(zhí)行。即使因為故障而使事務(wù)不能完成,在rollback時也要消除對數(shù)據(jù)庫得影響!
一致性(Consistency):事務(wù)得操作應(yīng)該使使數(shù)據(jù)庫從一個一致狀態(tài)轉(zhuǎn)變倒另一個一致得狀態(tài)!就拿網(wǎng)上購物來說吧,你只有即讓商品出庫,又讓商品進(jìn)入顧客得購物籃才能構(gòu)成事務(wù)!
隔離性(Isolation):如果多個事務(wù)并發(fā)執(zhí)行,應(yīng)象各個事務(wù)獨立執(zhí)行一樣!
持久性(Durability):一個成功執(zhí)行得事務(wù)對數(shù)據(jù)庫得作用是持久得,即使數(shù)據(jù)庫應(yīng)故障出錯,也應(yīng)該能夠恢復(fù)!
MYSQL的事務(wù)處理主要有兩種方法。
1、用begin,rollback,commit來實現(xiàn)
begin
開始一個事務(wù)
rollback 事務(wù)回滾
commit 事務(wù)確認(rèn)
2、直接用set來改變mysql的自動提交模式
MYSQL默認(rèn)是自動提交的,也就是你提交一個QUERY,它就直接執(zhí)行!我們可以通過
set autocommit=0
禁止自動提交
set autocommit=1 開啟自動提交
來實現(xiàn)事務(wù)的處理。
但注意當(dāng)你用 set
autocommit=0
的時候,你以后所有的SQL都將做為事務(wù)處理,直到你用commit確認(rèn)或rollback結(jié)束,注意當(dāng)你結(jié)束這個事務(wù)的同時也開啟了個新的事務(wù)!按第一種方法只將當(dāng)前的作為一個事務(wù)!
個人推薦使用第一種方法!
MYSQL中只有INNODB和BDB類型的數(shù)據(jù)表才能支持事務(wù)處理!其他的類型是不支持的?。ㄇ杏洠。?/p>
下次有空說下MYSQL的數(shù)據(jù)表的鎖定和解鎖!
MYSQL5.0 WINXP下測試通過~ ^_^
mysql use test;
Database
changed
mysql CREATE TABLE `dbtest`(
- 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
*******************************************************************************************************************
[PHP]
function
Tran( $sql ) {
$judge = 1;
mysql_query('begin');
foreach ($sql as $v) {
if
( !mysql_query($v) ) {
$judge =
0;
}
}
if ($judge == 0)
{
mysql_query('rollback');
return
false;
}
elseif ($judge == 1) {
mysql_query('commit');
return true;
}
}
[/PHP]
************************************************
?php
$handler=mysql_connect("localhost","root","");
mysql_select_db("task");
mysql_query("SET
AUTOCOMMIT=0");//設(shè)置為不自動提交,因為MYSQL默認(rèn)立即執(zhí)行
mysql_query("BEGIN");//開始事務(wù)定義
if(!mysql_query("insert
into trans (id)
values('2')"))
{
mysql_query("ROOLBACK");//判斷當(dāng)執(zhí)行失敗時回滾
}
if(!mysql_query("insert
into trans (id)
values('4')"))
{
mysql_query("ROOLBACK");//判斷執(zhí)行失敗回滾
}
mysql_query("COMMIT");//執(zhí)行事務(wù)
mysql_close($handler);
?
引自:
mssql和mysql的區(qū)別
mssql 是微軟的那個 SQL Server,運行于windows 2000,2003等平臺
mysql 是個開源的數(shù)據(jù)庫Server,可運行在windows平臺、unix\\linux平臺,其標(biāo)準(zhǔn)版是免費的,可以到 看看
asp\\php只是一種解釋語言,不一定mssql不能用php,也不一定mysql非得用php,只不過asp-mssql,php-mysql是一種常用的組合
SQL數(shù)據(jù)庫完全手冊_1
SQL是Structured Quevy Language(結(jié)構(gòu)化查詢語言)的縮寫。SQL是專為數(shù)據(jù)庫而建立的操作命令集,是一種功能齊全的數(shù)據(jù)庫語言。在使用它時,只需要發(fā)出“做什么”的命令,“怎么做”是不用使用者考慮的。SQL功能強(qiáng)大、簡單易學(xué)、使用方便,已經(jīng)成為了數(shù)據(jù)庫操作的基礎(chǔ),并且現(xiàn)在幾乎所有的數(shù)據(jù)庫均支持SQL。
##1 二、SQL數(shù)據(jù)庫數(shù)據(jù)體系結(jié)構(gòu)
SQL數(shù)據(jù)庫的數(shù)據(jù)體系結(jié)構(gòu)基本上是***結(jié)構(gòu),但使用術(shù)語與傳統(tǒng)關(guān)系模型術(shù)語不同。在SQL中,關(guān)系模式(模式)稱為“基本表”(base table);存儲模式(內(nèi)模式)稱為“存儲文件”(stored file);子模式(外模式)稱為“視圖”(view);元組稱為“行”(row);屬性稱為“列”(column)。名稱對稱如^00100009a^:
##1 三、SQL語言的組成
在正式學(xué)習(xí)SQL語言之前,首先讓我們對SQL語言有一個基本認(rèn)識,介紹一下SQL語言的組成:
1.一個SQL數(shù)據(jù)庫是表(Table)的集合,它由一個或多個SQL模式定義。
2.一個SQL表由行集構(gòu)成,一行是列的序列(集合),每列與行對應(yīng)一個數(shù)據(jù)項。
3.一個表或者是一個基本表或者是一個視圖?;颈硎菍嶋H存儲在數(shù)據(jù)庫的表,而視圖是由若干基本表或其他視圖構(gòu)成的表的定義。
4.一個基本表可以跨一個或多個存儲文件,一個存儲文件也可存放一個或多個基本表。每個存儲文件與外部存儲上一個物理文件對應(yīng)。
5.用戶可以用SQL語句對視圖和基本表進(jìn)行查詢等操作。在用戶角度來看,視圖和基本表是一樣的,沒有區(qū)別,都是關(guān)系(表格)。
6.SQL用戶可以是應(yīng)用程序,也可以是終端用戶。SQL語句可嵌入在宿主語言的程序中使用,宿主語言有FORTRAN,COBOL,PASCAL,PL/I,C和Ada語言等。SQL用戶也能作為獨立的用戶接口,供交互環(huán)境下的終端用戶使用。
##1 四、對數(shù)據(jù)庫進(jìn)行操作
SQL包括了所有對數(shù)據(jù)庫的操作,主要是由4個部分組成:
1.數(shù)據(jù)定義:這一部分又稱為“SQL DDL”,定義數(shù)據(jù)庫的邏輯結(jié)構(gòu),包括定義數(shù)據(jù)庫、基本表、視圖和索引4部分。
2.數(shù)據(jù)操縱:這一部分又稱為“SQL DML”,其中包括數(shù)據(jù)查詢和數(shù)據(jù)更新兩大類操作,其中數(shù)據(jù)更新又包括插入、刪除和更新三種操作。
3.數(shù)據(jù)控制:對用戶訪問數(shù)據(jù)的控制有基本表和視圖的授權(quán)、完整性規(guī)則的描述,事務(wù)控制語句等。
4.嵌入式SQL語言的使用規(guī)定:規(guī)定SQL語句在宿主語言的程序中使用的規(guī)則。
下面我們將分別介紹:
##2 (一)數(shù)據(jù)定義
SQL數(shù)據(jù)定義功能包括定義數(shù)據(jù)庫、基本表、索引和視圖。
首先,讓我們了解一下SQL所提供的基本數(shù)據(jù)類型:(如^00100009b^)
1.數(shù)據(jù)庫的建立與刪除
(1)建立數(shù)據(jù)庫:數(shù)據(jù)庫是一個包括了多個基本表的數(shù)據(jù)集,其語句格式為:
CREATE DATABASE 數(shù)據(jù)庫名 〔其它參數(shù)〕
其中,數(shù)據(jù)庫名在系統(tǒng)中必須是唯一的,不能重復(fù),不然將導(dǎo)致數(shù)據(jù)存取失誤。〔其它參數(shù)〕因具體數(shù)據(jù)庫實現(xiàn)系統(tǒng)不同而異。
例:要建立項目管理數(shù)據(jù)庫(xmmanage),其語句應(yīng)為:
CREATE DATABASE xmmanage
(2) 數(shù)據(jù)庫的刪除:將數(shù)據(jù)庫及其全部內(nèi)容從系統(tǒng)中刪除。
其語句格式為:DROP DATABASE 數(shù)據(jù)庫名
例:刪除項目管理數(shù)據(jù)庫(xmmanage),其語句應(yīng)為:
DROP DATABASE xmmanage
2.基本表的定義及變更
本身獨立存在的表稱為基本表,在SQL語言中一個關(guān)系唯一對應(yīng)一個基本表?;颈淼亩x指建立基本關(guān)系模式,而變更則是指對數(shù)據(jù)庫中已存在的基本表進(jìn)行刪除與修改。
(1)基本表的定義:基本表是非導(dǎo)出關(guān)系,其定義涉及表名、列名及數(shù)據(jù)類型等,其語句格式為:
CREATE TABLE〔數(shù)據(jù)庫名.〕表名
(列名 數(shù)據(jù)類型 〔缺省值〕 〔NOT NULL / NULL〕
〔,列名 數(shù)據(jù)類型 〔缺省值〕 〔NOT NULL / NULL〕〕......
〔,UNIQUE (列名〔,列名〕......)〕
〔,PRIMARY KEY(列名)〕
〔,F(xiàn)OREIGN KEY(列名〔,列名〕......)REFERENCE 表名(列名〔,列名〕......)〕
〔,CHECK(條件)〕 〔其它參數(shù)〕)
其中,〈數(shù)據(jù)庫名〉.〕指出將新建立的表存放于該數(shù)據(jù)庫中;
新建的表由兩部分組成:其一為表和一組列名,其二是實際存放的數(shù)據(jù)(即可在定義表的同時,直接存放數(shù)據(jù)到表中);
列名為用戶自定義的易于理解的名稱,列名中不能使用空格;
數(shù)據(jù)類型為上面所介紹的幾種標(biāo)準(zhǔn)數(shù)據(jù)類型;
〔NOT NULL/NULL〕指出該列是否允許存放空值,SQL語言支持空值的概念,所謂空值是“不知道”或“無意義”的值,值得注意的是數(shù)據(jù)“0”和空格都不是空值,系統(tǒng)一般默認(rèn)允許為空值,所以當(dāng)不允許為空值時,必須明確使用NOT NULL;
〔,UNIQUE〕將列按照其規(guī)定的順序進(jìn)行排列,如不指定排列順序,則按列的定義順序排列;
〔PRIMARY KEY〕用于指定表的主鍵(即關(guān)系中的主屬性),實體完整性約束條件規(guī)定:主鍵必須是唯一的,非空的;
〔,F(xiàn)OREIGN KEY (列名〔,列名〕......) REFERENCE表名(列名〔,列名〕......)〕是用于指定外鍵參照完整性約束條件,F(xiàn)OREIGN KEY指定相關(guān)列為外鍵,其參照對象為另外一個表的指定列,即使用REFERENCE引入的外表中的列,當(dāng)不指定外表列名時,系統(tǒng)將默認(rèn)其列名與參照鍵的列名相同,要注意的是:使用外鍵時必須使用參照,另外數(shù)據(jù)的外鍵參照完整性約束條件規(guī)定:外鍵的值要么與相對應(yīng)的主鍵相同,要么為空值(具體由實現(xiàn)系統(tǒng)不同而異)
〔,CHECK〕用于使用指定條件對存入表中的數(shù)據(jù)進(jìn)行檢查,以確定其合法性,提高數(shù)據(jù)的安全性。
例:要建立一個學(xué)生情況表(student)
CREATE TABLE student //創(chuàng)建基本表student
(st_class CHAR(8),// 定義列st_class班級,數(shù)據(jù)類型為8位定長字符串
st_no CHAR(10) NOT NULL,//定義列st_no學(xué)號,類型為10位定長字符串,非空
st_name CHAR(8) NOT NULL,//定義列st_name姓名,類型為8位定長字符串,非空
st_sex CHAR(2),//定義列st_sex性別,類型為2位定長字符串
st_age SMALLINT,//定義列st_age年齡,類型為短整型
PRIMARY KEY (st_no))//定義st_no學(xué)號為主鍵。
例:要建立課程設(shè)置表(subject)
CREATE TABLE subject//創(chuàng)建基本表subject
(su_no CHAR(4) NOT NULL,// 定義列su_no課號,類型為4位定長字符串,非空
su_subject CHAR(20) NOT NULL,// 定義列su_subject課程名,類型為20位定長字符串,非空
su_credit INTEGER,// 定義列su_credit學(xué)分,類型為長整數(shù)
su_period INTEGER,//定義列su_period學(xué)時,類型為長整數(shù)
su_preno CHAR(4),//定義列su_preno先修課號,類型為4位定長字符串
PRIMARY KEY(su_no))//定義su_no課號為主鍵。
例:要建立學(xué)生選課表(score)
CREATE TABLE score //創(chuàng)建基本表score
(st_no CHAR(10),//定義列st_no學(xué)號,類型為10位定長字符串
su_no CHAR(4),//定義列su_no課號,類型為4位定長字符串
sc_score INTEGER NULL,//定義列sc_score,類型為長整形,可以為空值
FOREIGN KEY (st_no) REFERENCE student,//從表student中引入?yún)⒄胀怄Ist_no,以確保本表與表student的關(guān)聯(lián)與同步
FOREIGN KEY (suno) REFERENCE subject)//從表subject中引入?yún)⒄胀怄Isu_no,以確保本表與表subject的關(guān)聯(lián)與同步
(2)基本表的刪除:用以從數(shù)據(jù)庫中刪除一個基本表及其全部內(nèi)容,其語句格式為:
DROP TABLE〔數(shù)據(jù)庫名.〕表名
例如:將上面建立的表都刪除
DROP TABLE student,subject,score
(3)基本表的修改:在基本表建立并使用一段時間后,可能需要根據(jù)實際要求對基本表的結(jié)構(gòu)進(jìn)行修改,即增加新的屬性或刪除屬性。
增加屬性的語句格式為:
ALTER TABLE 〔數(shù)據(jù)庫名.〕表名 ADD
(列名 數(shù)據(jù)類型 〔缺省值〕 〔NOT NULL / NULL〕
〔,列名 數(shù)據(jù)類型〔缺省值〕〔NOT NULL / NULL〕〕......
〔,UNIQUE (列名〔,列名〕......)〕
〔,PRIMARY KEY(列名)〕
〔,F(xiàn)OREIGN KEY(列名〔,列名〕......) REFERENCE 表名(列名〔,列名〕......)〕
〔,CHECK(條件)〕〔其它參數(shù)〕)
例如:在基本表student中加入列stborn出生日期,數(shù)據(jù)類型為DATE,且不能為空值
ALTER TABLE student ADD (stborn DATE NOT NULL)
刪除屬性的語句格式為:
ALTER TABLE 〔數(shù)據(jù)庫名.〕表名 DROP
( 列名 數(shù)據(jù)類型 〔缺省值〕〔NOT NULL / NULL〕
〔,列名 數(shù)據(jù)類型 〔缺省值〕〔NOT NULL / NULL〕〕......)
例如:將基本表student中的列st_age刪除
ALTER TABLE student DROP (st_age)
3.視圖定義與刪除
在SQL中,視圖是外模式一級數(shù)據(jù)結(jié)構(gòu)的基本單位。它是從一個或幾個基本表中導(dǎo)出的表,是從現(xiàn)有基本表中抽取若干子集組成用戶的“專用表”。這種構(gòu)造方式必須使用SQL中的SELECT語句來實現(xiàn)。在定義一個視圖時,只是把其定義存放在系統(tǒng)的數(shù)據(jù)中,而并不直接存儲視圖對應(yīng)的數(shù)據(jù),直到用戶使用視圖時才去求得對應(yīng)的數(shù)據(jù)。
(1)視圖的定義:定義視圖可以使用CREATE VIEW語句實現(xiàn),其語句格式為:
CREATE VIEW 視圖名 AS SELECT語句
從一個基本表中導(dǎo)出視圖:
例:從基本表student中導(dǎo)出只包括女學(xué)生情況的視圖
CREATE VIEW WOMANVIEW AS //創(chuàng)建一個視圖WOMANVIEW
SELECT st_class,st_no,st_name,st_age //選擇列st_class,st_no,st_name,st_age顯示
FROM student //從基本表student引入
WHERE st_sex=‘女’//引入條件為性別為“女”,注意字符變量都使用單引號引用
從多個基本表中導(dǎo)出視圖:
例如:從基本表student和score中導(dǎo)出只包括女學(xué)生且分?jǐn)?shù)在60分以上的視圖
CREATEVIEW WOMAN_SCORE AS //定義視圖WOMANSCORE
SELECT student.st_class,student.st_no,student.st_name,student.st_age,score.sc_score //有選擇性顯示相關(guān)列
FROM student.score //從基本表student和score中引入
WHERE student.st_sex=‘女’AND score.sc_score=60 AND student.st_no=score.st_no //選擇條件:性別為“女” 且分?jǐn)?shù)在60分以上。并使用st_no將兩表聯(lián)系起來。
以后如果進(jìn)行這一視圖的應(yīng)用,則只需使用語句
SELECT * FROM WOMAN_SCORE //其中“*”為通配符,代表所有元素
(2)視圖的刪除:用于刪除已不再使用的視圖,其語句格式如下:
DROP VIEW 視圖名
例:將上面建立的WOMAN_SCORE視圖刪除
DROP VIEW WOMAN_SCORE
4.索引的定義與刪除
索引屬于物理存儲概念,而不是邏輯的概念。在SQL中拋棄了索引概念,直接使用主鍵概念。值得一提的是,有些關(guān)系DBMS同時包括索引機(jī)制和主鍵機(jī)制,這里我們推薦使用主鍵機(jī)制,因為它對系統(tǒng)資源占用較低且效率較高。
(1)索引的定義:索引是建立在基本表之上的,其語句格式為:
CREATE 〔UNIQUE〕 INDEX 索引名 ON
〔數(shù)據(jù)庫名.〕表名(列名 〔ASC/DESC〕〔,列名 〔ASC/DESC〕〕......)
這里,保留字UNIQUE表示基本表中的索引值不允許重復(fù),若缺省則表示索引值在表中允許重復(fù);DESC表示按索引鍵降序排列,若缺省或ASC表示升序排列。
例:對基本表student中的st_no和st_age建立索引,分別為升序與降序,且索引值不允許重復(fù)
CREATE UNIQUE INDEX STINDEX ON//創(chuàng)建索引STINDEX
student(st_no ASC,st_age DESC)//對student中的st_no和st_age建立索引
(2)索引的刪除:
DROP INDEX 索引名
例:刪除上面建立的索引STINDEX
DROP INDEX STINDEX
##2 (二)數(shù)據(jù)查詢
SQL是一種查詢功能很強(qiáng)的語言,只要是數(shù)據(jù)庫存在的數(shù)據(jù),總能通過適當(dāng)?shù)姆椒▽⑺鼜臄?shù)據(jù)庫中查找出來。SQL中的查詢語句只有一個:SELECT,它可與其它語句配合完成所有的查詢功能。SELECT語句的完整語法,可以有6個子句。完整的語法如下:
SELECT 目標(biāo)表的列名或列表達(dá)式集合
FROM 基本表或(和)視圖集合
〔WHERE條件表達(dá)式〕
〔GROUP BY列名集合
〔HAVING組條件表達(dá)式〕〕
〔ORDER BY列名〔集合〕…〕
整個語句的語義如下:從FROM子句中列出的表中,選擇滿足WHERE子句中給出的條件表達(dá)式的元組,然后按GROUPBY子句(分組子句)中指定列的值分組,再提取滿足HAVING子句中組條件表達(dá)式的那些組,按SELECT子句給出的列名或列表達(dá)式求值輸出。ORDER子句(排序子句)是對輸出的目標(biāo)表進(jìn)行重新排序,并可附加說明ASC(升序)或DESC(降序)排列。