四胎撇、數(shù)據(jù)結(jié)構(gòu)和算法
1氢卡、求一串?dāng)?shù)字序列中的連續(xù)子串最大和旬痹,比如arr=1 -2 3 -1 2
玄帕,連續(xù)子串最大和就是3 -1 2
組成的max_sum=4部脚。
- 分析:這是一道動(dòng)態(tài)規(guī)劃的題目,可以設(shè)子問題dp[i]為以第i個(gè)數(shù)字結(jié)尾的連續(xù)子串的最大和裤纹,所以我們能得到dp[1]=1,dp[2]=-1,dp[3]=3,dp[4]=2,dp[5]=4委刘,這5個(gè)數(shù)中最大的數(shù)
max{dp[i]}
就是我們要找的。 - 如果dp[i-1]<=0鹰椒,那么dp[i]=arr[i]锡移;如果dp[i-1]>0,則有必要把前面的數(shù)加入求和dp[i]=arr[i]+dp[i-1]漆际。
int MaxSubSum(int *arr, int n)
{
int sum=0, b=0; //只用一個(gè)b記錄dp[i]淆珊,更節(jié)省內(nèi)存
for (int i=1;i<=n; i++)
{
if (b>0) b+=a[i];
else b=a[i];
if (b>sum) sum=b;
}
return sum;
}
2、尋找100范圍內(nèi)的素?cái)?shù)的算法奸汇,對(duì)于找到的前面的每個(gè)素?cái)?shù)的n倍都必然不是素?cái)?shù)施符,都可以剔除檢查
五、網(wǎng)絡(luò)
1茫蛹、TCP三次握手操刀,四次揮手狀態(tài)改變過程烁挟?
- 所謂三次握手(Three-way Handshake)婴洼,是指建立一個(gè) TCP 連接時(shí),需要客戶端和服務(wù)器總共發(fā)送3個(gè)包撼嗓。
三次握手的目的是連接服務(wù)器指定端口柬采,建立 TCP 連接,并同步連接雙方的序列號(hào)和確認(rèn)號(hào)且警,交換 TCP 窗口大小信息粉捻。在 socket 編程中,客戶端執(zhí)行 connect() 時(shí)斑芜。將觸發(fā)三次握手肩刃。
第一次握手(SYN=1, seq=x):
客戶端發(fā)送一個(gè) TCP 的控制位
的SYN 標(biāo)志位置1的包,指明客戶端打算連接的服務(wù)器的端口杏头,以及初始序號(hào) X,保存在包頭的序列號(hào)(Sequence Number)字段里盈包。
發(fā)送完畢后,客戶端進(jìn)入 SYN_SEND 狀態(tài)醇王。
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):
服務(wù)器發(fā)回確認(rèn)包(ACK)應(yīng)答呢燥。即 SYN 標(biāo)志位和 ACK 標(biāo)志位均為1。服務(wù)器端選擇自己 ISN 序列號(hào)寓娩,放到 Seq 域里叛氨,同時(shí)將確認(rèn)序號(hào)(Acknowledgement Number)設(shè)置為客戶的 ISN 加1呼渣,即X+1。 發(fā)送完畢后寞埠,服務(wù)器端進(jìn)入 SYN_RCVD 狀態(tài)屁置。
第三次握手(ACK=1,ACKnum=y+1)
客戶端再次發(fā)送確認(rèn)包(ACK)畸裳,SYN 標(biāo)志位為0缰犁,ACK 標(biāo)志位為1,并且把服務(wù)器發(fā)來 ACK 的序號(hào)字段+1怖糊,放在確定字段中發(fā)送給對(duì)方帅容,并且在數(shù)據(jù)段放寫ISN的+1
發(fā)送完畢后,客戶端進(jìn)入 ESTABLISHED 狀態(tài)伍伤,當(dāng)服務(wù)器端接收到這個(gè)包時(shí)并徘,也進(jìn)入 ESTABLISHED 狀態(tài),TCP 握手結(jié)束扰魂。
為什么就需要3次握手麦乞,不是2次或者4次?
三次握手的目的:是為了確認(rèn)雙方都有收發(fā)數(shù)據(jù)的能力或者說想確定雙通道通暢
劝评。
Client->Server:表明C有發(fā)數(shù)據(jù)的能力姐直,發(fā)了seq序列號(hào)x。
S->C:回應(yīng)x+1表明S有收數(shù)據(jù)的能力收到過x蒋畜,也有發(fā)數(shù)據(jù)的能力并且發(fā)了序列號(hào)y声畏。
C->S:回應(yīng)y+1表明C也有收數(shù)據(jù)的能力。
至此C S都互相確認(rèn)了對(duì)方有收發(fā)數(shù)據(jù)的能力姻成,然后就可以放心的向?qū)Ψ綌?shù)據(jù)了插龄。若是只有兩次,那么Server是不能確認(rèn)Client能夠收數(shù)據(jù)的科展。兩次達(dá)不到目的均牢,3次能搞定的事情,4次就顯得多余了才睹。
》從另一方面來講徘跪,若是默認(rèn)雙方都能收發(fā)數(shù)據(jù),兩次握手時(shí)琅攘,如果因?yàn)榫W(wǎng)絡(luò)擁塞先前的client某個(gè)連接請(qǐng)求被延遲垮庐,而超時(shí)重發(fā)連接請(qǐng)求后連接成功然后收發(fā)數(shù)據(jù)結(jié)束后斷開連接了。但是之前延遲的連接請(qǐng)求又最終發(fā)到了server端乎澄,server以為是個(gè)新連接然后就準(zhǔn)備給client發(fā)送數(shù)據(jù)突硝,但是client此時(shí)并沒有連接,因此收不到server的數(shù)據(jù)置济,導(dǎo)致server不停的重發(fā)數(shù)據(jù)直至認(rèn)為應(yīng)該斷開連接解恰,但是也會(huì)造成資源浪費(fèi)锋八。
》假設(shè)不采用“三次握手”而是兩次,那么只要server發(fā)出確認(rèn)护盈,新的連接就建立了挟纱。由于現(xiàn)在client并沒有發(fā)出建立連接的請(qǐng)求,因此不會(huì)理睬server的確認(rèn)腐宋,也不會(huì)向server發(fā)送數(shù)據(jù)紊服。但server卻以為新的運(yùn)輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)胸竞。這樣欺嗤,server的很多資源就白白浪費(fèi)掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生卫枝。例如剛才那種情況煎饼,client不會(huì)向server的確認(rèn)發(fā)出確認(rèn)。server由于收不到確認(rèn)校赤,就知道client并沒有要求建立連接吆玖。
》這個(gè)問題的本質(zhì)是, 信道不可靠, 但是通信雙方需要就某個(gè)問題達(dá)成一致.
而要解決這個(gè)問題, 無論你在消息中包含什么信息, 三次通信是理論上的最小值. 所以三次握手不是TCP本身的要求, 而是為了滿足"在不可靠信道上可靠地傳輸信息"這一需求所導(dǎo)致的. 請(qǐng)注意這里的本質(zhì)需求,信道不可靠, 數(shù)據(jù)傳輸要可靠. 三次達(dá)到了, 那后面你想接著握手也好, 發(fā)數(shù)據(jù)也好, 跟進(jìn)行可靠信息傳輸?shù)男枨缶蜎]關(guān)系了. 因此,如果信道是可靠的, 即無論什么時(shí)候發(fā)出消息, 對(duì)方一定能收到, 或者你不關(guān)心是否要保證對(duì)方收到你的消息, 那就能像UDP那樣直接發(fā)送消息就可以了.”。這可視為對(duì)“三次握手”目的的另一種解答思路马篮。后面一段話意思就是如果想確定雙通道通暢
沾乘,必須使用三個(gè)包的發(fā)送接收,也就是三次握手浑测。
- TCP 的連接的拆除需要發(fā)送四個(gè)包翅阵,因此稱為四次揮手(Four-way handshake),也叫做改進(jìn)的三次握手尽爆≡豕耍客戶端或服務(wù)器均可主動(dòng)發(fā)起揮手動(dòng)作读慎,在 socket 編程中漱贱,任何一方執(zhí)行 close() 操作即可產(chǎn)生揮手操作。
第一次揮手(FIN=1夭委,seq=x)
假設(shè)客戶端想要關(guān)閉連接幅狮,客戶端發(fā)送一個(gè) FIN 標(biāo)志位置為1的包,表示自己已經(jīng)沒有數(shù)據(jù)可以發(fā)送了株灸,但是仍然可以接受數(shù)據(jù)崇摄。
發(fā)送完畢后,客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)慌烧。
第二次揮手(ACK=1逐抑,ACKnum=x+1)
服務(wù)器端確認(rèn)客戶端的 FIN 包,發(fā)送一個(gè)確認(rèn)包屹蚊,表明自己接受到了客戶端關(guān)閉連接的請(qǐng)求厕氨,但還沒有準(zhǔn)備好關(guān)閉連接进每。
發(fā)送完畢后,服務(wù)器端進(jìn)入 CLOSE_WAIT 狀態(tài)命斧,客戶端接收到這個(gè)確認(rèn)包之后田晚,進(jìn)入 FIN_WAIT_2 狀態(tài),等待服務(wù)器端關(guān)閉連接国葬。
第三次揮手(FIN=1贤徒,seq=y)
服務(wù)器端準(zhǔn)備好關(guān)閉連接時(shí),向客戶端發(fā)送結(jié)束連接請(qǐng)求汇四,F(xiàn)IN 置為1接奈。
發(fā)送完畢后,服務(wù)器端進(jìn)入 LAST_ACK 狀態(tài)通孽,等待來自客戶端的最后一個(gè)ACK鲫趁。
第四次揮手(ACK=1,ACKnum=y+1)
客戶端接收到來自服務(wù)器端的關(guān)閉請(qǐng)求利虫,發(fā)送一個(gè)確認(rèn)包挨厚,并進(jìn)入 TIME_WAIT狀態(tài),等待可能出現(xiàn)的要求重傳的 ACK 包糠惫。
服務(wù)器端接收到這個(gè)確認(rèn)包之后疫剃,關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)硼讽。 - 客戶端等待了某個(gè)固定時(shí)間(兩個(gè)最大段生命周期巢价,2MSL,2 Maximum Segment Lifetime)之后固阁,沒有收到服務(wù)器端重發(fā)的FIN 報(bào)文壤躲,認(rèn)為服務(wù)器端已經(jīng)正常關(guān)閉連接摧冀,于是自己也關(guān)閉連接咪奖,進(jìn)入 CLOSED 狀態(tài)。若是收到了重復(fù)的FIN報(bào)文赁还,則要再次回應(yīng)ACK并齐。
為什么需要4次揮手漏麦?
那可能有人會(huì)有疑問,在tcp連接握手時(shí)為何ACK是和SYN一起發(fā)送况褪,這里ACK卻沒有和FIN一起發(fā)送呢撕贞。原因是因?yàn)閠cp是全雙工模式,接收到FIN時(shí)意味著對(duì)方將沒有數(shù)據(jù)再發(fā)來测垛,但是本方還是可以繼續(xù)發(fā)送數(shù)據(jù)到對(duì)方捏膨。因?yàn)槊績(jī)纱挝帐执_認(rèn)一邊不再發(fā)數(shù)據(jù),兩邊都不發(fā)數(shù)據(jù)就需要4次握手了食侮。
2号涯、TIME_WAIT狀態(tài)存在的理由和作用熬北?
- 雖然雙方都同意關(guān)閉連接了,而且握手的4個(gè)報(bào)文也都協(xié)調(diào)和發(fā)送完畢诚隙,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣)讶隐;但是因?yàn)槲覀儽仨氁傧刖W(wǎng)絡(luò)是不可靠的,你無法保證你最后發(fā)送的ACK報(bào)文會(huì)一定被對(duì)方收到久又,因此對(duì)方處于
LAST_ACK狀態(tài)下的SOCKET可能會(huì)因?yàn)槌瑫r(shí)未收到ACK報(bào)文巫延,而重發(fā)FIN報(bào)文
,所以這個(gè)TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報(bào)文
地消。 - TIME_WAIT狀態(tài)所帶來的影響
1炉峰、當(dāng)某個(gè)連接的一端處于TIME_WAIT狀態(tài)時(shí),該連接將不能再被使用脉执。事實(shí)上疼阔,對(duì)于我們比較有現(xiàn)實(shí)意義的是,這個(gè)端口將不能再被使用半夷。
2婆廊、某個(gè)端口處于TIME_WAIT狀態(tài)(其實(shí)應(yīng)該是這個(gè)連接)時(shí),這意味著這個(gè) TCP 連接并沒有斷開(完全斷開)巫橄,那么淘邻,如果你bind這個(gè)端口,就會(huì)失敗湘换。對(duì)于服務(wù)器而言宾舅,如果服務(wù)器突然壞掉了,那么它將無法再2MSL內(nèi)重新啟動(dòng)彩倚,因?yàn)閎ind會(huì)失敗筹我。
3、解決這個(gè)問題的一個(gè)方法就是設(shè)置 socket (setsockopt()函數(shù))的SO_REUSEADDR選項(xiàng)的值設(shè)為1帆离。這個(gè)選項(xiàng)意味著你可以重用一個(gè)端口地址蔬蕊。
3、ping網(wǎng)絡(luò)主機(jī)之間通不通用到什么協(xié)議盯质?
- ICMP(因特網(wǎng)控制報(bào)文協(xié)議)
- ICMP協(xié)議是IP層的附屬協(xié)議袁串,是介于IP層和TCP層之間的協(xié)議概而,一般認(rèn)為屬于IP層協(xié)議呼巷。IP協(xié)議用它來 與其他主機(jī)或路由器交換錯(cuò)誤報(bào)文和其他的一些網(wǎng)絡(luò)情況。在ICMP包重?cái)y帶了控制信息和故障恢復(fù)信 息赎瑰。主要用于路由器主機(jī)向其他路由器或者主機(jī)發(fā)送出錯(cuò)報(bào)文的控制信息
- 簡(jiǎn)單地說王悍,ping就是給目標(biāo)IP地址發(fā)送一個(gè) ICMP 回顯請(qǐng)求,并要求對(duì)方返回一個(gè) ICMP 回顯應(yīng)答來確定兩臺(tái)網(wǎng)絡(luò)機(jī)器是否連通餐曼,時(shí)延是多少压储。
4鲜漩、什么時(shí)候使用TCP,什么時(shí)候使用UDP集惋?
- TCP是穩(wěn)定孕似、可靠、面向連接的傳輸層協(xié)議刮刑,它在傳遞數(shù)據(jù)前要三次握手建立連接喉祭,在數(shù)據(jù)傳遞時(shí),有ACK確認(rèn)機(jī)制雷绢、重傳機(jī)制泛烙、流量控制、擁塞控制等翘紊,可以保證數(shù)據(jù)的正確性和有序性蔽氨。
- TCP 提供一種面向連接的、可靠的字節(jié)流服務(wù)帆疟。
在一個(gè) TCP 連接中鹉究,僅有兩方進(jìn)行彼此通信。廣播和多播不能用于 TCP踪宠。
TCP 使用校驗(yàn)和坊饶,序列號(hào)seq-ack確認(rèn)和重傳機(jī)制來保證可靠傳輸
。
TCP 給數(shù)據(jù)分節(jié)進(jìn)行排序殴蓬,并使用累積確認(rèn)保證數(shù)據(jù)的順序不變和非重復(fù)匿级。
TCP 使用滑動(dòng)窗口機(jī)制來實(shí)現(xiàn)流量控制,通過動(dòng)態(tài)改變窗口的大小進(jìn)行擁塞控制染厅。 - UDP是無連接的數(shù)據(jù)傳輸協(xié)議痘绎,端與端之間不需要建立連接,且沒有類似TCP的那些機(jī)制肖粮,會(huì)發(fā)生丟包孤页、亂序等情況。因此有低時(shí)延優(yōu)點(diǎn)涩馆。
- TCP是數(shù)據(jù)流模式行施,而UDP是數(shù)據(jù)報(bào)模式。
- 需要可靠傳輸對(duì)時(shí)延要求不高時(shí)用TCP魂那,對(duì)時(shí)延要求高并且允許一定的丟包發(fā)生時(shí)用UDP蛾号。比如游戲中,對(duì)于那些打斗視頻畫面要求低時(shí)延而且允許一定的丟包發(fā)生那就用UDP傳輸涯雅,而如果用TCP會(huì)因?yàn)橐恍﹣G包引發(fā)重傳而使得時(shí)延很高鲜结;而對(duì)于游戲中的信息管理操作交易操作等要求可靠的就要TCP,還有棋牌類游戲也是可靠性高于時(shí)延要求使用TCP。
5精刷、為什么 TCP 叫數(shù)據(jù)流模式拗胜? UDP 叫數(shù)據(jù)報(bào)模式?
- 所謂的“流模式”怒允,是指TCP發(fā)送端發(fā)送幾次數(shù)據(jù)和接收端接收幾次數(shù)據(jù)是沒有必然聯(lián)系的埂软,比如你通過 TCP 連接給另一端發(fā)送數(shù)據(jù),你只調(diào)用了一次 write纫事,發(fā)送了100個(gè)字節(jié)仰美,但是對(duì)方可以分10次收完,每次10個(gè)字節(jié)儿礼;你也可以調(diào)用10次 write咖杂,每次10個(gè)字節(jié),但是對(duì)方可以一次就收完蚊夫。
原因:
這是因?yàn)門CP是面向連接的诉字,一個(gè) socket 中收到的數(shù)據(jù)都是由同一臺(tái)主機(jī)發(fā)出,且有序地到達(dá)知纷,所以每次讀取多少數(shù)據(jù)都可以壤圃。 - 所謂的“數(shù)據(jù)報(bào)模式”,是指UDP發(fā)送端調(diào)用了幾次 write琅轧,接收端必須用相同次數(shù)的 read 讀完伍绳。UDP 是基于報(bào)文的,在接收的時(shí)候乍桂,每次最多只能讀取一個(gè)報(bào)文冲杀,報(bào)文和報(bào)文是不會(huì)合并的,如果緩沖區(qū)小于報(bào)文長(zhǎng)度睹酌,則多出的部分會(huì)被丟棄权谁。
原因:
這是因?yàn)閁DP是無連接的,只要知道接收端的 IP 和端口憋沿,任何主機(jī)都可以向接收端發(fā)送數(shù)據(jù)旺芽。 這時(shí)候, 如果一次能讀取超過一個(gè)報(bào)文的數(shù)據(jù)辐啄, 則會(huì)亂套采章。
6、IP地址的分類壶辜?私有IP(局域網(wǎng)IP)是哪些——相對(duì)于公網(wǎng)IP來說悯舟?
- IPv4是4字節(jié)32位地址,被分為A\B\C三類士复。
- A類第一個(gè)bit位固定為0图谷,1字節(jié)的網(wǎng)絡(luò)號(hào)和3字節(jié)的主機(jī)號(hào)翩活;A類的私有地址在10.0.0.0到10.255.255.255阱洪,共有2^24個(gè)可用的私有IP地址便贵。
- B類前兩個(gè)bit位固定10,2字節(jié)的網(wǎng)絡(luò)號(hào)和2字節(jié)的主機(jī)號(hào)冗荸;B類的私有地址是在172.16.0.0到172.31.255.255范圍承璃,共有16x2^16個(gè)可用的私有IP地址。
- C類前3個(gè)bit位固定110蚌本,前3字節(jié)的網(wǎng)絡(luò)號(hào)和1字節(jié)的主機(jī)號(hào)盔粹;C類私有地址為192.168.0.0到192.168.255.255,共有2^16次方個(gè)可用的私有IP地址程癌。
- 由于IPv4最大的問題在于網(wǎng)絡(luò)地址資源有限舷嗡,嚴(yán)重制約了互聯(lián)網(wǎng)的應(yīng)用和發(fā)展。IPv6地址是128位16字節(jié)的嵌莉。格式為X:X:X:X:X:X:X:X进萄,每個(gè)X是16進(jìn)制的4個(gè)數(shù)字表示16位,故8x16=128位锐峭。
7中鼠、http協(xié)議和各個(gè)狀態(tài)碼表示什么意思?
- http協(xié)議底層是應(yīng)用tcp協(xié)議沿癞,分為每次用完就斷開的短連接和用完保持的長(zhǎng)連接援雇。
- http是無狀態(tài)的協(xié)議是指,服務(wù)器不會(huì)對(duì)瀏覽器客戶端的行為進(jìn)行記錄椎扬,每次請(qǐng)求服務(wù)器都當(dāng)做是一次新的行為惫搏。但是像緩存行為那是客戶端自己記錄的,與服務(wù)器無關(guān)蚕涤【Ц客戶端想要再次獲取某個(gè)資源時(shí),向服務(wù)器發(fā)送一個(gè)包詢問在上一次訪問網(wǎng)站的時(shí)間后是否更改了頁(yè)面钻趋,如果服務(wù)器沒有更新川陆,顯然不需要把整個(gè)網(wǎng)頁(yè)傳給客戶端,客戶端只要使用本地緩存即可蛮位,如果服務(wù)器對(duì)照客戶端給出的時(shí)間已經(jīng)更新了客戶端請(qǐng)求的網(wǎng)頁(yè)较沪,則發(fā)送這個(gè)更新了的網(wǎng)頁(yè)給用戶。
- HTTP 請(qǐng)求分為三個(gè)部分:狀態(tài)行失仁、請(qǐng)求頭尸曼、消息主體。類似于下面這樣:
<method> <request-URL> <version>
<headers>
<entity-body>
- HTTP定義了與服務(wù)器交互的不同方法萄焦,最基本的方法有4種控轿,分別是GET冤竹,POST,PUT茬射,DELETE鹦蠕。URL全稱是資源描述符,我們可以這樣認(rèn)為:一個(gè)URL地址在抛,它用于描述一個(gè)網(wǎng)絡(luò)上的資源钟病,而 HTTP 中的GET獲取,POST修改刚梭,PUT增加肠阱,DELETE刪除資源。
- HTTP響應(yīng)也是三部分:狀態(tài)行朴读、響應(yīng)頭屹徘、響應(yīng)正文。狀態(tài)行由協(xié)議版本衅金、數(shù)字形式的狀態(tài)代碼噪伊、及相應(yīng)的狀態(tài)描述,各元素之間以空格分隔典挑。
200 OK 客戶端請(qǐng)求成功
301 Moved Permanently 請(qǐng)求的資源永久移動(dòng)
302 Moved Temporarily 請(qǐng)求的資源臨時(shí)移動(dòng)
304 Not Modified 文件未修改酥宴,可以直接使用瀏覽器緩存的文件,無需再?gòu)姆?wù)器下載您觉。
400 Bad Request 由于客戶端請(qǐng)求有語(yǔ)法錯(cuò)誤拙寡,不能被服務(wù)器所理解。
401 Unauthorized 請(qǐng)求未經(jīng)授權(quán)琳水,則要求客戶端再次發(fā)送用戶名密碼等認(rèn)證信息肆糕。這個(gè)狀態(tài)代碼必須和WWW-Authenticate報(bào)頭域一起使用
403 Forbidden 服務(wù)器收到請(qǐng)求,但是拒絕提供服務(wù)在孝。服務(wù)器通常會(huì)在響應(yīng)正文中給出不提供服務(wù)的原因
404 Not Found 請(qǐng)求的資源不存在诚啃,例如,輸入了錯(cuò)誤的URL
500 Internal Server Error 服務(wù)器內(nèi)部發(fā)生不可預(yù)期的錯(cuò)誤私沮,導(dǎo)致無法完成客戶端的請(qǐng)求始赎。
503 Service Unavailable 服務(wù)器當(dāng)前不能夠處理客戶端的請(qǐng)求,在一段時(shí)間之后仔燕,服務(wù)器可能會(huì)恢復(fù)正常造垛。
8、 sip協(xié)議和上面的http非常像晰搀,包含了并且擴(kuò)展了HTTP/1.1的一些狀態(tài)碼:
臨時(shí)應(yīng)答(1XX)
100 Trying 正在處理中
180 Ringing 振鈴
181 call being forwarder 呼叫正在前向
182 queue 排隊(duì)
181* session progress 會(huì)話進(jìn)行
305 use proxy 用戶代理
380 alternative service 替代服務(wù)
請(qǐng)求失敗(4XX)
405 method no allowed 方法不允許
406 not acceptable 不可接受
407 proxy authentication required 代理需要認(rèn)證
408 request timeout 請(qǐng)求超時(shí)
服務(wù)器失敗(5XX)
501 not implemented 不可執(zhí)行
502 bad gateway 壞網(wǎng)關(guān)
503 service unavailable 服務(wù)無效
504 server time-out 服務(wù)器超時(shí)
505 version not supported 版本不支持
全局性錯(cuò)誤(6XX)
600 busy everywhere 全忙
603 decline 丟棄
604 does not exist anywhere 不存在
606 not acceptable 不可接受
9五辽、訪問一個(gè)網(wǎng)站失敗,如何定位故障外恕?
- 首先訪問一個(gè)其他知名網(wǎng)站杆逗,查看是否是自身網(wǎng)絡(luò)斷開問題乡翅,比如
www.baidu,com
,若是能訪問罪郊,則說明自身電腦可以訪問外網(wǎng)蠕蚜。 - 可以詢問其他地方的朋友是否能訪問該網(wǎng)站∨帕洌看看是不是該網(wǎng)站自己出了問題波势,還可以觀察瀏覽器的返回http的狀態(tài)碼查看對(duì)應(yīng)的問題翎朱。
- 使用win+R進(jìn)入控制臺(tái)輸入ping命令橄维,可驗(yàn)證是否輸入的網(wǎng)址未被DNS服務(wù)器記錄對(duì)應(yīng)的ip,導(dǎo)致無法訪問拴曲,此時(shí)返回
ping請(qǐng)求找不到主機(jī)
争舞。若是返回丟包超時(shí),則有可能是禁止了ping命令澈灼,防火墻攔截或者是某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)出了故障竞川。 - 然后可以用trace router命令
tracert
追蹤30個(gè)節(jié)點(diǎn)內(nèi)的路由連通情況,若是從某個(gè)ip節(jié)點(diǎn)之后到第30個(gè)地址都是請(qǐng)求超時(shí)叁熔,說明就是從這個(gè)節(jié)點(diǎn)之后網(wǎng)絡(luò)斷開的委乌。
六、linux操作系統(tǒng)
1荣回、舉幾個(gè)常用的linux命令遭贸?
- cd,ls,cp,mv,rm,pwd,mkdir,rmdir,touch,cat,find -name,locate,vim,service iptables stop,ifconfig,ip addr show,
- ps -ef|grep freeswitch,kill -9 pid,service netstat restart,netstat -an | grep ESTABLISHED
- tar -cvf,tar -xvf,zip,unzip,gzip,gunzip,df,du,top
- yum -y install,apt-get -y install
- link,link -s,ls -i
http://www.reibang.com/p/a0e799ffb876
2、linux中想要將一個(gè)文件中的字符串A全部用字符串B替換心软,命令怎么寫壕吹?
-
#sed -i "s/A/B/g" file.txt
-i表示直接操作文件內(nèi)容insert,而不用打印到屏幕(如果不用-i那么只會(huì)輸出臨時(shí)文本到屏幕删铃,而不會(huì)寫入到原文件耳贬,當(dāng)然也可以用>file1.txt重定向輸出到另一個(gè)文件)。s是開始g是到末尾猎唁。sed全名叫stream editor咒劲,流編輯器,用程序的方式來編輯文本诫隅。 - 使用
#vim file
先打開文件腐魂,然后再在normal模式下(相對(duì)于插入模式編輯):%s/A/B/g
回車執(zhí)行。 -
#sed 's/^/#/g' file.txt
對(duì)文件中每一行行首(通過正則符號(hào)^匹配到行首)添加#符號(hào)阎肝,對(duì)于一些腳本文件的注釋很有用挤渔。 -
#sed 's/$/---/g' file.txt
對(duì)每一行的行尾($匹配到)添加---字符串。
3风题、正則表達(dá)式的匹配規(guī)則判导?
^ 表示一行的開頭嫉父。如:/^#/ 以#開頭的匹配。
$表示一行的結(jié)尾眼刃。如:/}$/ 以}結(jié)尾的匹配绕辖。
< 表示詞首。 如:<abc 表示以 abc 為首的詞擂红。
> 表示詞尾仪际。 如:abc> 表示以 abc 結(jié)尾的詞。
. 表示任何單個(gè)字符昵骤。
* 表示任何0或多個(gè)字符树碱。
[ ] 字符集合。 如:[abc] 表示匹配a或b或c变秦,還有 [a-zA-Z] 表示匹配所有的26個(gè)字符中的一個(gè)成榜。如果其中有^表示反,如 [^a] 表示非a的一個(gè)字符蹦玫。[0-9]表示匹配0到9的一個(gè)數(shù)字赎婚。
4、awk命令選定分隔符樱溉?
- 默認(rèn)用空格作為各列的分隔符挣输,想用其他字符需要用
-F
參數(shù)
5、Linux命令去重統(tǒng)計(jì)排序(awk命令去重保留原順序福贞,sort, uniq命令排序去重統(tǒng)計(jì))撩嚼?
-
awk '!a[$0]++' file.txt > file1.txt
對(duì)文件各行去重后重新輸出到另一個(gè)文件,并且各行保留原順序肚医,其實(shí)主要思想是前面輸出過的一行字符串绢馍,后面再遇到相同的將不會(huì)輸出。 -
sort file.txt | uniq > file1.tet
對(duì)文件先排序肠套,然后再用uniq命令去重(只能是相鄰行舰涌,所以要先排序?qū)⒅貜?fù)行放到相鄰的位置),最后再輸出到另一個(gè)文件保存而不是只打印出來你稚。 - https://blog.csdn.net/feng973/article/details/73849586
6瓷耙、Nginx服務(wù)器架構(gòu)?
- worker 進(jìn)程又是如何處理請(qǐng)求的呢刁赖?我們前面有提到搁痛,worker 進(jìn)程之間是平等的,每個(gè)進(jìn)程宇弛,處理請(qǐng)求的機(jī)會(huì)也是一樣的鸡典。當(dāng)我們提供 80 端口的 http 服務(wù)時(shí),一個(gè)連接請(qǐng)求過來枪芒,每個(gè)進(jìn)程都有可能處理這個(gè)連接彻况,怎么做到的呢谁尸?首先,每個(gè) worker 進(jìn)程都是從 master 進(jìn)程 fork 過來纽甘,在 master 進(jìn)程里面良蛮,先建立好需要 listen 的 socket(listenfd)之后,然后再 fork 出多個(gè) worker 進(jìn)程悍赢。所有 worker 進(jìn)程的 listenfd 會(huì)在新連接到來時(shí)變得可讀决瞳,為保證只有一個(gè)進(jìn)程處理該連接,所有 worker 進(jìn)程在注冊(cè) listenfd 讀事件前搶 accept_mutex左权,搶到互斥鎖的那個(gè)進(jìn)程注冊(cè) listenfd 讀事件皮胡,在讀事件里調(diào)用 accept 接受該連接。當(dāng)一個(gè) worker 進(jìn)程在 accept 這個(gè)連接之后涮总,就開始讀取請(qǐng)求胸囱,解析請(qǐng)求祷舀,處理請(qǐng)求瀑梗,產(chǎn)生數(shù)據(jù)后,再返回給客戶端裳扯,最后才斷開連接抛丽,這樣一個(gè)完整的請(qǐng)求就是這樣的了。我們可以看到饰豺,一個(gè)請(qǐng)求亿鲜,完全由 worker 進(jìn)程來處理,而且只在一個(gè) worker 進(jìn)程中處理冤吨。
- 那么蒿柳,Nginx 采用這種進(jìn)程模型有什么好處呢吼蚁?當(dāng)然胧瓜,好處肯定會(huì)很多了。首先空繁,對(duì)于每個(gè) worker 進(jìn)程來說怠李,獨(dú)立的進(jìn)程圾叼,不需要加鎖,所以省掉了鎖帶來的開銷捺癞,同時(shí)在編程以及問題查找時(shí)夷蚊,也會(huì)方便很多。其次髓介,采用獨(dú)立的進(jìn)程惕鼓,可以讓互相之間不會(huì)影響,一個(gè)進(jìn)程退出后唐础,其它進(jìn)程還在工作箱歧,服務(wù)不會(huì)中斷夫否,master 進(jìn)程則很快啟動(dòng)新的 worker 進(jìn)程。當(dāng)然叫胁,worker 進(jìn)程的異常退出凰慈,肯定是程序有 bug 了,異常退出驼鹅,會(huì)導(dǎo)致當(dāng)前 worker 上的所有請(qǐng)求失敗微谓,不過不會(huì)影響到所有請(qǐng)求,所以降低了風(fēng)險(xiǎn)输钩。當(dāng)然豺型,好處還有很多,大家可以慢慢體會(huì)买乃。
http://wiki.jikexueyuan.com/project/nginx/nginx-framework.html
7姻氨、C/S架構(gòu)和B/S結(jié)構(gòu)?
- C/S是Client/Server剪验,即tcp/udp中的客戶端和服務(wù)器架肴焊。
- B/S是Browser/Server,即瀏覽器和服務(wù)器功戚,是web的架構(gòu)娶眷。
8、gdb調(diào)試常用命令啸臀?
- 先編譯生成帶調(diào)試信息的可執(zhí)行文件:
#gcc -g test.c -o test
- 然后使用gdb命令運(yùn)行可執(zhí)行文件:
#gdb test
然后進(jìn)入gdb調(diào)試命令行環(huán)境届宠。 - (gdb) l <-------------------- l命令相當(dāng)于list,從第一行開始列出源碼乘粒。
- (gdb) <-------------------- 直接回車表示豌注,重復(fù)上一次命令
- (gdb) start <-------------------- //開始調(diào)試,運(yùn)行到第一個(gè)斷點(diǎn)處停止灯萍。
- (gdb) break 16 <-------------------- 設(shè)置斷點(diǎn)轧铁,在源程序第16行處。break命令也可簡(jiǎn)寫成b竟稳。+16表示在16行后停止属桦,-16表示在16行前停止。
- (gdb) break func <-------------------- 設(shè)置斷點(diǎn)他爸,在函數(shù)func()入口處聂宾。
- (gdb) info break <-------------------- 查看斷點(diǎn)信息。
- (gdb) delete breakpoints 2 <-------------------- //刪除某個(gè)斷點(diǎn)
- (gdb) bt <--------------------- backtrace命令诊笤,查看當(dāng)前運(yùn)行的函數(shù)的堆棧(函數(shù)參數(shù)系谐、局部變量、該函數(shù)的函數(shù)調(diào)用棧等)。
- (gdb) finish <--------------------- 執(zhí)行完并退出當(dāng)前函數(shù)纪他。
- (gdb) r <--------------------- 重新開始運(yùn)行程序鄙煤,run命令簡(jiǎn)寫,運(yùn)行到第一個(gè)斷點(diǎn)處停止茶袒。
- (gdb) n <--------------------- 單條語(yǔ)句執(zhí)行梯刚,next命令簡(jiǎn)寫。
- (gdb) set var sum=0 <--------------------- //修改變量值
- (gdb) c <--------------------- 繼續(xù)運(yùn)行程序薪寓,continue命令簡(jiǎn)寫亡资,運(yùn)行到下一個(gè)斷點(diǎn)處停止。
- (gdb) p i <--------------------- 打印變量i的值向叉,print命令簡(jiǎn)寫锥腻。
- (gdb) q <--------------------- quit,退出gdb母谎,回到linux命令行瘦黑。
- 程序發(fā)生段錯(cuò)誤或總線錯(cuò)誤等會(huì)產(chǎn)生core dump ,然后留下一個(gè)core文件奇唤,可用
#gdb core
運(yùn)行此文件幸斥,查看出錯(cuò)的信息。 - 調(diào)試已運(yùn)行的程序
————————
兩種方法:
1冻记、在UNIX下用ps查看正在運(yùn)行的程序的PID(進(jìn)程ID)睡毒,然后用gdb PID格式掛接正在
運(yùn)行的程序。
2冗栗、先用gdb 關(guān)聯(lián)上源代碼,并進(jìn)行g(shù)db供搀,在gdb中用attach命令來掛接進(jìn)程的PID隅居。并用
detach來取消掛接的進(jìn)程。 - Core dump叫做核心轉(zhuǎn)儲(chǔ)葛虐,它是進(jìn)程運(yùn)行時(shí)在突然崩潰的那一刻的一個(gè)內(nèi)存快照胎源。操作系統(tǒng)在程序發(fā)生異常而異常在進(jìn)程內(nèi)部又沒有被捕獲的情況下,會(huì)把進(jìn)程此刻內(nèi)存屿脐、寄存器狀態(tài)涕蚤、運(yùn)行堆棧等信息轉(zhuǎn)儲(chǔ)保存在一個(gè)文件里。(linux中如果內(nèi)存越界會(huì)收到SIGSEGV信號(hào)的诵,然后就會(huì)core dump)產(chǎn)生段錯(cuò)誤或者總線錯(cuò)誤万栅。
- 產(chǎn)生core dump后會(huì)在可執(zhí)行文件的目錄下產(chǎn)生一個(gè)core文件(若沒有設(shè)置則可能不產(chǎn)生)。
- 使用ulimit -c unlimited來設(shè)置無限大西疤,則任意情況下都會(huì)產(chǎn)生core文件烦粒。
- 使用命令#gdb 可執(zhí)行程序 core.xxx,然后再在gdb環(huán)境中輸入where或者bt(backtrace)就可以看到產(chǎn)生段錯(cuò)誤的地方。注意使用where的前提是該可執(zhí)行文件是gcc -g 即加了gdb調(diào)試編譯得到的扰她,然后用where才可以看到錯(cuò)誤的行號(hào)兽掰。否則看不到行號(hào),只會(huì)和用bt命令一樣徒役,把運(yùn)行經(jīng)過的函數(shù)椖蹙。回溯(backtrace)顯示出來。
- 顯示了帶編號(hào)的函數(shù)棧后忧勿,frame addr(函數(shù)幀數(shù))或者簡(jiǎn)寫f n 跳轉(zhuǎn)到core堆棧的第n幀我們自己的函數(shù)泻云。然后可以用disassemble打開該幀函數(shù)的反匯編代碼,有個(gè)箭頭指向最終停止程序執(zhí)行的地方狐蜕,上一行就是出錯(cuò)的行宠纯。
https://blog.csdn.net/sunxiaopengsun/article/details/72974548
》》》造成segment fault,產(chǎn)生core dump的可能原因
1.內(nèi)存訪問越界
a) 由于使用錯(cuò)誤的下標(biāo)层释,導(dǎo)致數(shù)組訪問越界
b) 搜索字符串時(shí)婆瓜,依靠字符串結(jié)束符來判斷字符串是否結(jié)束,但是字符串沒有正常的使用結(jié)束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函數(shù)贡羔,將目標(biāo)字符串讀/寫爆廉白。應(yīng)該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數(shù)防止讀寫越界。
2 多線程程序使用了線程不安全的函數(shù)乖寒。
3 多線程讀寫的數(shù)據(jù)未加鎖保護(hù)猴蹂。對(duì)于會(huì)被多個(gè)線程同時(shí)訪問的全局?jǐn)?shù)據(jù),應(yīng)該注意加鎖保護(hù)楣嘁,否則很容易造成core dump
4 非法指針
a) 使用空指針
b) 隨意使用指針轉(zhuǎn)換磅轻。一個(gè)指向一段內(nèi)存的指針,除非確定這段內(nèi)存原先就分配為某種結(jié)構(gòu)或類型逐虚,或者這種結(jié)構(gòu)或類型的數(shù)組聋溜,否則不要將它轉(zhuǎn)換為這種結(jié)構(gòu)或類型的指針,而應(yīng)該將這段內(nèi)存拷貝到一個(gè)這種結(jié)構(gòu)或類型中叭爱,再訪問這個(gè)結(jié)構(gòu)或類型撮躁。這是因?yàn)槿绻@段內(nèi)存的開始地址不是按照這種結(jié)構(gòu)或類型對(duì)齊的,那么訪問它時(shí)就很容易因?yàn)閎us error而core dump.
5 堆棧溢出.不要使用大的局部變量(因?yàn)榫植孔兞慷挤峙湓跅I希┞蛭恚@樣容易造成堆棧溢出把曼,破壞系統(tǒng)的棧和堆結(jié)構(gòu),導(dǎo)致出現(xiàn)莫名其妙的錯(cuò)誤漓穿。
9嗤军、從C源代碼到可執(zhí)行文件的編譯鏈接過程?
gcc test.c -o test 器净,這一行命令就可以將test.c源代碼生成可執(zhí)行文件test型雳,下面是拆解這個(gè)過程。
預(yù)處理》編譯》匯編》鏈接》可執(zhí)行文件
總結(jié)這個(gè)變化過程為test.c 》 test.i 》 test.s 》 test.o 》 test
-
#gcc test.c -E -o test.i
預(yù)處理過程,將c文件去注釋纠俭、宏替換沿量、展開頭文件、條件編譯冤荆。得到的還是ASCII碼形式的文本C語(yǔ)言源碼朴则。 -
#gcc test.i -S -o test.s
編譯過程,將預(yù)處理后的C語(yǔ)言源碼編譯成ASCII碼文本形式的匯編代碼钓简,期間會(huì)進(jìn)行代碼優(yōu)化乌妒,匯總函數(shù)變量等符號(hào)。 -
#gcc test.s -c -o test.o
匯編過程外邓,將ASCII碼文本形式的內(nèi)容匯編成二進(jìn)制目標(biāo)文件撤蚊,合并各個(gè)section,合并符號(hào)表。 -
#gcc test1.o test2.o -o test
鏈接過程损话,將多個(gè).o目標(biāo)文件鏈接成一個(gè)可執(zhí)行文件侦啸,合并各個(gè).obj文件的section,合并符號(hào)表丧枪,進(jìn)行符號(hào)解析光涂;符號(hào)地址重定位。
我們用gcc編譯程序時(shí)拧烦,常常會(huì)用到“-I”(大寫i)后接頭文件地址忘闻,“-L”(大寫l)后接鏈接庫(kù)文件地址,“-l”(小寫l)指定需鏈接的庫(kù)文件等參數(shù)(當(dāng)既有動(dòng)態(tài)庫(kù)world.so又有靜態(tài)庫(kù)world.a時(shí)默認(rèn)使用動(dòng)態(tài)庫(kù)恋博,若要首選靜態(tài)庫(kù)則要加上-static選項(xiàng))齐佳,下面做個(gè)記錄:例:
gcc -o hello hello1.c hello2.c hello3.c -I/home/hello/include -L/home/hello/lib -lworld
10、靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)生成和區(qū)別交播?
- 靜態(tài)庫(kù).a——archives重虑,鏈接時(shí)拷貝需要的函數(shù)內(nèi)容到可執(zhí)行文件,因此可執(zhí)行文件會(huì)比較大秦士,鏈接完成后不再需要靜態(tài)庫(kù)了。
- 靜態(tài)庫(kù)的生成:
#ar cr libtest.a test1.o test2.o
ar——archives靜態(tài)庫(kù)永高,cr——create創(chuàng)建隧土。 - 動(dòng)態(tài)庫(kù).so——shared object,共享動(dòng)態(tài)庫(kù)命爬,所謂共享的意思即為所有動(dòng)態(tài)庫(kù)共享一份源代碼曹傀,而不是像每個(gè)靜態(tài)庫(kù)那樣都拷貝一份源代碼,節(jié)省空間饲宛,程序運(yùn)行時(shí)再載入需要的庫(kù)皆愉,linux鏈接時(shí)默認(rèn)首選動(dòng)態(tài)庫(kù)。
- 動(dòng)態(tài)庫(kù)生成:
#gcc -shared -fPIC -o libtest.so test1.o test2.o
,PIC是指位置無關(guān)代碼(Position-Independent Code)幕庐。 - 還可在程序中進(jìn)行動(dòng)態(tài)庫(kù)的裝載和卸載久锥,而不是在編譯時(shí)就鏈接好
頭文件<dlfcn.h>
void* handle = dlopen("libtest.so", RTLD_LAZY);
//根據(jù)地址加載動(dòng)態(tài)庫(kù),并選定加載模式是立即加載RTLD_NOW還是用到時(shí)再加載RTLD_LAZY异剥。加載失敗時(shí)返回空瑟由。
void (*test_func)() = dlsym(handle, "test");
根據(jù)提供的函數(shù)名test從動(dòng)態(tài)庫(kù)中返回該函數(shù)的調(diào)用地址并賦給一個(gè)函數(shù)指針。
(*test_func)();
執(zhí)行該函數(shù)冤寿,也可以是test_func();
int flag = dlclose(handle);
動(dòng)態(tài)庫(kù)卸載函數(shù)歹苦,傳入的參數(shù)是加載時(shí)返回的句柄,返回值為0表示成功督怜,非0錯(cuò)誤殴瘦。
七、數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS——MySQL是一種關(guān)系型DBMS)
- 注意數(shù)據(jù)庫(kù)database和數(shù)據(jù)庫(kù)管理系統(tǒng)的區(qū)別
0号杠、MySQL基于tcp協(xié)議蚪腋?
- 同一臺(tái)服務(wù)器上的MySQL客戶端和服務(wù)器可以是用Unix socket進(jìn)程間通信協(xié)議。
同一臺(tái)或不同的服務(wù)器都可以遠(yuǎn)程連接MySQL數(shù)據(jù)庫(kù)究流,采用的就是TCP協(xié)議通信辣吃。 - MySQL服務(wù)器默認(rèn)監(jiān)聽3306端口。應(yīng)用程序作為客戶端去TCP連接3306端口然后發(fā)送sql請(qǐng)求然后得到響應(yīng)芬探。
- TCP握手協(xié)議:客戶端連接MySQL服務(wù)器首先也是會(huì)經(jīng)過TCP的3次握手神得,然后連接成功。
- MYSQL握手協(xié)議:接著偷仿,進(jìn)行mysql認(rèn)證過程哩簿。(1)服務(wù)端首先會(huì)發(fā)一個(gè)握手包到客戶端,(2)然后客戶端向服務(wù)端發(fā)送認(rèn)證信息(用戶名酝静,密碼等)节榜,(3)服務(wù)端收到認(rèn)證包后,會(huì)檢查用戶名與密碼是否合法别智,并發(fā)送包告知客戶端認(rèn)證信息宗苍。如果合法,則登陸成功薄榛,否則讳窟,登陸失敗連接報(bào)錯(cuò)。
問題
(1).Unix socket方式登陸與TCP方式登陸有什么區(qū)別和聯(lián)系敞恋?
Unix socket是實(shí)現(xiàn)進(jìn)程間通信
的一種方式丽啡,mysql支持利用Unix socket來實(shí)現(xiàn)客戶端-服務(wù)端的通信,但要求客戶端和服務(wù)端在同一臺(tái)機(jī)器上硬猫。對(duì)于unix socket而言补箍,同樣也是一種套接字改执,監(jiān)聽線程會(huì)同時(shí)監(jiān)聽TCP socket和Unix socket,接受到請(qǐng)求然后處理坑雅,后續(xù)的處理邏輯都是一致的辈挂,只不過底層通信方式不一樣罷了。
mysql -h127.0.0.1 –P3306 –uxxx –pxxx [TCP通信方式霞丧,需要指明host呢岗、Port]
mysql -uxxx –pxxx –S/usr/mysql/mysql.sock [unix socket通信方式,不需要h\P]
(2).監(jiān)聽socket是否與通信socket公用一個(gè)端口蛹尝?
我們知道后豫,服務(wù)端一直有一個(gè)監(jiān)聽socket在3306端口監(jiān)聽,等待新進(jìn)來的客戶請(qǐng)求突那,一旦一個(gè)請(qǐng)求過來挫酿,服務(wù)端會(huì)重新創(chuàng)建一個(gè)新的通信socket,這個(gè)新的socket專門用于與這個(gè)客戶通信愕难,而監(jiān)聽socket則繼續(xù)監(jiān)聽早龟。雖然是2個(gè)套接字,但監(jiān)聽socket和通信socket都是同一個(gè)端口猫缭,通過netstat可以確認(rèn)這個(gè)問題葱弟。
(3).連接超時(shí)參數(shù)connect_timeout在何時(shí)作用?
這個(gè)參數(shù)實(shí)質(zhì)就是在MYSQL認(rèn)證過程起作用猜丹,如果在這個(gè)過程中芝加,客戶端超過connect_timeout時(shí)間仍然沒有發(fā)送密碼認(rèn)證包過來,則會(huì)主動(dòng)斷開連接射窒。
1藏杖、事務(wù)(transaction)是什么?
- 簡(jiǎn)單說脉顿,一個(gè)事務(wù)就是一組SQL語(yǔ)句蝌麸。
- 在數(shù)據(jù)庫(kù)系統(tǒng)中,一個(gè)事務(wù)是指:由一系列數(shù)據(jù)庫(kù)操作組成的一個(gè)
完整的
邏輯過程艾疟。例如銀行轉(zhuǎn)帳来吩,從原賬戶扣除金額
,以及向目標(biāo)賬戶添加金額
蔽莱,這兩個(gè)數(shù)據(jù)庫(kù)操作的總和误褪,
構(gòu)成一個(gè)完整的邏輯過程,不可拆分
碾褂。這個(gè)過程被稱為一個(gè)事務(wù)。 - MySQL從5.5.5版本開始默認(rèn)使用InnoDB作為存儲(chǔ)引擎历葛,這個(gè)存儲(chǔ)引擎支持事務(wù)正塌;然而之前的默認(rèn)的MyISAM存儲(chǔ)引擎是不支持事務(wù)性的嘀略。
- 執(zhí)行BEGIN命令開啟一個(gè)事務(wù),若一系列數(shù)據(jù)庫(kù)操作命令中有失敗的將會(huì)執(zhí)行ROLLBACK命令恢復(fù)原狀乓诽,當(dāng)所有命令成功執(zhí)行時(shí)會(huì)執(zhí)行COMMIT命令提交帜羊,確保事務(wù)結(jié)束并且這個(gè)表得到正確的更新。
2鸠天、事務(wù)有幾個(gè)特性讼育?分別是什么?
- 四個(gè)特性稠集,ACID(英語(yǔ)意思:酸)
- A 原子性(atomicity奶段,或稱不可分割性)一個(gè)事務(wù)中的所有操作,要么全部完成剥纷,要么全部不完成痹籍,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤晦鞋,會(huì)被恢復(fù)(Rollback)到事務(wù)開始前的狀態(tài)蹲缠,就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣。
- C 一致性(consistency)在事務(wù)開始之前和事務(wù)結(jié)束以后悠垛,數(shù)據(jù)庫(kù)的完整性沒有被破壞线定。這表示寫入的資料必須完全符合所有的預(yù)設(shè)規(guī)則,這包含資料的精確度确买、串聯(lián)性以及后續(xù)數(shù)據(jù)庫(kù)可以自發(fā)性地完成預(yù)定的工作斤讥。
- I 隔離性(isolation,又稱獨(dú)立性)數(shù)據(jù)庫(kù)允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其數(shù)據(jù)進(jìn)行讀寫和修改的能力拇惋,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致周偎。事務(wù)隔離分為不同級(jí)別,包括讀未提交(Read uncommitted)撑帖、讀提交(read committed)蓉坎、可重復(fù)讀(repeatable read)和串行化(Serializable)。
- D 持久性(durability)事務(wù)處理結(jié)束后胡嘿,對(duì)數(shù)據(jù)的修改就是永久的蛉艾,即便系統(tǒng)故障也不會(huì)丟失。
3衷敌、MySQL數(shù)據(jù)庫(kù)基本操作命令
- 注意: MySQL語(yǔ)句以分號(hào)(;)作為語(yǔ)句的結(jié)束, 若在語(yǔ)句結(jié)尾不添加分號(hào)時(shí), 命令提示符會(huì)以 -> 提示你繼續(xù)輸入(有個(gè)別特例, 但加分號(hào)是一定不會(huì)錯(cuò)的);
-
show databases;
查看當(dāng)前已經(jīng)創(chuàng)建的數(shù)據(jù)庫(kù) -
create database samp_db;
創(chuàng)建數(shù)據(jù)庫(kù)勿侯,為了便于在命令提示符下顯示中文, 在創(chuàng)建時(shí)通過后加 character set gbk 將數(shù)據(jù)庫(kù)字符編碼指定為 gbk。 -
mysql -D 所選擇的數(shù)據(jù)庫(kù)名 -h 主機(jī)名 -u 用戶名 -p
再輸入密碼缴罗,表示登錄時(shí)指定使用的數(shù)據(jù)庫(kù)助琐;也可以不指定-D db登錄后,再用命令use samp_db;
(也可不加分號(hào))選擇該數(shù)據(jù)庫(kù)進(jìn)行執(zhí)行面氓。選擇成功后會(huì)提示: Database changed兵钮。 -
show tables;
查看當(dāng)前已經(jīng)存在的表 -
create table 表明(列名);
創(chuàng)建表命令
create table tab_new like tab_old;
(使用舊表創(chuàng)建新表)
"primary key" 表示該列是表的主鍵, 本列的值必須唯一, MySQL將自動(dòng)索引該列蛆橡。
"auto_increment"表示該值若給的是NULL,則會(huì)自動(dòng)的在當(dāng)前最大值基礎(chǔ)上加1賦值掘譬。
MySQL有3種數(shù)據(jù)類型:
數(shù)字類型
【tinyint(1字節(jié)-128~127),smallint,bigint,int(4字節(jié)最常用)(前面的都有unsigned),float(總長(zhǎng)泰演,小數(shù)長(zhǎng)),double】,可在條件語(yǔ)句中比較大小
日期和時(shí)間類型
【year(2或4位),date(日期年-月-日=最常用),time(時(shí)間時(shí):分:秒),datetime(日期和時(shí)間組合=最常用),timestamp(從1970.1.1開始的時(shí)間戳年月日時(shí)分秒無分割)】
字符串類型
【char(length定長(zhǎng)字符串),varchar(length變長(zhǎng)字符串=最常用),text(大量文本=最常用),blob(二進(jìn)制對(duì)象如圖片),enum(每局型只能是填入其中指定的值的索引)】
create table students
(
id int unsigned not null auto_increment primary key,
name char(8) not null,
sex char(4) not null,
age tinyint unsigned not null,
tel char(13) null default "-"
);
從sql腳本執(zhí)行命令:
打開命令提示符, 輸入:mysql -D samp_db -u root -p < createtable.sql
(提示: 1.如果連接遠(yuǎn)程主機(jī)請(qǐng)加上 -h 指令; 2. createtable.sql 文件若不在當(dāng)前工作目錄下需指定文件的完整路徑葱轩。)crud是指在做計(jì)算處理時(shí)的增加(Create)睦焕、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)幾個(gè)單詞的首字母簡(jiǎn)寫靴拱。crud主要被用在描述軟件系統(tǒng)中數(shù)據(jù)庫(kù)或者持久層的基本操作功能垃喊。
向表中插入數(shù)據(jù)【增】:
insert [into] 表名 [(列名1, 列名2, 列名3, ...)] values (值1, 值2, 值3, ...);
其中 [] 內(nèi)的內(nèi)容是可選的, 如給 samp_db 數(shù)據(jù)庫(kù)中 students 表插入一條記錄, 執(zhí)行語(yǔ)句:
若是要完整插入一條記錄insert into students values(NULL, "王剛", "男", 20, "13811371377");
,若是只插入部分?jǐn)?shù)據(jù)或者不按照順序插入數(shù)據(jù)則必須將列名和值一一對(duì)應(yīng)插入:insert into students (name, sex, age) values("張三", "男", 20);
從表中【刪】除符合條件的數(shù)據(jù):
delete from 表名稱 where 刪除條件;
刪除id為2的行: delete from students where id=2;
刪除所有年齡小于21歲的數(shù)據(jù): delete from students where age<20;
刪除表中的所有數(shù)據(jù): delete from students;更新修【改】表中的某條記錄:
update 表名稱 set 列名稱=新值 where 更新條件;
將id為5的手機(jī)號(hào)改為默認(rèn)的"-": update students set tel=default where id=5;
將所有人的年齡增加1: update students set age=age+1;
將手機(jī)號(hào)為 13288097888 的姓名改為 "張偉鵬", 年齡改為 19: update students set name="張偉鵬", age=19 where tel="13288097888";【替換REPLACE INTO】==【DELETE】+【INSERT INTO】:即先根據(jù)新插入值的主鍵查找缭嫡,如果之前有這個(gè)主鍵存在則要DELETE該行然后在該位置替換新的一行數(shù)據(jù)缔御;要是之前不存在該主鍵,那就在最后面插入一行新紀(jì)錄妇蛀。
replace into students (id,name,sex,age) values(1,"李四","男",30);
-
從表中【查】找數(shù)據(jù):
select 列名稱 from 表名稱 [where查詢條件獲取指定的行] [order by 列名排序[ASC默認(rèn)升序|DESC降序]] [LIMIT 限制輸出從第幾行開始的n條數(shù)據(jù)];
只查詢 students 表中所有學(xué)生的名字和年齡兩列內(nèi)容:select name, age from students;
使用通配符 * 查詢表中所有列的內(nèi)容, 語(yǔ)句:select * from students;
查詢返回不同的值過濾掉相同值【DISTINCT關(guān)鍵字】:select DISTINCT age from students;
只返回所有學(xué)生中不重復(fù)的年齡情況耕突。
按特定條件查詢: where 關(guān)鍵詞用于指定查詢條件:select 列名稱 from 表名稱 where 條件;
查詢所有性別為女【字符串=】的信息:select * from students where sex="女";
查詢年齡在21【數(shù)字比較大小】歲以上的所有人信息:select * from students where age > 21;
查詢名字中帶有 "王" 字【like】的所有人信息:select * from students where name like "%王%";
》》》通配符,注意%號(hào)表示匹配多個(gè)字符评架,_號(hào)表示匹配一個(gè)字符眷茁,如"王%"表示匹配姓王的名字,"王_"表示匹配姓王但是姓名只有兩個(gè)字的人纵诞。這個(gè)比較總是不區(qū)分大小寫的上祈,若是使用binary關(guān)鍵字則可強(qiáng)制區(qū)分大小寫where name binary like "A%"
表示匹配A開頭的,而不會(huì)匹配a開頭的浙芙。類似的還有一個(gè)【正則REGEXP】關(guān)鍵字登刺,用于使用正則表達(dá)式匹配姓王的select * from students where name REGEXP "王$";
,所有的正則規(guī)則都可以使用嗡呼。
查詢id小于5且【and和or】年齡大于20的所有人信息:select * from students where id<5 and age>20;
查詢年齡位于【between and】18到25的所有行:select * from students where age between 18 and 25;
找出年齡大于等于18歲的剛成年的年齡最小【order by】的5個(gè)人【limit】的信息:select * from students where age>=18 order by age ASC limit 0,5;
//即從小到大排序后下標(biāo)0開始的5條記錄
同上輸出5個(gè)人后面接下來5個(gè)人的信息:select * from students where age>=18 order by age ASC limit 5,5;
//即從下標(biāo)5開始的5條記錄
使用【in】操作來指定想要匹配的范圍列表(圓括號(hào)括起):where name in ("alice","bob","mary");
【多表查詢】可以在一條select語(yǔ)句中查詢兩個(gè)無關(guān)聯(lián)的表纸俭,假設(shè)fruit和color都有id和fruitname,colornamelainglie南窗,各4行數(shù)據(jù)揍很。若是直接select * from fruit,color;
則會(huì)展示4x4=16條記錄,因?yàn)檫@個(gè)查詢會(huì)簡(jiǎn)單的吧color表中的每一行追加連接到fruit后面万伤。
select fruit.id,fruitname,colorname from fruit,color where fruit.id=color.id;
才會(huì)只輸出4行數(shù)據(jù)窒悔。注意必須指明輸出的id是誰(shuí)的,如果直接用id會(huì)產(chǎn)生歧義報(bào)錯(cuò)敌买。
【子查詢简珠,即語(yǔ)句中內(nèi)含SELECT查詢子句】select * from A where key in (select key from B)
就是求A表中key也在【配合IN使用】B表的所有A表的數(shù)據(jù)(不包含B表的數(shù)據(jù))。和下圖中A交B還是有區(qū)別的虹钮,A交B是指把A和B表中key相同的各列連接起來北救。
【join表聯(lián)結(jié)】聯(lián)結(jié)是在查詢語(yǔ)句運(yùn)行后對(duì)結(jié)果聯(lián)結(jié)返回荐操,不對(duì)數(shù)據(jù)庫(kù)中的表進(jìn)行修改。
select fruit.id,fruitname,colorname from fruit INNER JOIN color ON fruit.id=color.id;
可見使用ON代替了上面的where子句珍策,【INNER JOIN】表示把兩個(gè)表中id相同的行連接起來,默認(rèn)只用【JOIN】就是指這個(gè)宅倒,【CROSS JOIN】從語(yǔ)法上來看在mysql與INNER JOIN等同攘宙,CROSS JOIN是交叉聯(lián)結(jié)即類似全排列(笛卡爾積)」涨ǎ【STRAIGHT JOIN】完全等同于inner join 只不過蹭劈,INNER JOIN語(yǔ)法是會(huì)自動(dòng)根據(jù)“哪個(gè)表的結(jié)果集小,就以哪個(gè)表為驅(qū)動(dòng)表”來決定誰(shuí)先載入的线召,而straight_join 會(huì)強(qiáng)制選擇其左邊的表先載入铺韧。
前面講的都是內(nèi)聯(lián)結(jié),接下來看外聯(lián)結(jié)缓淹。另外還有一個(gè)常用的【LEFT JOIN左聯(lián)結(jié)】表示左邊的表記錄都會(huì)輸出哈打,ON后面匹配到的右邊的表的內(nèi)容才會(huì)連接到左表記錄,沒匹配的左表對(duì)應(yīng)記錄為空讯壶。同理【RIGHT JOIN右聯(lián)結(jié)】表示右表記錄全部輸出料仗,而左表只輸出ON后匹配到的。
外鍵只是一個(gè)表中的非主鍵列但是它是另一個(gè)表的主鍵伏蚊,即外面的主鍵的意思立轧。用于將兩個(gè)表關(guān)聯(lián)起來,然后更好地進(jìn)行聯(lián)結(jié)查詢或子查詢躏吊。
要修改表結(jié)構(gòu)(表的列值或表名稱等):
添加列:alter table 表名 add 列名 列數(shù)據(jù)類型 [after 插入在哪列之后];
默認(rèn)插入到末尾列
刪除列:alter table 表名 drop 列名稱;
修改列:alter table 表名 change 列名稱 列新名稱 新數(shù)據(jù)類型;
修改表名稱:alter table 表名 rename 新表名;
刪除表或者數(shù)據(jù)庫(kù):
刪除表(在當(dāng)前數(shù)據(jù)庫(kù)操作范圍內(nèi)):drop table 表名;
刪除數(shù)據(jù)庫(kù):drop database 數(shù)據(jù)庫(kù)名;
4氛改、mysql默認(rèn)是不區(qū)分列名大小寫的(輸入的大寫會(huì)先轉(zhuǎn)為小寫再保存),如何使字段查詢區(qū)分大小寫?
- 方法一:在sql查詢條件語(yǔ)句中,要查詢的字段前加
binary
關(guān)鍵字辕近,表示使用二進(jìn)制進(jìn)行比較
SELECT * FROM emp WHERE BINARY emp.job='Engineer';
SELECT * FROM emp WHERE BINARY emp.job='ENGINEER'; - 方法二:在建表的時(shí)候就指定表中數(shù)據(jù)存儲(chǔ)的格式吟榴,Mysql默認(rèn)的字符檢索策略:utf8_general_ci,表示不區(qū)分大小寫绪抛;utf8_general_cs表示區(qū)分大小寫,utf8_bin表示二進(jìn)制比較,同樣也區(qū)分大小寫 紫新。
創(chuàng)建表:
CREATE TABLE test(
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL //或者在后面直接指定BINARY二進(jìn)制形式存儲(chǔ)
) ENGINE = INNODB COLLATE =utf8_bin;
如果表已經(jīng)創(chuàng)建,則修改表結(jié)構(gòu)中Collation字段
- 在win操作系統(tǒng)李剖,對(duì)數(shù)據(jù)庫(kù)名和表名默認(rèn)都不區(qū)分大小寫芒率,在linux下都區(qū)分。sql命令都不區(qū)分大小寫篙顺。
在my.cnf文件中偶芍,有個(gè)變量值的設(shè)置可以影響表名稱的大小寫敏感充择,表示表名是否大小寫敏感,可以修改匪蟀。
lower_case_table_names = 0時(shí)椎麦,mysql會(huì)根據(jù)表名直接操作,大小寫敏感材彪,linux下默認(rèn)設(shè)置观挎。
lower_case_table_names = 1時(shí),mysql會(huì)先把表名轉(zhuǎn)為小寫段化,再執(zhí)行操作大小寫就不敏感了嘁捷。 - 命名規(guī)范
為了避免大小寫引發(fā)的問題,一種推薦的命名規(guī)則是:在定義數(shù)據(jù)庫(kù)/表/列的時(shí)候全部采用小寫字母+下劃線形式显熏,不使用任何大寫字母雄嚣。
如果你使用InnoDB引擎,在任何平臺(tái)上均應(yīng)用lower_case_tables_name=1,以強(qiáng)制將名轉(zhuǎn)換為小寫喘蟆。請(qǐng)注意在Unix系統(tǒng)中將lower_case_tables_name設(shè)置為1之前缓升,重啟mysqld之前,必須先將原來的數(shù)據(jù)庫(kù)名以及表名全部轉(zhuǎn)換為小寫履肃。
5仔沿、sql的查詢優(yōu)化原則?
- 根據(jù)存儲(chǔ)引擎提供的統(tǒng)計(jì)信息尺棋,重新定義表的關(guān)聯(lián)順序封锉;參考where語(yǔ)句和庫(kù)表的結(jié)構(gòu)設(shè)計(jì),將外連接轉(zhuǎn)換為內(nèi)連接膘螟;使用等價(jià)變化規(guī)則成福,簡(jiǎn)化where過濾條件中的規(guī)則;將子查詢轉(zhuǎn)換為關(guān)聯(lián)表荆残;提前終止查詢奴艾,如limit限制輸出等;
- 在where的匹配條件中内斯,如果要使用like和%_字符串匹配項(xiàng)蕴潦,最好要放到最后,因?yàn)檫@個(gè)匹配起來最慢俘闯。
- 能使用MySQL的函數(shù)處理查詢結(jié)果時(shí)盡量使用函數(shù)潭苞,比先查出來再在客戶端進(jìn)行處理效果更好,比如對(duì)查詢出的所有訂單的單價(jià)和數(shù)量求總價(jià)真朗。
- 盡量避免子查詢此疹,而用join。
- 在使用Left (right) join的時(shí)候,一定要先在ON給出盡可能多的匹配滿足條件蝗碎,減少Where的執(zhí)行湖笨。
- 盡量用INNER JOIN,避免 LEFT JOIN 和 NULL蹦骑。
- 使用存儲(chǔ)過程會(huì)比一條一條地執(zhí)行更快慈省。
- 如果不是真的需要所有列的數(shù)據(jù),一般別用select *去查詢脊串,數(shù)據(jù)量很大時(shí)很慢辫呻。
- 索引能加快數(shù)據(jù)的查找,但是會(huì)使插入和刪除數(shù)據(jù)性能降低琼锋,如果是頻繁查找的數(shù)據(jù)更建議用索引。
- like很慢祟昭,不如使用FULLTEXT更快缕坎。
- 注意WHERE是在ON匹配產(chǎn)生的結(jié)果的基礎(chǔ)上再過濾一遍。
mysql> SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
AND product_details.id=2;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | 2 | 22 | 0 |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
rows in set (0.00 sec)
mysql> SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
WHERE product_details.id=2;
+----+--------+----+--------+-------+
| id | amount | id | weight | exist |
+----+--------+----+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
+----+--------+----+--------+-------+
row in set (0.01 sec)
從上可知篡悟,第一條查詢使用 ON 條件決定了從 LEFT JOIN的 product_details表中檢索符合的所有數(shù)據(jù)行谜叹。
第二條查詢做了簡(jiǎn)單的LEFT JOIN,然后使用 WHERE 子句從 LEFT JOIN的數(shù)據(jù)中過濾掉不符合條件的數(shù)據(jù)行搬葬。
6荷腊、數(shù)據(jù)庫(kù)的備份和恢復(fù)?
- 備份命令mysqldump急凰,主要是將當(dāng)前數(shù)據(jù)庫(kù)信息全部轉(zhuǎn)為sql的insert語(yǔ)句保存起來
- 格式:
mysqldump -h主機(jī)名 -P端口 -u用戶名 -p密碼 –database 數(shù)據(jù)庫(kù)名 > 文件名.sql
- 備份MySQL數(shù)據(jù)庫(kù)某個(gè)(些)表
mysqldump -hhostname -uusername -ppassword databasename specific_table1 specific_table2 > backupfile.sql
- 備份服務(wù)器上所有數(shù)據(jù)庫(kù)
mysqldump –all-databases > allbackupfile.sql
- 將數(shù)據(jù)庫(kù)轉(zhuǎn)移到新服務(wù)器
mysqldump -uusername -ppassword databasename | mysql –host=*.*.*.* -C databasename
- 常用source命令女仰,用use進(jìn)入到某個(gè)數(shù)據(jù)庫(kù),
mysql>source d:\test.sql
抡锈,后面的參數(shù)為腳本文件疾忍。 - 【增量備份】
小量的數(shù)據(jù)庫(kù)可以每天進(jìn)行完整備份,因?yàn)檫@也用不了多少時(shí)間床三,但當(dāng)數(shù)據(jù)庫(kù)很大時(shí)一罩,就不太可能每天進(jìn)行一次完整備份了,這時(shí)候就可以使用增量備份撇簿。增量備份的原理就是使用了mysql的binlog志聂渊。
1、首先做一次完整備份:
mysqldump -h10.6.208.183 -utest2 -p123 -P3310 --single-transaction --master-data=2 test>test.sql這時(shí)候就會(huì)得到一個(gè)全備文件test.sql
在sql文件中我們會(huì)看到:
-- CHANGE MASTER TO MASTER_LOG_FILE='bin-log.000002', MASTER_LOG_POS=107;是指?jìng)浞莺笏械母膶?huì)保存到bin-log.000002二進(jìn)制文件中四瘫。
2汉嗽、在test庫(kù)的t_student表中增加兩條記錄,然后執(zhí)行flush logs命令莲组。這時(shí)將會(huì)產(chǎn)生一個(gè)新的二進(jìn)制日志文件bin-log.000003诊胞,bin-log.000002則保存了全備過后的所有更改,既增加記錄的操作也保存在了bin-log.00002中。
3撵孤、再在test庫(kù)中的a表中增加兩條記錄迈着,然后誤刪除t_student表和a表。a中增加記錄的操作和刪除表a和t_student的操作都記錄在bin-log.000003中邪码。
- 【恢復(fù)數(shù)據(jù)】
1裕菠、首先導(dǎo)入全備數(shù)據(jù)
mysql -h10.6.208.183 -utest2 -p123 -P3310 < test.sql,也可以直接在mysql命令行下面用source導(dǎo)入
2闭专、恢復(fù)bin-log.000002
mysqlbinlog bin-log.000002 |mysql -h10.6.208.183 -utest2 -p123 -P3310
3奴潘、恢復(fù)部分 bin-log.000003
在general_log中找到誤刪除的時(shí)間點(diǎn),然后更加對(duì)應(yīng)的時(shí)間點(diǎn)到bin-log.000003中找到相應(yīng)的position點(diǎn)影钉,需要恢復(fù)到誤刪除的前面一個(gè)position點(diǎn)画髓。
可以用如下參數(shù)來控制binlog的區(qū)間
--start-position 開始點(diǎn) --stop-position 結(jié)束點(diǎn)
--start-date 開始時(shí)間 --stop-date 結(jié)束時(shí)間
找到恢復(fù)點(diǎn)后,既可以開始恢復(fù)平委。
mysqlbinlog mysql-bin.000003 --stop-position=208 |mysql -h10.6.208.183 -utest2 -p123 -P3310
https://www.cnblogs.com/Cherie/p/3309456.html
7奈虾、數(shù)據(jù)庫(kù)的3大范式?反范式廉赔?
1肉微、第一范式
確保數(shù)據(jù)表中每列(字段)的原子性。
如果數(shù)據(jù)表中每個(gè)字段都是不可再分的最小數(shù)據(jù)單元蜡塌,則滿足第一范式碉纳。
例如:user用戶表,包含字段id,username,password
例如:顧客表(姓名馏艾、編號(hào)劳曹、地址、……)其中"地址"列還可以細(xì)分為國(guó)家攒至、省厚者、市、區(qū)等迫吐。需要拆分成兩個(gè)表:
顧客表——姓名库菲、編號(hào)、地址ID
地址表——主鍵志膀、國(guó)家熙宇、省份、市區(qū)
2溉浙、第二范式
在第一范式的基礎(chǔ)上更進(jìn)一步烫止,目標(biāo)是確保表中的每列都和主鍵相關(guān)。
如果一個(gè)關(guān)系滿足第一范式戳稽,并且除了主鍵之外的其他列馆蠕,都依賴于該主鍵期升,則滿足第二范式。
例如:一個(gè)用戶只有一種角色互躬,而一個(gè)角色對(duì)應(yīng)多個(gè)用戶播赁。則可以按如下方式建立數(shù)據(jù)表關(guān)系,使其滿足第二范式吼渡。
user用戶表容为,字段id,username,password,role_id
role角色表,字段id,name
用戶表通過角色id(role_id)來關(guān)聯(lián)角色表
3.第三范式
在第二范式的基礎(chǔ)上更進(jìn)一步寺酪,目標(biāo)是確保表中的列都和主鍵直接相關(guān)坎背,而不是間接相關(guān)。
例如:一個(gè)用戶可以對(duì)應(yīng)多個(gè)角色寄雀,一個(gè)角色也可以對(duì)應(yīng)多個(gè)用戶得滤。則可以按如下方式建立數(shù)據(jù)表關(guān)系,使其滿足第三范式盒犹。
user用戶表耿戚,字段id,username,password
role角色表,字段id,name
user_role用戶-角色中間表阿趁,id,user_id,role_id
像這樣,通過第三張表(中間表)來建立用戶表和角色表之間的關(guān)系坛猪,同時(shí)又符合范式化的原則脖阵,就可以稱為第三范式。
4.反范式化
反范式化指的是通過增加冗余或重復(fù)的數(shù)據(jù)來提高數(shù)據(jù)庫(kù)的讀性能墅茉。
例如:在上例中的user_role用戶-角色中間表增加字段role_name命黔。
反范式化可以減少關(guān)聯(lián)查詢時(shí),join表的次數(shù)就斤。
8悍募、常用的MySQL函數(shù)處理select查詢的返回值?
-
select CONCAT(name,"+",school) AS stu from students;
拼接返回的多個(gè)列值洋机。得到返回值如"bob+清華大學(xué)" - AS 關(guān)鍵字可以使經(jīng)函數(shù)處理后的數(shù)據(jù)具有一個(gè)別名坠宴,然后就可以讓客戶端根據(jù)別名引用數(shù)據(jù)。如上stu就是拼接后的字符串列的別名绷旗。
- TRIM(name)/RTRIM()/LTRIM()用于對(duì)字段去除左右兩邊的空格喜鼓。
- UPPER()/LOWER()轉(zhuǎn)換成大寫/小寫。
- CURDATE()返回當(dāng)前日期衔肢,CURTIME()返回當(dāng)前時(shí)間庄岖,NOW()返回當(dāng)前日期和時(shí)間。DATE(dt)和TIME(dt)是返回一個(gè)一個(gè)datetime類型數(shù)據(jù)的日期和時(shí)間部分角骤。
- 直接在select后對(duì)各列返回值進(jìn)行+-*/運(yùn)行并取別名隅忿,可以得到結(jié)果列。
- 數(shù)值處理函數(shù),如ABS()取絕對(duì)值背桐,SQRT()取平方根优烧,MOD()取余等。
- 對(duì)返回的某列的數(shù)據(jù)進(jìn)行處理牢撼,COUNT(name)統(tǒng)計(jì)name列的行數(shù)匙隔,即name個(gè)數(shù),
select COUNT(*) from students;
返回行數(shù)即學(xué)生個(gè)數(shù)而不是詳細(xì)的每一行數(shù)據(jù)熏版;MAX(age)返回最大age纷责;MIN(age)返回最小age;AVG(age)返回平均age撼短;SUM(age)返回所有年齡總和再膳,`select SUM(price*quantity) as total_price from orderitems;就是先將單價(jià)和數(shù)量相乘再求和得到總價(jià)。 - DISTINCT 關(guān)鍵字用于將查詢列值只返回不同的
- MATCH(note_text),AGAINST("hello world")函數(shù)組合使用曲横,進(jìn)行全文搜索喂柒。
9、分組查詢GROUP BY禾嫉?分組過濾HAVING(和where過濾的區(qū)別)灾杰?
- GROUP BY 子句必須出現(xiàn)在WHERE子句之后,ORDER BY子句之前熙参。
注意上面的HAVING后的表達(dá)式必須寫完整的而不能用上面的別名艳吠。
- SELECT+FROM+WHERE+GROUP BY+HAVING+ORDER BY+LIMIT;順序
10、MySQL引擎的區(qū)別孽椰?
- 有兩種昭娩,MyISAM和InnoDB,注意引擎是指的表的存儲(chǔ)方式黍匾,而不是數(shù)據(jù)庫(kù)的存儲(chǔ)方式栏渺,同一個(gè)數(shù)據(jù)庫(kù)中不同的表可以使用不同的引擎(創(chuàng)建表時(shí)再最后指定ENGINE=InnoDB),默認(rèn)使用InnoDB锐涯。
- InnoDB支持事務(wù)磕诊,myisam不支持。
- mysiam支持全文索引FULLTEXT全庸,innodb不支持秀仲。
- MyISAM:只支持表級(jí)鎖,用戶在操作myisam表時(shí)壶笼,select神僵,update,delete覆劈,insert語(yǔ)句都會(huì)給表自動(dòng)加鎖保礼,如果加鎖以后的表滿足insert并發(fā)的情況下可以在表的尾部插入新的數(shù)據(jù)沛励。
InnoDB:支持事務(wù)和行級(jí)鎖,是innodb的最大特色炮障。行鎖大幅度提高了多用戶并發(fā)操作的性能目派。
但是InnoDB的行鎖,只是在WHERE的主鍵是有效的胁赢,非主鍵的WHERE都會(huì)鎖全表的企蹭。 - 表主鍵
MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址智末。
InnoDB:如果沒有設(shè)定主鍵或者非空唯一索引谅摄,就會(huì)自動(dòng)生成一個(gè)6字節(jié)的主鍵(用戶不可見),數(shù)據(jù)是主索引的一部分系馆,附加索引保存的是主索引的值的數(shù)據(jù)列送漠。 - MyISAM:如果執(zhí)行大量的SELECT,MyISAM是更好的選擇由蘑。
InnoDB:如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE闽寡,出于性能方面的考慮,應(yīng)該使用InnoDB表尼酿。 - 外鍵
MyISAM:不支持
InnoDB:支持 - 存儲(chǔ)空間
MyISAM:可被壓縮爷狈,存儲(chǔ)空間較小。支持三種不同的存儲(chǔ)格式:靜態(tài)表(默認(rèn)裳擎,但是注意數(shù)據(jù)末尾不能有空格淆院,會(huì)被去掉)、動(dòng)態(tài)表句惯、壓縮表。
InnoDB:需要更多的內(nèi)存和存儲(chǔ)支救,它會(huì)在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引抢野。
通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了各墨,原因是InnoDB自身很多良好的特點(diǎn)指孤,比如事務(wù)支持、更新數(shù)據(jù)更快贬堵、視圖恃轩、存儲(chǔ)過程、行級(jí)鎖定等等黎做,在并發(fā)很多的情況下叉跛,相信InnoDB的表現(xiàn)肯定要比MyISAM強(qiáng)很多。另外蒸殿,任何一種表都不是萬(wàn)能的筷厘,只用恰當(dāng)?shù)尼槍?duì)業(yè)務(wù)類型來選擇合適的表類型鸣峭,才能最大的發(fā)揮MySQL的性能優(yōu)勢(shì)。如果不是很復(fù)雜的Web應(yīng)用酥艳,非關(guān)鍵應(yīng)用摊溶,還是可以繼續(xù)考慮MyISAM的,硬件資源有限也可以使用存儲(chǔ)空間少的MyISAM充石,這個(gè)具體情況可以自己斟酌莫换。
- 存儲(chǔ)引擎選擇的基本原則
采用MyISAM引擎
R/W > 100:1 且update相對(duì)較少
并發(fā)不高
表數(shù)據(jù)量小
硬件資源有限
采用InnoDB引擎
R/W比較小,頻繁更新大字段
表數(shù)據(jù)量超過1000萬(wàn)骤铃,并發(fā)高
安全性和可用性要求高
采用Memory引擎
有足夠的內(nèi)存
對(duì)數(shù)據(jù)一致性要求不高拉岁,如在線人數(shù)和session等應(yīng)用
需要定期歸檔數(shù)據(jù)
11、視圖的使用劲厌?
- 視圖是一種虛擬表膛薛,創(chuàng)建的規(guī)則和限制與表相似,但是注意視圖不能索引补鼻,也不能有關(guān)聯(lián)的觸發(fā)器或默認(rèn)值哄啄。
- 簡(jiǎn)單的視圖可以更新底層表的這列數(shù)據(jù),復(fù)雜的視圖如有分組风范、聯(lián)結(jié)咨跌、子查詢、函數(shù)等的則不允許更新數(shù)據(jù)硼婿,因?yàn)榭赡艿讓泳驼也坏竭@列數(shù)據(jù)锌半。視圖的主要作用還是用于查詢數(shù)據(jù),盡量不要用于更新數(shù)據(jù)寇漫。
12刊殉、存儲(chǔ)過程?
- 存儲(chǔ)過程州胳,為以后使用而保存的一條或多條的SQL語(yǔ)句的組合记焊,具有簡(jiǎn)單、安全和高性能的特點(diǎn)栓撞,和MySQL中函數(shù)相比遍膜,功能更加全面,使用簡(jiǎn)單瓤湘,注意事項(xiàng)如下:
IN瓢颅,使用時(shí)傳遞進(jìn)去參數(shù)類型;OUT,存儲(chǔ)過程使用后傳遞出去類型弛说;
使用中需要使用delimiter暫時(shí)更新存儲(chǔ)過程語(yǔ)句結(jié)束分割符挽懦,否則都使用默認(rèn)的;會(huì)使得存儲(chǔ)過程中的sql語(yǔ)句語(yǔ)法錯(cuò)誤,如下先用//木人,在END結(jié)束存儲(chǔ)過程的創(chuàng)建后又將分隔符設(shè)為默認(rèn)的;號(hào)巾兆。
DELIMITER //
create procedure order_total(
IN order_num int,
OUT order_sum decimal(8,2)
)
BEGIN
select sum(item_price*quantity)
from orderitems where order_id = order_num
into order_sum;
END //
DELIMITER ;
// 調(diào)用這個(gè)存儲(chǔ)過程
call order_total(1001,@total);
// 查看訂單1001的結(jié)果:切記此處需要@
select @total;
//顯示存儲(chǔ)過程的創(chuàng)建語(yǔ)句
show CREATE PROCEDURE order_total;
// 刪除過程:切記此處沒有括號(hào)
dorp prodedure order_total;
//列出所有存儲(chǔ)過程猎物,包括顯示何時(shí)由誰(shuí)創(chuàng)建等信息。
show PROCEDURE STATUS; // LIKE "order_total"; 則是顯示指定的存儲(chǔ)過程的狀態(tài)
13角塑、觸發(fā)器蔫磨?
14、數(shù)據(jù)庫(kù)的索引圃伶?
- 索引底層一般使用B+樹實(shí)現(xiàn)的堤如,將設(shè)為索引的一列值創(chuàng)建一個(gè)對(duì)應(yīng)的B+樹進(jìn)行排序,然后就可以加快查詢窒朋、排序的速度搀罢。
-
一般來說,應(yīng)該在這些列上創(chuàng)建索引:
在經(jīng)常需要搜索的列上侥猩,可以加快搜索的速度榔至;
在作為主鍵的列上,強(qiáng)制該列的唯一性和組織表中數(shù)據(jù)的排列結(jié)構(gòu)欺劳;
在經(jīng)常用在連接的列上唧取,這些列主要是一些外鍵,可以加快連接的速度划提;
在經(jīng)常需要根據(jù)范圍進(jìn)行搜索的列上創(chuàng)建索引枫弟,因?yàn)樗饕呀?jīng)排序,其指定的范圍是連續(xù)鹏往;
在經(jīng)常需要排序的列上創(chuàng)建索引淡诗,因?yàn)樗饕呀?jīng)排序,這樣查詢可以利用索引的排序伊履,加快排序查詢時(shí)間韩容;
在經(jīng)常使用在WHERE子句中的列上面創(chuàng)建索引,加快條件的判斷速度唐瀑。 - MyISAM使用B+Tree作為索引結(jié)構(gòu)宙攻,索引文件和數(shù)據(jù)文件是分離的,索引文件僅保存數(shù)據(jù)記錄的地址介褥。
- InnoDB也使用B+Tree作為索引結(jié)構(gòu),但具體實(shí)現(xiàn)方式卻與MyISAM截然不同递惋。第一個(gè)重大區(qū)別是InnoDB的數(shù)據(jù)文件本身就是索引文件柔滔。而在InnoDB中,表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu)萍虽,這棵樹的葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄睛廊。這個(gè)索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引杉编。
15超全、創(chuàng)建索引的方式咆霜?
- 1、創(chuàng)建索引嘶朱,例如 create index <索引的名字> on table_name (列的列表);
2蛾坯、修改表,例如 alter table table_name add index[索引的名字] (列的列表);
3疏遏、創(chuàng)建表的時(shí)候指定索引脉课,例如create table table_name ( [...], INDEX [索引的名字] (列的列表) ); - 查看表中索引的方法:
show index from table_name; 查看索引 - 刪除索引
- 索引的類型及創(chuàng)建例子::
1.PRIMARY KEY (主鍵索引)
MySQL> alter table table_name add primary key (column
)
2.UNIQUE 或 UNIQUE KEY (唯一索引)
mysql> alter table table_name add unique (column
)
3.FULLTEXT (全文索引)
mysql> alter table table_name add fulltext (column
)
4.INDEX (普通索引)
mysql> alter table table_name add index index_name (column
)
5.多列索引 (組合索引)——最左前綴原則,即先匹配左邊的列
mysql> alter tabletable_name
add index index_name (column1
,column2
,column3
)
16财异、sqlite3數(shù)據(jù)庫(kù)和MySQL數(shù)據(jù)庫(kù)的區(qū)別倘零?
- sqlite是基于文件的數(shù)據(jù)庫(kù)就是一個(gè)結(jié)構(gòu)化的文件,程序只需要引用相應(yīng)的C庫(kù)函數(shù)就可以像讀寫文件一樣訪問該數(shù)據(jù)庫(kù)戳寸,而不用像MySQL一樣使用socket進(jìn)程間通信呈驶,省掉了一次數(shù)據(jù)庫(kù)遠(yuǎn)程鏈接沒有復(fù)雜的權(quán)限驗(yàn)證,打開就能操作疫鹊。
- sqlite數(shù)據(jù)庫(kù)沒有多用戶管理袖瞻,因此不支持多用戶并發(fā)訪問,該文件的訪問權(quán)限只和文件的訪問權(quán)限設(shè)置有關(guān)订晌。
- 使用輕便快速虏辫,適合單機(jī)服務(wù)器使用數(shù)據(jù)量不超過百萬(wàn)無壓力,sql語(yǔ)句大部分功能都兼容锈拨,有增有刪砌庄。