1.1 多線程
在傳統操作系統中,每個進程有一個地址空間,而且默認就有一個控制線程
線程顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個進程
車間負責把資源整合到一起,是一個資源單位,而一個車間內至少有一個流水線
流水線的工作需要電源,電源就相當於cpu
所以,進程只是用來把資源集中到一起(進程只是一個資源單位,或者說資源集合),而線程才是cpu上的執行單位。
多線程(即多個控制線程)的概念是,在一個進程中存在多個控制線程,多個控制線程共享該進程的地址空間,相當於一個車間內有多條流水線,都共用一個車間的資源。
例如,北京地鐵與上海地鐵是不同的進程,而北京地鐵里的13號線是一個線程,北京地鐵所有的線路共享北京地鐵所有的資源,比如所有的乘客可以被所有線路拉。
l 創建進程的開銷要遠大於線程?
如果我們的軟件是一個工廠,該工廠有多條流水線,流水線工作需要電源,電源只有一個即cpu(單核cpu),一個車間就是一個進程,一個車間至少一條流水線(一個進程至少一個線程),創建一個進程,就是創建一個車間(申請空間,在該空間內建至少一條流水線),而建線程,就只是在一個車間內造一條流水線,無需申請空間,所以創建開銷小
l 進程之間是競爭關系,線程之間是協作關系?
車間直接是競爭/搶電源的關系,競爭(不同的進程直接是競爭關系,是不同的程序員寫的程序運行的,迅雷搶占其他進程的網速,360把其他進程當做病毒干死),一個車間的不同流水線式協同工作的關系(同一個進程的線程之間是合作關系,是同一個程序寫的程序內開啟動,迅雷內的線程是合作關系,不會自己干自己)
1.1.1 為何要用多線程
多線程指的是,在一個進程中開啟多個線程,簡單的講:如果多個任務共用一塊地址空間,那么必須在一個進程內開啟多個線程。詳細的講分為4點:
1. 多線程共享一個進程的地址空間
2. 線程比進程更輕量級,線程比進程更容易創建可撤銷,在許多操作系統中,創建一個線程比創建一個進程要快10-100倍,在有大量線程需要動態和快速修改時,這一特性很有用
3. 若多個線程都是cpu密集型的,那么並不能獲得性能上的增強,但是如果存在大量的計算和大量的I/O處理,擁有多個線程允許這些活動彼此重疊運行,從而會加快程序執行的速度。
4. 在多cpu系統中,為了最大限度的利用多核,可以開啟多個線程,比開進程開銷要小的多。(這一條並不適用於python)
1.2 死鎖現象與遞歸鎖
進程也有死鎖與遞歸鎖。
所謂死鎖: 是指兩個或兩個以上的進程或線程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
遞歸鎖,在Python中為了支持在同一線程中多次請求同一資源,python提供了可重入鎖RLock,
這個RLock內部維護着一個Lock和一個counter變量,counter記錄了acquire的次數,從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上面的例子如果使用RLock代替Lock,則不會發生死鎖:
from threading import Thread,Lock,RLock import time # mutexA=Lock() # mutexB=Lock() mutexA=mutexB=RLock() #一個線程拿到鎖,counter加1,該線程內又碰到加鎖的情況,則counter繼續加1,這期間所有其他線程都只能等待,等待該線程釋放所有鎖,即counter遞減到0為止 class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 拿到了A鎖' %self.name) mutexB.acquire() print('%s 拿到了B鎖' % self.name) mutexB.release() #1 mutexA.release() #0 def f2(self): mutexB.acquire() print('%s 拿到了B鎖' % self.name) time.sleep(0.1) mutexA.acquire() print('%s 拿到了A鎖' % self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t=MyThread() t.start()
1.3 信號量Semaphore
同進程的一樣,Semaphore管理一個內置的計數器,每當調用acquire()時內置計數器-1;調用release() 時內置計數器+1;計數器不能小於0;當計數器為0時,acquire()將阻塞線程直到其他線程調用release()。
實例:(同時只有5個線程可以獲得semaphore,即可以限制最大連接數為5):
from threading import Thread,Semaphore,current_thread import time,random sm=Semaphore(5) def task(): with sm: print('%s is laing' %current_thread().getName()) time.sleep(random.randint(1,3)) if __name__ == '__main__': for i in range(20): t=Thread(target=task) t.start()
與進程池是完全不同的概念,進程池Pool(4),最大只能產生4個進程,而且從頭到尾都只是這四個進程,不會產生新的,而信號量是產生一堆線程/進程
1.4 Event事件
同進程的一樣,線程的一個關鍵特性是每個線程都是獨立運行且狀態不可預測。如果程序中的其 他線程需要通過判斷某個線程的狀態來確定自己下一步的操作,這時線程同步問題就會變得非常棘手。為了解決這些問題,我們需要使用threading庫中的Event對象。 對象包含一個可由線程設置的信號標志,它允許線程等待某些事件的發生。在 初始情況下,Event對象中的信號標志被設置為假。如果有線程等待一個Event對象, 而這個Event對象的標志為假,那么這個線程將會被一直阻塞直至該標志為真。一個線程如果將一個Event對象的信號標志設置為真,它將喚醒所有等待這個Event對象的線程。如果一個線程等待一個已經被設置為真的Event對象,那么它將忽略這個事件, 繼續執行
event.isSet():返回event的狀態值; event.wait():如果 event.isSet()==False將阻塞線程; event.set(): 設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態, 等待操作系統調度; event.clear():恢復event的狀態值為False。
例如,有多個工作線程嘗試鏈接MySQL,我們想要在鏈接前確保MySQL服務正常才讓那些工作線程去連接MySQL服務器,如果連接不成功,都會去嘗試重新連接。那么我們就可以采用threading.Event機制來協調各個工作線程的連接操作
from threading import Thread,Event,current_thread import time event=Event() def check(): print('checking MySQL...') time.sleep(5) event.set() def conn(): count=1 while not event.is_set(): if count > 3: raise TimeoutError('超時') print('%s try to connect MySQL time %s' %(current_thread().getName(),count)) event.wait(1) count+=1 print('%s connected MySQL' %current_thread().getName()) if __name__ == '__main__': t1=Thread(target=check) t2=Thread(target=conn) t3=Thread(target=conn) t4=Thread(target=conn) t1.start() t2.start() t3.start() t4.start()
1.5 定時器
定時器,指定n秒后執行某操作
from threading import Timer def hello(name): print("hello, world %s " %name) t = Timer(3, hello,args=('egon',)) t.start() # after 1 seconds, "hello, world" will be printed
1.6 線程queue
queue隊列 :使用import queue,用法與進程Queue一樣
import queue q=queue.Queue(3) #隊列:先進先出 q.put(1) q.put(2) q.put(3) # q.put(4) # q.put_nowait(4) # q.put(4,block=False) q.put(4,block=True,timeout=3) # print(q.get()) # print(q.get()) # print(q.get()) q=queue.LifoQueue(3) #堆棧:后進先出 q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) q=queue.PriorityQueue(3) #優先級隊列 q.put((10,'a')) q.put((-3,'b')) q.put((100,'c')) print(q.get()) print(q.get()) print(q.get())
1.7 進程池線程池
#提交任務的兩種方式:
#同步調用:提交完任務后,就在原地等待,等待任務執行完畢,拿到任務的返回值,才能繼續下一行代碼,導致程序串行執行
#異步調用+回調機制:提交完任務后,不在原地等待,任務一旦執行完畢就會觸發回調函數的執行, 程序是並發執行
#進程的執行狀態:
#阻塞
#非阻塞
1.7.1 同步調用示例:
# from multiprocessing import Pool
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time,random,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(random.randint(1,3)) return n**2 def handle(res): print('handle res %s' %res) if __name__ == '__main__': #同步調用 pool=ProcessPoolExecutor(2) for i in range(5): res=pool.submit(task,i).result() # print(res) handle(res) pool.shutdown(wait=True) # pool.submit(task,33333) print('主')
1.7.2 異步調用示例:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time,random,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(random.randint(1,3)) # res=n**2 # handle(res) return n**2 def handle(res): res=res.result() print('handle res %s' %res) if __name__ == '__main__': #異步調用 pool=ProcessPoolExecutor(2) for i in range(5): obj=pool.submit(task,i) obj.add_done_callback(handle) #handle(obj) pool.shutdown(wait=True) print('主')
1.7.3 線程池
from concurrent.futures import ThreadPoolExecutor from threading import current_thread import requests import time def get(url): print('%s GET %s' %(current_thread().getName(),url)) response=requests.get(url) time.sleep(2) if response.status_code == 200: return {'url':url,'content':response.text} def parse(res): res=res.result() print('parse:[%s] res:[%s]' %(res['url'],len(res['content']))) if __name__ == '__main__': pool=ThreadPoolExecutor(2) urls=[ 'https://www.baidu.com', 'https://www.python.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', ] for url in urls: pool.submit(get,url).add_done_callback(parse) pool.shutdown(wait=True)
1.8 協程
單純地切換反而會降低運行效率
協程:是單線程下的並發,又稱微線程,纖程。英文名Coroutine。一句話說明什么是線程:協程是一種用戶態的輕量級線程,即協程是由用戶程序自己控制調度的。
總結協程特點:
必須在只有一個單線程里實現並發
修改共享數據不需加鎖
用戶程序里自己保存多個控制流的上下文棧
附加:一個協程遇到IO操作自動切換到其它協程(如何實現檢測IO,yield、greenlet都無法實現,就用到了gevent模塊(select機制))
1.8.1 串行執行
import time def consumer(res): '''任務1:接收數據,處理數據''' pass def producer(): '''任務2:生產數據''' res=[] for i in range(10000000): res.append(i) return res start=time.time() #串行執行 res=producer() consumer(res) stop=time.time() print(stop-start)
1.8.2 基於yield並發執行
import time def consumer(): '''任務1:接收數據,處理數據''' while True: print('consumer') x=yield time.sleep(100) def producer(): '''任務2:生產數據''' g=consumer() next(g) for i in range(10000000): print('producer') g.send(i) start=time.time() #基於yield保存狀態,實現兩個任務直接來回切換,即並發的效果 #PS:如果每個任務中都加上打印,那么明顯地看到兩個任務的打印是你一次我一次,即並發執行的. producer() stop=time.time() print(stop-start) #
1.9 greenlet模塊
如果我們在單個線程內有20個任務,要想實現在多個任務之間切換,使用yield生成器的方式過於麻煩(需要先得到初始化一次的生成器,然后再調用send。。。非常麻煩),而使用greenlet模塊可以非常簡單地實現這20個任務直接的切換
安裝模塊
pip3 install greenlet
from greenlet import greenlet import time def eat(name): print('%s eat 1' %name) time.sleep(1000) g2.switch('egon') print('%s eat 2' %name) g2.switch() def play(name): print('%s play 1' % name) g1.switch() #可以在第一次switch時傳入參數,以后都不需要 print('%s play 2' % name) g1=greenlet(eat) g2=greenlet(play)
greenlet只是提供了一種比generator更加便捷的切換方式,當切到一個任務執行時如果遇到io,那就原地阻塞,仍然是沒有解決遇到IO自動切換來提升效率的問題。
單線程里的這20個任務的代碼通常會既有計算操作又有阻塞操作,我們完全可以在執行任務1時遇到阻塞,就利用阻塞的時間去執行任務2。。。。如此,才能提高效率,這就用到了Gevent模塊。
1.10 gevent模塊
Gevent 是一個第三方庫,可以輕松通過gevent實現並發同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協程。 Greenlet全部運行在主程序操作系統進程的內部,但它們被協作式地調度。
#用法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)創建一個協程對象g1,spawn括號內第一個參數是函數名,如eat,后面可以有多個參數,可以是位置實參或關鍵字實參,都是傳給函數eat的 g2=gevent.spawn(func2) g1.join() #等待g1結束 g2.join() #等待g2結束 #或者上述兩步合作一步:gevent.joinall([g1,g2]) g1.value#拿到func1的返回值
from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat 1' %name) # gevent.sleep(3) time.sleep(3) print('%s eat 2' %name) def play(name): print('%s play 1' % name) # gevent.sleep(2) time.sleep(3) print('%s play 2' % name) g1=gevent.spawn(eat,'egon') g2=gevent.spawn(play,'alex') # gevent.sleep(1) # g1.join() # g2.join() gevent.joinall([g1,g2])
練習
通過gevent實現單線程下的socket並發(from gevent import monkey;monkey.patch_all()一定要放到導入socket模塊之前,否則gevent無法識別socket的阻塞)
服務端
from gevent import monkey,spawn;monkey.patch_all() from threading import current_thread from socket import * def comunicate(conn): print('子線程:%s' %current_thread().getName()) while True: try: data=conn.recv(1024) if not data:break conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip,port): print('主線程:%s' %current_thread().getName()) server = socket(AF_INET, SOCK_STREAM) server.bind((ip,port)) server.listen(5) while True: conn, addr = server.accept() print(addr) # comunicate(conn) # t=Thread(target=comunicate,args=(conn,)) # t.start() spawn(comunicate,conn) server.close() if __name__ == '__main__': g=spawn(server,'127.0.0.1', 8081) g.join()
客戶端
多線程並發多個客戶端
from socket import * from threading import current_thread,Thread def client(): client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8081)) while True: client.send(('%s say hello' %current_thread().getName()).encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8')) client.close() if __name__ == '__main__': for i in range(500): t=Thread(target=client) t.start()
1.11 MySQL數據庫相關概念
MySQL是一個關系型數據庫管理系統,由瑞典MySQL AB 公司開發,目前屬於 Oracle 旗下公司。MySQL 最流行的關系型數據庫管理系統,在 WEB 應用方面MySQL是最好的 RDBMS (Relational Database Management System,關系數據庫管理系統) 應用軟件之一。
1、數據庫服務器:計算機
2、數據庫管理軟件:MySQL
3、數據庫/庫:文件夾
4、表:文件
5、記錄:一個事物的一系列典型的特征:egon,male,18,oldgirl
6、數據:事物的特征,sex='male'
1.11.1 mysql是什么
#mysql就是一個基於socket編寫的C/S架構的軟件
#客戶端軟件
mysql自帶:如mysql命令,mysqldump命令等
python模塊:如pymysql
1.11.2 數據庫管理軟件分類
#分兩大類:
關系型:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql語句通用
非關系型:mongodb,redis,memcache
#可以簡單的理解為:
關系型數據庫需要有表結構
非關系型數據庫是key-value存儲的,沒有表結構
1.11.3 下載安裝
1.11.3.1 Linux版本
一、二進制rpm包安裝
yum -y install mysql-server mysql
二、源碼安裝
1.解壓tar包
cd /software tar -xzvf mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz mv mysql-5.6.21-linux-glibc2.5-x86_64 mysql-5.6.21
2.添加用戶與組
groupadd mysql useradd -r -g mysql mysql chown -R mysql:mysql mysql-5.6.21
3.安裝數據庫
su mysql cd mysql-5.6.21/scripts ./mysql_install_db --user=mysql --basedir=/software/mysql-5.6.21 --datadir=/software/mysql-5.6.21/data
4.配置文件
cd /software/mysql-5.6.21/support-files cp my-default.cnf /etc/my.cnf cp mysql.server /etc/init.d/mysql vim /etc/init.d/mysql #若mysql的安裝目錄是/usr/local/mysql,則可省略此步 修改文件中的兩個變更值 basedir=/software/mysql-5.6.21 datadir=/software/mysql-5.6.21/data
5.配置環境變量
vim /etc/profile export MYSQL_HOME="/software/mysql-5.6.21" export PATH="$PATH:$MYSQL_HOME/bin" source /etc/profile
6.添加自啟動服務
chkconfig --add mysql
chkconfig mysql on
7.啟動mysql
service mysql start
8.登錄mysql及改密碼與配置遠程訪問
mysqladmin -u root password 'your_password' #修改root用戶密碼 mysql -u root -p #登錄mysql,需要輸入密碼 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_password' WITH GRANT OPTION; #允許root用戶遠程訪問 mysql>FLUSH PRIVILEGES; #刷新權限
三、源碼安裝mariadb
1. 解壓
tar zxvf mariadb-5.5.31-linux-x86_64.tar.gz
mv mariadb-5.5.31-linux-x86_64 /usr/local/mysql //必需這樣,很多腳本或可執行程序都會直接訪問這個目錄
2. 權限
groupadd mysql //增加 mysql 屬組 useradd -g mysql mysql //增加 mysql 用戶 並歸於mysql 屬組 chown mysql:mysql -Rf /usr/local/mysql // 設置 mysql 目錄的用戶及用戶組歸屬。 chmod +x -Rf /usr/local/mysql //賜予可執行權限
3. 拷貝配置文件
cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf //復制默認mysql配置 文件到/etc目錄
4. 初始化
/usr/local/mysql/scripts/mysql_install_db --user=mysql //初始化數據庫 cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql //復制mysql服務程序 到系統目錄 chkconfig mysql on //添加mysql 至系統服務並設置為開機啟動 service mysql start //啟動mysql
5. 環境變量配置
vim /etc/profile //編輯profile,將mysql的可執行路徑加入系統PATH export PATH=/usr/local/mysql/bin:$PATH source /etc/profile //使PATH生效。
6. 賬號密碼
mysqladmin -u root password 'yourpassword' //設定root賬號及密碼 mysql -u root -p //使用root用戶登錄mysql use mysql //切換至mysql數據庫。 select user,host,password from user; //查看系統權限 drop user ''@'localhost'; //刪除不安全的賬戶 drop user root@'::1'; drop user root@127.0.0.1; select user,host,password from user; //再次查看系統權限,確保不安全的賬戶均被刪除。 flush privileges; //刷新權限
7. 一些必要的初始配置
1)修改字符集為UTF8
vi /etc/my.cnf 在[client]下面添加 default-character-set = utf8 在[mysqld]下面添加 character_set_server = utf8
2)增加錯誤日志
vi /etc/my.cnf 在[mysqld]下面添加: log-error = /usr/local/mysql/log/error.log general-log-file = /usr/local/mysql/log/mysql.log 3) 設置為不區分大小寫,linux下默認會區分大小寫。 vi /etc/my.cnf 在[mysqld]下面添加: lower_case_table_name=1
修改完重啟:
service mysql restart
1.11.3.2 Window版本
安裝
#1、下載:MySQL Community Server 5.7.16
http://dev.mysql.com/downloads/mysql/
#2、解壓
如果想要讓MySQL安裝在指定目錄,那么就將解壓后的文件夾移動到指定目錄,如:C:\mysql-5.7.16-winx64
#3、添加環境變量
【右鍵計算機】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變量】--》【在第二個內容框中找到 變量名為Path 的一行,雙擊】 --> 【將MySQL的bin目錄路徑追加到變值值中,用 ; 分割】
#4、初始化
mysqld --initialize-insecure
#5、啟動MySQL服務
mysqld # 啟動MySQL服務
#6、啟動MySQL客戶端並連接MySQL服務
mysql -u root -p # 連接MySQL服務器
將MySQL服務制作成windows服務
上一步解決了一些問題,但不夠徹底,因為在執行【mysqd】啟動MySQL服務器時,當前終端會被hang住,那么做一下設置即可解決此問題:
注意:--install前,必須用mysql啟動命令的絕對路徑
# 制作MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --install
# 移除MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --remove
注冊成服務之后,以后再啟動和關閉MySQL服務時,僅需執行如下命令:
# 啟動MySQL服務
net start mysql
# 關閉MySQL服務
net stop mysql
1.12 重置密碼
1.12.1 設置密碼
C:\Users\Administrator> mysqladmin -uroot -p password "123"
1.12.2 重置密碼
net stop MySQL mysqld --skip-grant-tables mysql -uroot -p update mysql.user set password=password("") where user='root' and host="localhost"; flush privileges; C:\Users\Administrator>tasklist |findstr mysql mysqld.exe 6316 Console 1 454,544 K C:\Users\Administrator>taskkill /F /PID 6316 成功: 已終止 PID 為 6316 的進程。 C:\Users\Administrator>net start MySQL MySQL 服務正在啟動 . MySQL 服務已經啟動成功。
1.13 統一字符編碼
#1. 修改配置文件
[mysqld] default-character-set=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8 #mysql5.5以上:修改方式有所改動 [mysqld] character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8 [mysql] default-character-set=utf8
#2. 重啟服務
#3. 查看修改結果:
mysql> \s show variables like '%char%'
1.14 初識SQL
有了mysql這個數據庫軟件,就可以將程序員從對數據的管理中解脫出來,專注於對程序邏輯的編寫
mysql服務端軟件即mysqld幫我們管理好文件夾以及文件,前提是作為使用者的我們,需要下載mysql的客戶端,或者其他模塊來連接到mysqld,然后使用mysql軟件規定的語法格式去提交自己命令,實現對文件夾或文件的管理。該語法即sql(Structured Query Language 即結構化查詢語言)
SQL語言主要用於存取數據、查詢數據、更新數據和管理關系數據庫系統,SQL語言由IBM開發。SQL語言分為3種類型:
#1、DDL語句 數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER
#2、DML語句 數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT
#3、DCL語句 數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE
1.14.1 操作文件夾(庫)
1.14.1.1 增
create database db1 charset utf8;
1.14.1.2 查
show databases;
show create database db1;
1.14.1.3 改
alter database db1 charset gbk;
1.14.1.4 刪
drop database db1;
1.14.2 操作文件(表)
1.14.2.1 查看當前所在的文件夾:
select database();
1.14.2.2 切換文件夾:
use db1;
1.14.2.3 增
create table t1(id int,name char);
1.14.2.4 查
show tables;
show create table t1;
desc t1;
1.14.2.5 改
alter table t1 add sex char; alter table t1 drop sex; alter table t1 modify name char(16); alter table t1 change name Name char(13);
1.14.2.6 刪
drop table t1;
1.14.3 操作文件的內容(記錄)
1.14.3.1 增
insert into db1.t1 values (1,'egon'), (2,'alex'), (3,'wxx');
1.14.3.2 查
select id,name from db1.t1; select * from db1.t1;
1.14.3.3 改
update t1 set name='SB' where id=2;
1.14.3.4 刪
delete from t1 where id=2;
1.15 存儲引擎
儲引擎即表類型,mysql根據不同的表類型會有不同的處理機制
查看引擎
show engines;
創建引擎
create table t1(id int)engine=innodb; create table t2(id int)engine=myisam; create table t3(id int)engine=memory; create table t4(id int)engine=blackhole;
1.16 數值類型
1.16.1 整型(默認有符號)
create table t8(n tinyint); insert into t8 values(-1); insert into t8 values(128); insert into t8 values(-129); create table t9(n tinyint unsigned); insert into t9 values(-1),(256);
#整型的寬度代表顯示寬度
create table t11(n int(3) unsigned zerofill);
create table t12(n int unsigned zerofill);
create table t13(
id int
);
1.16.2 浮點型
create table t13(x float(255,30)); create table t14(x double(255,30)); create table t15(x decimal(65,30)); insert into t13 values(1.111111111111111111111111111111); insert into t14 values(1.111111111111111111111111111111); insert into t15 values(1.111111111111111111111111111111);
1.17 日期類型
create table student( id int, name char(16), born_year year, birth_date date, class_time time, reg_time datetime ); insert into student values (1,'egon',now(),now(),now(),now()) ; insert into student values (2,'alex','1999','1999-11-11','11:11:11',"1999-11-11 11:11:11")
1.18 字符類型
char:定長
varchar:變長
#寬度代表的是字符的個數
create table t16(name char(5)); create table t17(name varchar(5)); insert into t16 values('李傑 '); #'李傑 ' insert into t17 values('李傑 '); #'李傑 ' select char_length(name) from t16; #5 select char_length(name) from t17; #3 mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH'; select * from t16 where name='李傑'; select * from t17 where name='李傑'; select * from t16 where name like '李傑'; name char(5) egon |alex |wxx | name varchar(5) 1bytes+egon|1bytes+alex|1bytes+wxx|
1.19 枚舉類型與集合類型
create table employee( id int, name char(10), sex enum('male','female','other'), hobbies set('play','eat','music','read') ); insert into employee values (1,'egon','male','music,read'); insert into employee values (2,'alex','xxxx','music,read');