Python是一種具備對象、模塊、線程、異常和自動內存管理的編程語言。javascript
Python的好處是它簡單、易用、可移植、可擴展、內置數據結構、而且是開源的。
css
PEP8是一種編碼規範,中文意思「Python加強建議書」也可叫作「Python改進建議書」這個文檔主要是用來規範 Python 代碼的寫法。html
縮進:4個空格的縮進,不能混合使用Tab和空格。前端
每行最大長度79,換行能夠使用反斜槓,最好使用圓括號。vue
類和top-level函數定義之間空兩行;類中的方法定義之間空一行;函數內邏輯無關段落之間空一行;其餘地方儘可能不要再空行。java
模塊導入的順序:按標準、三方和本身編寫順序依次導入,之間空一行。python
不要在一句import中多個庫,好比import os, sys不推薦mysql
避免沒必要要的空格jquery
註釋必需要有linux
函數命名要遵循規範
儘量使用‘is’‘is not’取代‘==’,好比if x is not None 要優於if x。
使用基於類的異常,每一個模塊或包都有本身的異常類,此異常類繼承自Exception。
異常中try的代碼儘量少。
在 Python3 中,input()獲取用戶輸入,不論用戶輸入的是什麼,獲取到的都是字符串類型的。
在 Python2 中有 raw_input()和 input(), raw_input()和 Python3 中的 input()做用是同樣的,input()輸入的是什麼數據類型的,獲取到的就是什麼數據類型的。
方法一:
方法二:
read:讀取整個文件。
readline:讀取下一行,使用生成器方法。
readlines:讀取整個文件到一個迭代器以供咱們遍歷。
會繼續處理finally中的代碼。
使用raise方法能夠拋出自定義異常。
except:捕獲全部異常
except: <異常名> 捕獲自定異常
except:<異常名1, 異常名2, ...> 捕獲多個異常
except: <異常名> , <數據> 捕獲指定異常及其附加的數據
except:<異常名1, 異常名2>: <數據> 捕獲異常名1或者異常名2,及其附加的數據
系統庫:
第三方庫:
init在對象建立後,對對象進行初始化。
new是在對象建立以前建立一個對象,並將該對象返回給init。
能夠使用Python提供的random模塊生成隨機數。
舉🌰
random.random() 生成一個 0-1 之間的隨機浮點數。
random.uniform(a, b) 生成 a-b 之間的浮點數。
random.randint(a, b) 生成 a-b 之間的整數。
random.randrange(a, b, step) 在指定的集合[a, b)中,以step爲基數隨機取一個數。
random.choice(sequence) 從特定序列中隨機取一個元素,這裏的序列能夠使字符串,列表,元祖等。
os.path主要是用於對系統路徑文件的操做。
sys.path主要是對Python解釋器的系統環境參數的操做(動態的改變Python解釋器搜索路勁)。
方法太多,挑幾個容易記的
os.remove()刪除文件
os.rename()重命名文件
os.walk()生成目錄樹下的全部文件名
os.chdir()改變目錄
os.mkdir/makedirs 建立目錄/多層目錄
os.rmdir/removedirs 刪除目錄/多層目錄
os.listdir()列出指定目錄的文件
os.getcwd()取得當前工做目錄
os.chmod()改變目錄權限
os.path.basename()去掉目錄路徑,返回文件名
os.path.dirname()去掉文件名,返回目錄路徑
os.path.join()將分離的各部分組合成一個路徑名
os.path.split()返回(dirname(),basename())元組
os.path.splitext()(返回 filename,extension)元組
os.path.getatime\ctime\mtime 分別返回最近訪問、建立、修改時間
os.path.getsize()返回文件大小 • os.path.exists()是否存在
os.path.isabs()是否爲絕對路徑
os.path.isdir()是否爲目錄
os.path.isfile()是否爲文件
方法太多,挑幾個容易記的
sys.exit(n) 退出程序,正常退出時 exit(0)
sys.version 獲取 Python 解釋程序的版本信息
sys.argv 命令行參數 List,第一個元素是程序自己路徑
sys.modules.keys() 返回全部已經導入的模塊列表
sys.argv 命令行參數 List,第一個元素是程序自己路徑
sys.maxint 最大的 Int 值
sys.path 返回模塊的搜索路徑,初始化時使用 PYTHONPATH 環境變量的值
sys.platform 返回操做系統平臺名稱
sys.stdout 標準輸出
sys.stdin 標準輸入
sys.stderr 錯誤輸出
sys.path 返回模塊的搜索路徑,初始化時使用 PYTHONPATH 環境變量的值
在Python中,模塊是搭建程序的一種方式。每個Python代碼文件都是一個模塊,並能夠引用其餘的模塊,好比對象和屬性。
一個包包含許多Python代碼的文件夾就是一個包。一個包能夠包含模塊和子文件夾。
Python是強類型的動態腳本語言。
強類型:不容許不一樣類型相加
動態:不須要聲明數據類型,且肯定一個變量的類型是在第一次給它賦值的時候。
腳本語言:通常也是解釋型語言,運行diamante只須要一個解釋器,不須要編譯。
解釋型語言在程序運行的時候纔會進行翻譯。
編譯型語言在執行以前,須要一個專門的編譯過程,把程序編譯成機器語言(可執行文件)。
使用多線程,充分利用機器的多核性能。
對於性能影響較大的部分代碼,能夠使用 C 或 C++ 編寫。
對於 IO 阻塞形成的性能影響,能夠使用 iO 多路複用來解決。
儘可能使用 Python 的內建函數。
儘可能使用局部變量。
字典
列表
元祖
集合
set:集合,在Python中的書寫方式爲大括號"{}",集合與以前的列表、元祖相似,能夠儲存多個數據,可是這些數據是不能夠重複的。
集合對象支持union(聯合)、intersection(交)、difference(差)和sysmmetric_difference(對稱差集)等數學運算
字典是一種數據結構,json是一種數據的表現形式。
字典的key值只要是能hash的就行,json的必須是字符串。
可變不可變指的是內存中的值是否能夠被改變
不可變類型指的是對象所在內存塊裏面的值不能夠改變,如:數值、字符串、元祖
可變類型則是能夠改變,如:列表、字典
有三種不一樣的含義
轉義字符
路徑名中用來鏈接路徑名
代碼太長手動軟換行
類方法:是類對象的方法,在定義時須要在上方使用」@classmethod「進行裝飾,形參爲cls,表示類對象,類對象和示例對象均可調用。
類實例方法:是類實例化對象的方法,只有實例對象能夠調用,形參爲self,指表明對象自己。
靜態方法:是一個任意函數,在其上方使用」@staticmethod「進行裝飾,能夠用對象直接調用;靜態方法實際上跟該類沒有太多的關係。
Python內存由Python專用堆空間管理。全部Python對象和數據結構都位於私有堆中。程序員無權訪問此私有堆,解釋器負責處理此Python私有堆。
爲Python對象分配Python堆空間是由Python內存管理器完成的。核心API容許訪問一些工具,以便程序員進行編碼。
Python還具備一個內置的垃圾收集器,該垃圾收集器回收全部未使用的內存,並釋放內存並使之可用於堆空間。
內存泄漏是指因爲疏忽或錯誤形成程序未能釋放已經再也不使用的內存。內存泄漏並不是指內存在物理上的消失,而是應用程序分配某段內存後因爲設計錯誤,失去對該段內存的控制,所以形成了內存的浪費;致使程序運行速度減慢甚至系統崩潰等嚴重後果。
當不使用對象時能夠使用:del object來刪除一個對象的引用計數就能夠有效防止內存泄漏問題。
Python的參數傳遞有:位置參數、默認參數、可變參數、關鍵字參數。
函數究竟是值傳遞仍是引用傳遞要看實際狀況。
缺省參數指在調用函數的時候沒有傳入參數的狀況下,調用默認的參數,在調用函數的同時賦值時所傳入的參數會替代默認參數。
*args 是不定長參數,表示傳入參數是不肯定的;能夠是任意多個。
**kwargs 是關鍵字參數,賦值的時候是以鍵 = 值的方式,參數是能夠任意多對;在定義函數的時候不肯定會有多少個參數傳入時就能夠使用兩個參數。
內建類型:布爾類型、數字、字符串、列表、元祖、字典、集合
輸出字符串 ‘a’ 的內建方法
lambda 是一個匿名函數,它能夠接受任意多個參數(包括可選參數)而且返回單個表達式值得函數。
lambda 函數的好處:
lambda 函數比較輕便,即用即扔,很適合須要完成一項功能,可是此項功能只在此一處使用,連名字都很隨意的狀況下。
匿名函數,通常用來給 filter,map 這樣的函數式編程服務。
做爲回調函數,傳遞給某些應用;好比消息處理。
概念:單例模式是一種常見的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。好比,某個服務器的配置信息存在一個文件中,客戶端須要經過appConfig的類來讀取配置文件的信息。若是有不少地方都須要使用配置文件的內容,也就是說不少地方都須要建立AppConfig對象的示例,這就致使系統中存在多個AppConfig的示例對象,從而嚴重浪費系統資源。事實上,相似AppConfig這樣的類咱們但願在程序運行期間只存在一個實例對象,這個時候就該考慮使用咱們的單利模式。
場景:
網站的計數器
應用配置
多線程池
數據庫配置
數據庫鏈接池
應用程序的日誌應用等
Python裝飾器是用於拓展原來的函數功能的一種函數,使用Python裝飾器的好處就是在不更改原來函數的代碼前提下給函數增長新的功能。
裝飾器遵循的原則:
對功能的拓展開放
對代碼的修改封閉
迭代器是一個抽象的概念,任何對象,若是它的類有 next 方法和 iter 方法返回本身自己,對於 str、list、dict、tuple等這類容器對象,使用for循環遍歷是很方便的。
生成器是建立迭代器簡單而強大的工具。它們寫起來就像是正則的函數,只是在須要返回數據的時候使用yield 語句。每次 next() 被調用時,生成器會返回它脫離的位置。
區別:生成器能夠簡潔高效的自動建立 iter() 和 next() 方法,它能夠完成迭代器的全部事情,使用生成器能夠表達式取代列表解析能夠節省內存。迭代器在沒有後續元素時,next()會拋出一個StopIteration異常。
不可變對象:該對象所指向的內存中的值不能被改變。當改變某個變量是,因爲其所指的值不能被改變,至關於把原來的值複製一份後再改變,而且開闢一個新的地址;變量再指向這個新的地址。
可變對象:該對象所指向的內存中的值能夠被改變,變量改變後,其實是其所指的值直接發生改變,而且沒有複製和開闢新的地址,通俗說就是原地改變。
is 是經過 a 對象和 b 對象的 id 來判斷的
== 判斷的是 a 對象和 b 對象的值是否相等,經過 value 來判斷。
面向對象時至關於面向過程而言,面向過程是一種基於功能分析、以算法爲中心的程序設計方法;而面向對象是一種基於結構分析、以數據爲中心的程序設計思想。在面嚮對象語言中有一個重要的東西就是類。
面向對象的三大特性:
封裝:
繼承:
多態:
match()函數只檢測 RE 是否是 string 的開始位置匹配
search()會掃描整個 string 查找匹配
也就是說 match() 只有在 0 位置匹配成功的話纔有返回,若是不是開始位置匹配成功的話,match()就會返回 None
- re.findall(r'目的字符串', '原有字符串') # 查詢
- re.findall(r'du', 'baidu.com')[0]
- re.sub(r'要替換原字符', '要替換新字符', '原字符串')
- re.sub(r'world', 'python', 'helloworld')
進程:一個運行的程序或者代碼就是一個進程,進程是系統資源分配的最小單位,進程擁有本身獨立的內存空間,因此進程數據不共享,開銷大。
線程:調度執行的最小單位,也叫執行路徑,線程不能獨立存在,它必須依賴於進程。一個進程中至少有一個線程,也叫主線程。多個線程之間共享內存(數據共享、共享全局變量)從而極大提升了程序的運行效率。
協程:是一種用戶態的輕量級線程,協程的調度徹底由用戶控制;協程擁有本身的寄存器上下文和棧。
多進程優勢:
每一個進程相互獨立,不影響主程序的穩定性;子進程崩潰也不要緊。
經過增長CPU,就能夠擴充性能
能夠儘可能減小線程加鎖/解鎖的影響,極大提升性能,就算是線程運行的模塊算法效率低也不要緊
每一個子進程都有2GB地址空間和相關資源,整體可以達到的性能上限很是大
多進程缺點:
邏輯複雜,須要和主程序交互
須要跨進程邊界,不適合大量數據傳送;多進程協調開銷大
多線程優勢:
無需跨進程邊界
程序邏輯和控制方式簡單
全部線程能夠直接共享內存和變量等
線程方式消耗的總資源比進程方式好
多線程缺點:
每一個線程與主程序公用地址空間,受限於2GB地址空間
線程之間的同步和加鎖控制比較麻煩
一個線程崩潰可能影響到整個程序的穩定性
達到必定線程數後,即便再增長CPU也沒法提升性能
線程可以提升的總性能有限,並且線程多了以後,線程自己的調度也是個麻煩事,須要消耗較多的CPU
能夠經過加鎖來解決多線程之間的競爭。
加鎖的好處:
加鎖的壞處:
阻止了多線程併發執行,包含鎖的某段代碼實際上只能以單線程模式執行
因爲能夠存在多個鎖,不一樣的線程持有不一樣的鎖;並試圖獲取對象持有的鎖時就有可能形成死鎖
全局解釋器鎖(GIL):
全局解釋器鎖在 Cpython 裏纔有,它限制了多線程同時執行,同一個進程中只要有一個線程獲取了全局解釋期(CPU)的使用權,那麼其它線程就必須等待該線程的全局解釋器(CPU)使用權消失後才能使用全局解釋器(CPU)。其實 cpython 中的多線程是僞多線程,因此不少時候使用協程來代替多線程,協程也就至關因而一種更輕量級的線程。
全局解釋器鎖的優勢:
全局解釋器鎖的缺點:
同步鎖:
遞歸鎖(可重入鎖)和死鎖:
死鎖:
遞歸鎖(可重入鎖):
每一個對象都對應於一個可稱爲" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。
同一個進程中的多線程之間是共享系統資源的,多個線程同時對一個對象進行操做,一個線程操做還沒有結束,另外一個線程已經對其進行操做,致使最終結果出現錯誤,此時須要對被操做對象添加互斥鎖,保證每一個線程對該對象的操做都獲得正確的結果。每一個對象都對應於一個可稱爲" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。
同步:提交完任務後就在原地等待,知道任務運行完畢後,拿到任務的返回值才繼續執行下一行代碼。如:打電話
異步:提交完任務後不在原地等待,直接執行下一行。如:發短信
阻塞:遇到 I/O 操做時就發生阻塞,程序一旦遇到阻塞操做就會停在原地,而且馬上釋放CPU資源。
非阻塞(就緒態或運行態):沒有遇到 I/O操做,或者經過某種手段讓程序即使遇到 I/O 操做也不會停留在原地,執行其餘操做,力求儘量多佔用CPU。
不管是並行仍是併發,在用戶看來都是‘同時’運行的,無論是進程仍是線程都只是一個任務而已;真的幹活的仍是CPU,而一個CPU同一個時刻只能執行一個任務。
併發:是僞並行,即看起來是同時運行。
並行:同時運行,只有具有多個CPU的狀況下才能實現並行
殭屍進程:一個進程使用 fork 建立子進程,若是子進程退出,而父進程並無調用 wait 或 waitpid 獲取子進程的狀態信息,那麼子進程的進程描述任然保留在系統中;這種進程稱之爲殭屍進程。
孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼這些子進程將成爲孤兒進程。孤兒進程將被 init 進程(進程號爲1)所收養,並由 init 進程對它們完成狀態收集工做。
避免方案:
fork 兩次用孫子進程去完成子進程的任務
用 wait() 函數使父進程阻塞
使用信號量,在 signal handler 中調用 waitpid,這樣父進程不用阻塞
解決方案:
SIGCHLD 信號處理:
暴力出奇跡:
查看父進程命令:
ps -ef |grep def 查看殭屍進程 ps -e -o pid,stat |grep Z 查看殭屍進程PID ps -e -o ppid,stat |grep Z 查看殭屍進程的父進程
多進程適合在 CPU 密集型操做(CPU 操做指令比較多,如位數多的浮點運算)。
多線程適合在 IO 密集型操做(讀寫數據操做較多的好比爬蟲)。
線程是併發,進程是並行
進程之間相互獨立,是系統分配資源的最小單位,同一個線程中的全部線程共享資源。
並行:同一時刻多個任務同時在運行。
併發:在同一個時間間隔內多個任務都在運行,可是並不會在同一時刻同時運行,存在交替執行的狀況。
當程序須要執行較多的讀寫、請求和回覆任務須要大量的 IO 操做時;IO 密集型操做使用併發更好。
CPU 運算量大的程序使用並行會更好。
IO 密集型:在系統運做時大部分的狀況下都是CPU在等 I/O(硬盤/內存)的讀寫。
CPU 密集型:大部分時間用來作計算、邏輯判斷等 CPU 動做的程序就稱之爲CPU密集型。
使用 udp 發送/接收數據不收:
建立客戶端套接字
發送/接收數據
關閉套接字
import socket def main(): # 一、建立 udp 套接字 # socket.AF_INET 表示 IPv4 協議,AF_INET6 表示 IPv6 協議 # socket.SOCK_DGRAM 數據報套接字,主要用於 udp 協議 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 二、準備接收方的地址 # 元祖類型 ip 是字符串類型 端口爲整型 dest_addr = ('192.168.*.*', 8888) # 要發送的數據 send_data = '我是要發送的數據(#^.^#)' # 三、發送數據 udp_socket.sendto(send_data.encode("utf-8"), dest_addr) # 四、等待接收方發送的數據 若是沒有收到數據則會阻塞等待,直到收到數據 # 接收到的數據是一個元組 (接收到的數據, 發送方的 ip 和端口) # 1024 表示本次接收的最大字節數 recv_data, addr = udp_socket.recvfrom(1024) # 五、關閉套接字 udp_socket.close() if __name__ == '__main__': main()
編碼的轉換
str --> bytes:encode 編碼 bytes -->
str:decode() 解碼
UDP 綁定端口號:
建立 socket 套接字
綁定端口號
接收/發送數據
關閉套接字
import socket def main(): # 一、建立 udp 套接字 # socket.AF_INET 表示 IPv4 協議 AF_INET6 表示 IPv6 協議 # socket.SOCK_DGRAM 數據報套接字,只要用於 udp 協議 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 二、綁定端口 # 元組類型 ip 通常不寫 表示本機的任何的一個 ip local_addr = ('', 7777) udp_socket.bind(local_addr) # 三、準備接收方的地址 # 元組類型 ip 是字符串類型 端口號是整型 dest_addr = ('192.168.*.*', 8888) # 要發送的數據 send_data = "我是要發送的數據" # 四、發送數據 udp_socket.sendto(send_data.encode("utf-8"), dest_addr) # 五、等待接收方發送的數據 若是沒有收到數據則會阻塞等待,直到收到數據 # 接收到的數據是一個元組 (接收到的數據, 發送方的 ip 和端口) # 1024 表示本次接收的最大字節數 recv_data, addr = udp_socket.recvfrom(1024) # 六、關閉套接字 udp_socket.close() if __name__ == '__main__': main()
TCP 客戶端的建立流程:
建立 TCP 的 socket 套接字
鏈接服務器
發送數據給服務器端
接收服務器端發送來的消息
關閉套接字
import socket def main(): # 一、建立客戶端的 socket # socket.AF_INET 表示 IPv4 協議 AF_INET6 表示 IPv6 協議 # socket.SOCK_STREAM 流式套接字,只要用於 TCP 協議 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 二、構建目標地址 server_ip = input("請輸入服務器端的 IP 地址:") server_port = int(input("請輸入服務器端的端口號:")) # 三、鏈接服務器 # 參數:元組類型 ip 是字符串類型 端口號是整型 client_socket.connect((server_ip, server_port)) # 要發送給服務器端的數據 send_data = "我是要發送給服務器端的數據" # 四、發送數據 client_socket.send(send_data.encode("gbk")) # 五、接收服務器端恢復的消息, 沒有消息會阻塞 # 1024 表示接收的最大字節數 recv_date= client_socket.recv(1024) print("接收到的數據是:", recv_date.decode('gbk')) # 六、關閉套接字 client_socket.close() if __name__ == '__main__': main()
TCP 服務器的建立流程:
建立 TCP 服務端的 socket
bing 綁定 ip 地址和端口號
listen 使套接字變爲被動套接字
accept 取出一個客戶端鏈接,用於服務
recv/send 接收和發送消息
關閉套接字
import socket def main(): # 一、建立 tcp 服務端的 socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 二、綁定 server_socket.bind(('', 8888)) # 三、listen 使套接字變爲被動套接字 server_socket.listen(128) # 四、若是有新的客戶端來連接服務器,那麼就產生一個新的套接字專門爲這個客戶端服務 # client_socket 用來爲這個客戶端服務 # tcp_server_socket 就能夠省下來專門等待其餘新客戶端的連接 client_socket, client_addr = server_socket.accept() # 五、接收客戶端發來的消息 recv_data = client_socket.recv(1024) print("接收到客戶端%s 的數據:%s" % (str(client_addr), recv_data.decode('gbk'))) # 六、回覆數據給客戶端 client_socket.send("收到消息".encode('gbk')) # 七、關閉套接字 client_socket.close() server_socket.close() if __name__ == '__main__': main()
注意:
tcp 服務器通常都須要綁定,不然客戶端找不到服務器
tcp 客戶端通常不綁定,由於是主動連接服務器,因此只要肯定好服務器的 ip、port 等信息就好,本地客戶端能夠隨機
UDP 是面向無鏈接的通信協議,UDP 數據包括目的端口號和源端口號信息。
優勢:速度快、操做簡單、佔用系統資源少、無需創建鏈接可實現廣播發送。
缺點:因爲沒有創建鏈接,並不知道對方是否正確接收數據,不可靠。
TCP 是面向鏈接的通信協議,須要經過三次握手和四次揮手來完成通信。
優勢:傳遞數據時有確認、窗口、續傳、阻塞等控制機制,可以確保數據的正確性,較爲可靠。
缺點:相較於 UCP 速度稍慢,佔用資源較多。
瀏覽器發送請求給web服務器
web服務器接收到動態請求後經過wsgi協議調用框架
框架根據請求信息向數據庫獲取動態數據
框架將獲取的動態數據插入模板文件,構成響應體
框架將響應體數據、響應狀態碼和說明、響應頭信息返回給web服務器
web服務器接收到框架提供的數據後將數據按照響應報文的格式編碼發送給瀏覽器
瀏覽器接收到相應數據後,經過解碼並按照http協議格式顯示在界面上
先要解析出baidu.com對應的地址
先經過arp獲取默認網關(交換機)的mac地址(mac地址指的是物理地址)(UDP廣播)
組織數據發送給默認網關(ip是dns服務器的ip,mac是默認網關的mac地址)
默認網關(交換機)擁有轉發數據的能力,把數據轉發給路由器
路由器根據本身的路由協議,選擇一個合適的較快的路徑轉發數據給目的網關
目的網關(dns服務器所在的網關)把數據轉發給dns服務器
dns服務器查詢解析出baidu.com對應的IP地址,並將它原路返回給請求這個域名的client
獲得了baidu.com對應的ip地址後,會發送tcp三次握手進行鏈接
使用http協議發送請求數據給web服務器
web服務器收到數據請求以後,經過查詢本身的服務器獲得相應的結果,原路返回給瀏覽器
瀏覽器接收到數據後,經過瀏覽器本身的渲染功能來顯示這個網頁
瀏覽器關閉鏈接,即四次揮手
傳參區別:
GET請求傳參會將表單中的信息使用URL拼接的方法顯示到瀏覽器的地址欄中,不安全。
post傳參不會暴露信息,安全
GET方法屬於URL參數傳遞信息 以?進行拼接,多個參數使用&形式鏈接
post會將信息放在請求主體中,這樣的信息是不會暴露的。
長度限制:
get傳參有長度限制,超過限制後直接報錯。60KB
post傳參長度不受限制。
緩存:
get方式傳遞參數瀏覽器會直接緩存數據,不管多重要的信息瀏覽器都會緩存。
POST方式瀏覽不會直接緩存到,比較安全。
特色:
Post:安全
get惟一的好處就是比post快。
cookie 數據存放在客戶的瀏覽器上,session 數據放在服務器上。
cookie 不是很安全,別人能夠分析存放在本地的 cookie 並進行 cookie 欺騙考慮到安全應當使用 session。
session 會在必定時間內保存在服務器上。當訪問增多,會比較佔用服務器的性能考慮到減輕服務器性能方面,應當使用 cookie。
單個 cookie 保存的數據不能超過 4K,不少瀏覽器都限制一個站點最多保存 20 個 cookie。
建議: 將登錄信息等重要信息存放爲 SESSION 其餘信息若是須要保留,能夠放在 cookie 中
經過狀態碼告訴客戶端服務器的執行狀態,以判斷下一步該執行什麼操做。
常見的狀態機器碼有:
100-199:表示服務器成功接收部分請求,要求客戶端繼續提交其他請求才能完成整個處理過程。
200-299:表示服務器成功接收請求並已完成處理過程,經常使用 200(OK 請求成功)。
300-399:爲完成請求,客戶須要進一步細化請求。302(全部請求頁面已經臨時轉移到新的 url)。
30四、307(使用緩存資源)。
400-499:客戶端請求有錯誤,經常使用 404(服務器沒法找到被請求頁面),403(服務器拒絕訪問,權限不夠)。
500-599:服務器端出現錯誤,經常使用 500(請求未完成,服務器遇到不可預知的狀況)。
TCP 三次握手流程圖
專業版流程:
第一次握手:Client將標誌位SYN置爲1,隨機產生一個值seq=J,並將該數據表發送給Server,Client進入SYN_SENT狀態,等待Server確認。
第二次握手:Server收到數據包後由標誌位SYN=1知道了Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認鏈接請求,Server進入SYN_RCVD狀態。
第三次握手:Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,若是正確則將標誌位置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,開始傳輸數據。
簡潔版流程
第一次握手:客戶端向服務端發起請求:我想給你通訊,你準備好了麼?
第二次握手:服務端收到請求後迴應客戶端:'ok,你準備好了麼。
第三次握手:客戶端禮貌的再次回一下客戶端:準備就緒,我們開始通訊吧!
補充:SYN-請求詢問,ACK-迴應
TCP 四次揮手流程圖
簡潔版流程:
因爲 TCP 鏈接是能夠雙向通訊的(全雙工),所以每一個方向都必須單獨進行關閉;客戶端和服務端均可以先開始斷開鏈接
四次揮手過程:
第一次揮手:客戶端發送帶有 fin 標識的報文給服務端,請求通訊關閉
第二次揮手:服務端收到信息後,回覆 ACK 答應關閉客戶端通訊(鏈接)請求
第三次揮手:服務端發送帶有 fin 標識的報文給客戶端,也請求關閉通訊
第四次揮手:客戶端迴應 ack 給服務端,答應關閉服務端的通訊(鏈接)請求
第一次握手:客戶端先向服務器發出加密通訊的請求,而且提供本身的一些信息(加密方法等),這被叫作ClientHello請求。
第二次握手:服務器收到客戶端請求後,向客戶端發出迴應,而且提供服務器證書、確認的加密方法等,這叫作SeverHello。
第三次握手:客戶端收到服務器迴應之後,首先驗證服務器證書,若是沒問題的話會向服務器發送用於加密的隨機數、編碼改變通知、客戶端握手結束通知。
第四次握手:服務器收到客戶端的隨機數以後,計算生成本次會話所用的"會話密鑰",而後向客戶端發送編碼改變通知和服務器握手結束通知。
三次握手
在創建鏈接時只須要經過三次握手便可完成。
舉個生活中打電話的例子:
小明給小紅打電話
小明:去逛街,你準備好了嗎?(第一次握手)
小紅:嗯,準備好了;你準備好了嗎?(第二次握手)
小明:我也準備好了,走吧!(第三次握手)
當雙方都準備好的時候就能夠去逛街了....
三次握手的好處確保了雙方都知道彼此已經準備好
四次揮手
由於 TCP 鏈接是雙向通訊的,所以雙方都必須單獨進行關閉
第一次揮手:客戶端發送帶有 fin 標識的報文給服務端,請求通訊關閉
第二次揮手:服務端收到信息後,回覆 ACK 答應關閉客戶端通訊(鏈接)請求
第三次揮手:服務端發送帶有 fin 標識的報文給客戶端,也請求關閉通訊
第四次揮手:客戶端迴應 ack 給服務端,答應關閉服務端的通訊(鏈接)請求
注意:客戶端收到服務器的確認以後,啓動2MSL定時器,在time_wait狀態還需再等2MSL(最大報文段生存時間),纔會close。防止第四步的確認數據包丟失,萬一確認服務器沒有收到,服務器再發送FIN時,客戶端還能給服務器確認。
主動發送 fin 關閉的一方,在 4 次揮手最後一次要等待一段時間咱們稱這段時間爲 2MSL。
假定網絡是不可靠的,有可能最後一個ACK丟失。因此TIME_WAIT狀態就是用來重發可能丟失的ACK報文。若是服務器沒有收到ACK,將不斷重複發送FIN片斷。因此客戶端不能當即關閉,要確保服務器接收到該ACK。若是直到2MSL結束客戶端都沒有再次收到FIN,那麼客戶端推測ACK已經被成功接收,則關閉TCP鏈接。
TIME_WAIT 狀態的好處:
讓四次揮手關閉流程更加可靠
防止丟包後對後續創建的正常鏈接傳輸形成破壞
三次握手完成了兩個重要的功能,既要雙方作好發送數據的準備工做(雙方都知道彼此已經準備好),也要容許雙方就初始序列化進行協商,這個序列化在握手過程當中被髮送和確認。
若是把三次握手改成兩次握手,有可能會形成死鎖。
舉個例子:
客戶端和服務端之間的通訊,假定客戶端給服務端發送一個創建連接請求分組,服務器收到了這個分組,併發送了答應分組。
按照兩次握手的協定,服務器認爲鏈接已經成功創建了,能夠開發發送數據分組。但是,客戶端在沒有收到服務端發送過來答應分組的狀況下,客戶端將不知道服務端是否已準備好,不知道服務端創建什麼樣的序列號,客戶端甚至懷疑服務端是否收到本身的鏈接請求分組。在這種狀況下,客戶端認爲鏈接尚未創建成功,將忽略服務端發來的任何數據分組,只等待鏈接確認答應分組。而服務端發出的分組超時後,重複發送一樣的分組,就這樣造成了死鎖。
TCP 設有一個保活計時器,客戶端若是出現故障,服務器不能一直等下去白白浪費資源。
服務器每收到一次客戶端的請求後都會從新復位這個計時器,時間一般設置爲2小時,若兩小時尚未收到客戶端的任何數據,服務器就會發送一個探測報文段,之後每隔75秒鐘發送一次,若一連發送10個探測報文任然沒有反應,服務器就認爲客戶端出了故障,接着就關閉鏈接。
在三次握手過程當中,服務器發送SYN-ACK以後,收到客戶端的ACK以前的TCP鏈接稱爲半鏈接(half-open connect).此時服務器處於Syn_RECV狀態.當收到ACK後,服務器轉入ESTABLISHED狀態。
Syn攻擊就是 攻擊客戶端 在短期內僞造大量不存在的IP地址,向服務器不斷地發送syn包,服務器回覆確認包,並等待客戶的確認,因爲源地址是不存在的,服務器須要不斷的重發直 至超時,這些僞造的SYN包將長時間佔用未鏈接隊列,正常的SYN請求被丟棄,目標系統運行緩慢,嚴重者引發網絡堵塞甚至系統癱瘓。
Syn攻擊是一個典型的DDOS攻擊。檢測SYN攻擊很是的方便,當你在服務器上看到大量的半鏈接狀態時,特別是源IP地址是隨機的,基本上能夠判定這是一次SYN攻擊。
在Linux下能夠使用netstat -n -p TCP | grep SYN_RECV1命令檢測是否被 Syn攻擊。
HTTPS 協議須要到 CA(電子商務認證受權機構) 中心申請證書,通常免費證書較少;須要必定費用。
HTTP 協議是超文本傳輸協議,使用明文方式傳輸信息,HTTPS 則是具備安全性的 SSL 加密傳輸協議。
HTTP 和 HTTPS 使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是 80,後者是 443。
SSL是一種實現網絡通訊加密的安全協議,可在客戶端(瀏覽器)和服務器端(網站)之間創建一條加密通道,保證數據在傳輸過程當中不被竊取或篡改。
SSL證書,也稱爲服務器SSL證書,是遵照SSL協議的一種數字證書,由全球信任的證書頒發機構(CA)驗證服務器身份後頒發。將SSL證書安裝在網站服務器上,可實現網站身份驗證和數據加密傳輸雙重功能。
HTTP1.1 共有八種請求方式,分別是 GET、POST、PUT、DELETE、HEAD、TRACE、CONNECT。
經常使用的四種請求方式:
GET: 請求指定的頁面信息,並返回實體主體。
POST: 向指定資源提交數據進行處理請求,如提交把表單或上傳文件;數據被包含在請求體中。
PUT: 從客戶端向服務器傳送的數據取代指定的文檔內容。
DELETE: 請求服務器刪除指定的頁面。
不經常使用的四種請求方式:
HEAD: 相似於 GET 請求,只不過返回的響應體中沒有具體內容,用於獲取報頭。
CONNECT: HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
OPTIONS: 容許客戶端查看服務器的性能。
TRACE: 回顯服務器收到的請求,主要用於測試或診斷。
IP: 網絡層
TCP/UDP: 傳輸層
HTTP、RTSP、FTP: 應用層協議
七層模型:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層
URL(Uniform Resource Locator) ,統一資源定位符,可以對因特網的資源進行定位。
URL 通常有四部分組成: <協議> ://< 主機 >:< 端口 >/< 路徑 >
如今最經常使用的 <協議> 爲 http 協議。
<主機> 是指主機在因特網上的域名。(ip 地址 + 子網掩碼 = 主機號)
http 協議的默認 <端口> 爲 80(能夠省略)。
httpS 協議的默認 <端口> 爲 443(能夠省略)。
CSS 初始化是指重設瀏覽器的樣式。不一樣的瀏覽器默認的樣式可能不盡相同,若是沒對 CSS 初始化每每會出現瀏覽器之間的頁面差別。
好處:可以統一標籤在各大主流瀏覽器中的默認樣式,使得咱們開發網頁內容時更加方便簡潔,同時減小 CSS 代碼量,節約網頁下載時間。
浮動的特徵:
浮動元素有左浮動(float:left)和右浮動(float:right)兩種。
浮動的元素會向左或向右浮動,碰到父元素邊界、其餘元素才停下來。相鄰浮動的塊元素能夠並在一行,超出父級寬度就換行。浮動讓行內元素或塊元素轉化爲有浮動特性的行內塊元素(此時不會有行內塊元素間隙問題)。
父元素若是沒有設置尺寸(通常是高度不設置),父元素內總體浮動的子元素沒法撐開父元素,父元素須要清除浮動。
清除浮動的方法:
父級上增長屬性 overflow:hidden。
在最後一個子元素的後面加一個空的 div,給它樣式屬性 clear:both。
使用成熟的清浮動樣式類,clearfix。
clearfix:after,.clearfix:before{ content: "";display: table;}
clearfix:after{ clear:both;}
clearfix{zoom:1;}
什麼是Ajax:
Ajax的全稱是Asychronous JavaScript And XML(異步JavaScript和XML)
Ajax是一種改善用戶體驗的技術,利用瀏覽器內置的ajax對象異步地向服務器發送請求,服務器返回部分數據,瀏覽器利用這些數據修改頁面,整個過程頁面無需刷新,不打斷用戶的請求。
Ajax的優勢:
經過異步加載模式,提高了用戶體驗
優化瀏覽器和服務器之間的傳輸,減小沒必要要的數據往返,減小了帶寬佔用
Ajax引擎在客戶端運行,承擔了一部分原本由服務器承擔的工做,從而減小了高併發下的服務器負載
Ajax能夠實現動態加載局部刷新
JavaScript腳本語言;
可擴展標記語言 XML;
文檔對象模型 DOM;
級聯樣式表 CSS;
XMLHttpRequest對象。
Django框架:
Django 是一個重量級的框架,Django原生提供了衆多的功能組件
Django功能大而全,Django提供了一站式解決的思路,能讓開發者不用在開發以前就在選擇應用的基礎設施上花費大量時間。
Django自帶ORM(Object-Relational Mapping 對象關聯映射)和模板引擎,支持JinJa等非官方模板引擎,靈活度不高。
Django自帶數據庫管理app,Django自帶的模板引擎簡單好用
Django成熟、穩定、開發效率高、相對於Flask,Django的總體封閉性比較好,適合作企業級網站的開發
Django是Python web框架的先驅,用戶多,第三方庫最豐富,最好的Python庫,若是不能直接用到Django中,也必定能找到與之對應的移植
Flask框架:
Flask是一個輕量級web框架,只有一個內核,默認依賴兩個外部庫:Jinja2 模板引擎和 Werkzeug WSGI 工具集
Flask自由、靈活,可擴展性強,第三方庫的選擇面廣,開發時能夠結合本身最喜歡用的輪子,也能結合最流行最強大的Python庫
Flask適用於作小型網站以及web服務的API,開發大型網站無壓力,不過架構需自行設計
Flask與關係型數據庫結合不弱於Django,而與非關係型數據庫的結合遠遠優於Django
Django框架:
主要特色是大而全,集成了不少組件,例如: Models Admin Form 等等, 無論你用獲得用不到,反正它全都有,屬於全能型框架
優勢:
大和全(重量級框架)
自帶orm,template,view
須要的功能也能夠去找第三方的app
注重高效開發
全自動化的管理後臺(只須要使用起ORM,作簡單的定義,就能自動生成數據庫結構,全功能的管理後臺)
session功能
缺點:
template不怎麼好用(來自自身的缺點)
數據庫用nosql不方便(來自自身的缺點)
若是功能很少,容易臃腫
Tornado框架:
主要特色是原生異步非阻塞,在IO密集型應用和多任務處理上佔據絕對性的優點,屬於專一型框架
優勢:
少而精(輕量級框架)
注重性能優越,速度快
解決高併發(請求處理是基於回調的非阻塞調用)
異步非阻塞
websockets 長鏈接
內嵌了HTTP服務器
單線程的異步網絡程序,默認啓動時根據CPU數量運行多個實例;利用CPU多核的優點
自定義模塊
缺點:
Flask框架:
主要特色小而輕,原生組件幾乎爲0, 三方提供的組件請參考Django 很是全面,屬於短小精悍型框架
優勢:
簡單,Flask的路由以及路由函數由修飾器設定,開發人員不須要藉助其餘文件匹配;
配置靈活,有多種方法配置,不一樣環境的配置也很是方便;環境部署簡單,Flask運行不須要藉助其餘任何軟件,只須要安裝了Python的IDE,在命令行運行便可。只須要在Python中導入相應包便可知足全部需求;
低耦合,Flask能夠兼容多種數據庫、模板。
缺點:
對於大型網站開發,須要本身設計建構和路由映射規則
因爲Flask原生組件少,在版本升級時可能致使某些第三方組件出現問題
Flask-wtf是一個用於表單處理,校驗並提供csrf驗證的功能的擴展庫
Flask-wtf能把正表單免受CSRF <跨站請求僞造> 的攻擊
在shell中運行腳本文件
在python編譯器中run
會話(seesion)會話數據存儲在服務器上。 會話是客戶端登陸到服務器並註銷的時間間隔。 須要在此會話中進行的數據存儲在服務器上的臨時目錄中。
from flask import session導入會話對象
session['name'] = 'admin'給會話添加變量
session.pop('username', None)刪除會話的變量
Flask是一個典型的MVC框架
MVC框架,圖形理解
python中的數據庫鏈接有兩種方式
在腳本中以用第三方庫正常鏈接,用sql語句正常操做數據庫,如mysql關係型數據庫的pymsql庫
用ORM來進行數據庫鏈接,flask中典型的flask_sqlalchemy,已面向對象的方式進行數據庫的鏈接與操做
WSGI(Web Server Gateway Interface,Web 服務器網關接口)則是Python語言中1所定義的Web服務器和Web應用程序之間或框架之間的通用接口標準。
WSGI就是一座橋樑,橋樑的一端稱爲服務端或網關端,另外一端稱爲應用端或者框架端,WSGI的做用就是在協議之間進行轉化。WSGI將Web組件分紅了三類:Web 服務器(WSGI Server)、Web中間件(WSGI Middleware)與Web應用程序(WSGI Application)。
Web Server接收HTTP請求,封裝一系列環境變量,按照WSGI接口標準調用註冊的WSGI Application,最後將響應返回給客戶端。
Route(路由)
templates(模板)
Models(orm模型)
blueprint(藍圖)
Jinja2模板引擎
藍圖 /Blueprint 是 Flask 應用程序組件化的方法,能夠在一個應用內或跨越多個項目共用藍圖。使用藍圖能夠極大地簡化大型應用的開發難度,也爲 Flask 擴展 提供了一種在應用中註冊服務的集中式機制。
藍圖的應用場景:
把一個應用分解爲一個藍圖的集合。這對大型應用是理想的。一個項目能夠實例化一個應用對象,初始化幾個擴展,並註冊一集合的藍圖。
以 URL 前綴和/或子域名,在應用上註冊一個藍圖。 URL 前綴/子域名中的參數即成爲這個藍圖下的全部視圖函數的共同的視圖參數(默認狀況下)。
在一個應用中用不一樣的 URL 規則屢次註冊一個藍圖。
經過藍圖提供模板過濾器、靜態文件、模板和其它功能。一個藍圖不必定要實現應用或者視圖函數。
初始化一個 Flask 擴展時,在這些狀況中註冊一個藍圖。
藍圖的缺點:
使用藍圖的三個步驟:
建立一個藍圖對象
```python
blue = Blueprint("blue", name)
```
在這個藍圖對象上進行操做 ,例如註冊路由、指定靜態文件夾、註冊模板過濾器...
```python
@blue.route('/')
def blue_index():
return 'Welcome to my blueprint'
在應用對象上註冊這個藍圖對象
```python
app.register_blueprint(blue, url_prefix='/blue')
```
將不一樣的功能模塊化
構建大型應用
優化項目結構
加強可讀性,易於維護(跟Django的view功能類似)
flask_bootstrap
flask_WTF
flask_sqlalchemy
Flask中有三個session:
例如:db.session.add()
from flask_session importSession
from flask import session
SQL優化:
選擇最有效的表名排序,對查詢進行優化,要儘可能避免全表掃描。
應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描。
最好不要給數據庫留NULL,儘量的使用 NOT NULL填充數據庫。
應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描。
數據庫結構優化:
範式優化:好比消除冗餘等(節省空間)
反範式優化:如適當加冗餘等(減小join)
拆分表:垂直拆分和水平拆分
服務器硬件優化:
存儲過程就像咱們編程語言中的函數同樣,封裝了咱們的代碼(PLSQL、T-SQL)
存儲過程的優勢
可以將代碼封裝起來
保存在數據庫之中
讓編程語言進行調用
存儲過程是一個預編譯的代碼塊,執行效率比較高
一個存儲過程替代大量T_SQL語句 ,能夠下降網絡通訊量,提升通訊速率
存儲過程的缺點:
個數據庫的存儲過程語法幾乎都不同,十分難以維護(不通用)
業務邏輯放在數據庫上,難以迭代
事務:簡單來講,一個session中進行全部操做,要麼同時成功,要麼同時失敗。
事務的四個基本要素(ACID):
原子性(Atomicity):事務中包含的操做被看作一個邏輯單元,這個邏輯單元中的操做要麼所有成功,要麼所有失敗。
一致性(Consistency):事務完成時,數據必須處於一致狀態,數據的完整性約束沒有被破壞,事務在執行過程當中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。
隔離性(Isolation):事務容許多個用戶對同一個數據進行併發訪問,而不破壞數據的正確性和完整性。同時並行事務的修改必須與其餘並行事務的修改相互獨立。
持久性(Durability):事務結束後,事務處理的結果必須可以獲得固化。
鎖:在因此的 DBMS中,鎖是實現事務的關鍵,鎖能夠保證事務的完整性和併發性。與現實生活中鎖同樣,它能夠使某些數據的擁有者,在某段時間內不能使用某些數據或數據結構。固然鎖還分級別的。
視圖:一種虛擬的表,具備和物理表相同的功能。能夠對視圖進行增,改,查,操做,試圖一般是有一個表或者多個表的行或列的子集。對視圖的修改不影響基本表。它使得咱們獲取數據更容易,相比多表查詢。
遊標:對查詢出來的結果集做爲一個單元來有效的處理。遊標能夠定在該單元中的特定行,從結果集的當前行檢索一行或多行。能夠對結果集當前行作修改。通常不使用遊標,可是須要逐條處理數據的時候,遊標顯得十分重要。
使用場景:如多個地方須要用到一樣的查詢結果,該查詢結果經常須要編寫冗長而複雜的SQL語句...使用視圖能夠將查詢出來的數據進行封裝,在使用的時候就變得很是方便。
視圖的好處:
重用SQL
簡化複雜SQL操做,沒必要知道它的實現細節
保護數據,提升安全性
第一範式:字段是最小的單元不可再分。
第二範式:知足第一範式,表中的字段必須徹底依賴於所有主鍵而非部分主鍵。
其它字段組成的這行記錄和主鍵表示的是同一個東西,而主鍵是惟一的,它們只須要依賴於主鍵,也就成了惟一的。
學號爲1024的同窗,姓名爲Python3,年齡是23歲。姓名和年齡字段都依賴着學號主鍵。
第三範式:知足第二範式,非主鍵外的全部字段必須互不依賴
數據只在一個地方存儲,不重複出如今多張表中;能夠認爲就是消除傳遞依賴。
好比咱們大學分了不少系(中文系、外語系、計算機系......),這個系別管理表信息有如下字段組成:系編號、系主任、系簡介、系架構等。那咱們能不能在學生信息表添加系編號、系主任、系簡介、系架構等字段呢???很顯然不行,由於這樣就冗餘了,非主鍵外的字段造成了依賴關係(依賴到學生信息表),正確的作法是:學生表就增長一個系編號字段。
什麼是索引(index):
一種快速查詢表中內容的機制,相似於新華字典的目錄
運用在表中某些字段上,單存儲時,獨立於表以外
做用:
索引把數據變成有序的
快速定位到硬盤中的數據文件
索引的優勢:
加快數據的檢索速度
建立惟一性索引,保證數據庫表中每一行數據的惟一性
加速表和表的鏈接
在使用分組和排序子句進行數據檢索時,能夠顯著減小查詢中分組和排序的時間
索引的缺點:
索引須要佔物理空間
當對錶中的數據進行增長、刪除和修改的時候,索引頁要動態的維護,下降了數據的維護速度
索引分類:
惟一索引:惟一索引不容許兩行具備相同的索引值
主鍵索引:爲表定義一個主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特殊類型。主鍵索引要求主鍵中的每一個值是惟一的,而且不能爲空
聚焦索引(Clustered):表中各行的物理順序與鍵值的邏輯(索引)順序相同,每一個表只能有一個
非聚焦索引(Non-clustered):非聚焦索引指定表的邏輯順序。數據存儲在一個位置,索引存儲在另外一個位子,索引中寶行指向數據存儲位置的指針。
確保在多個事務同時存取數據庫中的一數據時不破壞事務的隔離性和一致性以及數據庫的統一性,樂觀鎖和悲觀鎖是併發控制主要採用的技術手段
悲觀鎖:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做。
在查詢完數據的時候就把事務鎖起來,直到提交事務
實現方法:使用數據庫中的鎖機制
缺點:性能低
樂觀鎖:假設不會發生併發衝突,只在提交操做時檢查是否違反數據完整性。
在修改數據的時候把事務鎖起來,經過version的方式來進行鎖定。
實現方法:使用version版本或者時間戳
超鍵:在關係中能惟一標識元祖的屬性集稱爲關係模型的超鍵。一個屬性能夠做爲一個超鍵,多個屬性組合在一塊兒也能夠做爲一個超鍵;超鍵包含候選鍵和主鍵。
候選鍵(候選碼):是最小超鍵,既沒有冗餘元素的超鍵。
主鍵(主碼):數據庫表中對存儲數據對象予以惟一和完整性標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,既不能爲空值(NULL)。
外鍵:在一個表中存在的另外一個表的主鍵稱此表的外鍵。
候選碼和主碼:
例子:郵寄地址(城市、街道名、郵政編碼、單位名、收件人)
它有兩個候選鍵:{城市名,街道名}和{街道名,收件人}
若是我選取{城市名,街道名}做爲惟一標識實體的屬性,那麼{城市名,街道名}就是主碼{主鍵}
約束類型: | 主鍵 | 默認值 | 惟一 | 外鍵 | 非空 |
---|---|---|---|---|---|
關鍵字: | PRIMARY KEY | DEFAULT | UNIQUE | FOREIGN KEY | NOT NULL |
總結:
桶排序,是一種複雜度爲O(n)的排序
桶排序,是一種穩定的排序
適用於數據均勻分佈在一個區間內的場景
pwd 顯示工做路徑
ls 列出目錄中的內容
cd 切換目錄
cd /home 進入'/home'的目錄
cd .. 返回上一級目錄
touch file1 建立一個名爲 file1 的文件
mkdir dir1 建立一個名爲 dir1 的目錄
rm -r file1 刪除一個名爲 file1 的文件,-f 參數忽略不存在的文件,沒有提示。
cp file1 /home 把 file1 文件複製到 /home 目錄下
mv 移動目錄
cat file1 查看文檔或代碼
sudo apt-get install 安裝命令
netstat -anp | grep service_name
重定向 「>」:
重定向 「>>」:
軟鏈接相似於windows的快捷鍵,當刪除源文件時;軟鏈接也會隨之失效。
硬連接能夠理解爲源文件的一個別名,多個別名所表明的是同一個文件。當 rm 一個文件的時候,那麼次文件的硬連接數減 1,當硬連接數爲 0 時,文件被刪除。
reboot 從新啓動操做系統
shutdown -h now 馬上關機,其中now至關於時間爲 0 的狀態
shutdown -h 20:30 系統在今天的 20:30關機
shutdown -h +10 系統過10分鐘後自動關機
init 0 關機
init 6 重啓
123