多線程與MySQL(十)

1.1 多線程

在傳統操做系統中,每一個進程有一個地址空間,並且默認就有一個控制線程python

  線程顧名思義,就是一條流水線工做的過程,一條流水線必須屬於一個車間,一個車間的工做過程是一個進程mysql

    車間負責把資源整合到一塊兒,是一個資源單位,而一個車間內至少有一個流水線linux

    流水線的工做須要電源,電源就至關於cpu程序員

  因此,進程只是用來把資源集中到一塊兒(進程只是一個資源單位,或者說資源集合),而線程纔是cpu上的執行單位。redis

  多線程(即多個控制線程)的概念是,在一個進程中存在多個控制線程,多個控制線程共享該進程的地址空間,至關於一個車間內有多條流水線,都共用一個車間的資源。sql

     例如,北京地鐵與上海地鐵是不一樣的進程,而北京地鐵裏的13號線是一個線程,北京地鐵全部的線路共享北京地鐵全部的資源,好比全部的乘客能夠被全部線路拉。mongodb

l  建立進程的開銷要遠大於線程?數據庫

若是咱們的軟件是一個工廠,該工廠有多條流水線,流水線工做須要電源,電源只有一個即cpu(單核cpu),一個車間就是一個進程,一個車間至少一條流水線(一個進程至少一個線程),建立一個進程,就是建立一個車間(申請空間,在該空間內建至少一條流水線),而建線程,就只是在一個車間內造一條流水線,無需申請空間,因此建立開銷小編程

l  進程之間是競爭關係,線程之間是協做關係?vim

車間直接是競爭/搶電源的關係,競爭(不一樣的進程直接是競爭關係,是不一樣的程序員寫的程序運行的,迅雷搶佔其餘進程的網速,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,關係數據庫管理系統) 應用軟件之一。

一、數據庫服務器:計算機

二、數據庫管理軟件:MySQL

三、數據庫/庫:文件夾

四、表:文件

五、記錄:一個事物的一系列典型的特徵:egon,male,18,oldgirl

六、數據:事物的特徵,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版本

1、二進制rpm包安裝

yum -y install mysql-server mysql

 

 

2、源碼安裝

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;     #刷新權限

 

 

3、源碼安裝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版本

安裝

#一、下載:MySQL Community Server 5.7.16

http://dev.mysql.com/downloads/mysql/

 

#二、解壓

若是想要讓MySQL安裝在指定目錄,那麼就將解壓後的文件夾移動到指定目錄,如:C:\mysql-5.7.16-winx64

 

#三、添加環境變量

【右鍵計算機】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變量】--》【在第二個內容框中找到 變量名爲Path 的一行,雙擊】 --> 【將MySQL的bin目錄路徑追加到變值值中,用 ; 分割】

 

#四、初始化

mysqld --initialize-insecure

 

 

#五、啓動MySQL服務

mysqld # 啓動MySQL服務

 

 

#六、啓動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種類型:

#一、DDL語句    數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER

#二、DML語句    數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT

#三、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');
相關文章
相關標籤/搜索