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,则不会发生死锁:

  1. from threading import Thread,Lock,RLock
  2.  
  3. import time
  4.  
  5. # mutexA=Lock()
  6.  
  7. # mutexB=Lock()
  8.  
  9. mutexA=mutexB=RLock() #一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
  10.  
  11. class MyThread(Thread):
  12.  
  13. def run(self):
  14.  
  15. self.f1()
  16.  
  17. self.f2()
  18.  
  19. def f1(self):
  20.  
  21. mutexA.acquire()
  22.  
  23. print('%s 拿到了A锁' %self.name)
  24.  
  25. mutexB.acquire()
  26.  
  27. print('%s 拿到了B锁' % self.name)
  28.  
  29. mutexB.release() #
  30.  
  31. mutexA.release() #
  32.  
  33. def f2(self):
  34.  
  35. mutexB.acquire()
  36.  
  37. print('%s 拿到了B锁' % self.name)
  38.  
  39. time.sleep(0.1)
  40.  
  41. mutexA.acquire()
  42.  
  43. print('%s 拿到了A锁' % self.name)
  44.  
  45. mutexA.release()
  46.  
  47. mutexB.release()
  48.  
  49. if __name__ == '__main__':
  50.  
  51. for i in range(10):
  52.  
  53. t=MyThread()
  54.  
  55. t.start()

1.3 信号量Semaphore

同进程的一样,Semaphore管理一个内置的计数器,每当调用acquire()时内置计数器-1;调用release() 时内置计数器+1;计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

实例:(同时只有5个线程可以获得semaphore,即可以限制最大连接数为5):

  1. from threading import Thread,Semaphore,current_thread
  2.  
  3. import time,random
  4.  
  5. sm=Semaphore(5)
  6.  
  7. def task():
  8.  
  9. with sm:
  10.  
  11. print('%s is laing' %current_thread().getName())
  12.  
  13. time.sleep(random.randint(1,3))
  14.  
  15. if __name__ == '__main__':
  16.  
  17. for i in range(20):
  18.  
  19. t=Thread(target=task)
  20.  
  21. t.start()

与进程池是完全不同的概念,进程池Pool(4),最大只能产生4个进程,而且从头到尾都只是这四个进程,不会产生新的,而信号量是产生一堆线程/进程

1.4 Event事件

同进程的一样,线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其 他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在 初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行

  1. event.isSet():返回event的状态值;
  2.  
  3. event.wait():如果 event.isSet()==False将阻塞线程;
  4.  
  5. event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
  6.  
  7. event.clear():恢复event的状态值为False

例如,有多个工作线程尝试链接MySQL,我们想要在链接前确保MySQL服务正常才让那些工作线程去连接MySQL服务器,如果连接不成功,都会去尝试重新连接。那么我们就可以采用threading.Event机制来协调各个工作线程的连接操作

  1. from threading import Thread,Event,current_thread
  2.  
  3. import time
  4.  
  5. event=Event()
  6.  
  7. def check():
  8.  
  9. print('checking MySQL...')
  10.  
  11. time.sleep(5)
  12.  
  13. event.set()
  14.  
  15. def conn():
  16.  
  17. count=1
  18.  
  19. while not event.is_set():
  20.  
  21. if count > 3:
  22.  
  23. raise TimeoutError('超时')
  24.  
  25. print('%s try to connect MySQL time %s' %(current_thread().getName(),count))
  26.  
  27. event.wait(1)
  28.  
  29. count+=1
  30.  
  31. print('%s connected MySQL' %current_thread().getName())
  32.  
  33. if __name__ == '__main__':
  34.  
  35. t1=Thread(target=check)
  36.  
  37. t2=Thread(target=conn)
  38.  
  39. t3=Thread(target=conn)
  40.  
  41. t4=Thread(target=conn)
  42.  
  43. t1.start()
  44.  
  45. t2.start()
  46.  
  47. t3.start()
  48.  
  49. t4.start()

1.5 定时器

定时器,指定n秒后执行某操作

  1. from threading import Timer
  2.  
  3. def hello(name):
  4.  
  5. print("hello, world %s " %name)
  6.  
  7. t = Timer(3, hello,args=('egon',))
  8.  
  9. t.start() # after 1 seconds, "hello, world" will be printed

1.6 线程queue

queue队列 :使用import queue,用法与进程Queue一样

  1. import queue
  2.  
  3. q=queue.Queue(3) #队列:先进先出
  4.  
  5. q.put(1)
  6.  
  7. q.put(2)
  8.  
  9. q.put(3)
  10.  
  11. # q.put(4)
  12.  
  13. # q.put_nowait(4)
  14.  
  15. # q.put(4,block=False)
  16.  
  17. q.put(4,block=True,timeout=3)
  18.  
  19. # print(q.get())
  20.  
  21. # print(q.get())
  22.  
  23. # print(q.get())
  24.  
  25. q=queue.LifoQueue(3) #堆栈:后进先出
  26.  
  27. q.put(1)
  28.  
  29. q.put(2)
  30.  
  31. q.put(3)
  32.  
  33. print(q.get())
  34.  
  35. print(q.get())
  36.  
  37. print(q.get())
  38.  
  39. q=queue.PriorityQueue(3) #优先级队列
  40.  
  41. q.put((10,'a'))
  42.  
  43. q.put((-3,'b'))
  44.  
  45. q.put((100,'c'))
  46.  
  47. print(q.get())
  48.  
  49. print(q.get())
  50.  
  51. print(q.get())

1.7 进程池线程池

#提交任务的两种方式:

#同步调用:提交完任务后,就在原地等待,等待任务执行完毕,拿到任务的返回值,才能继续下一行代码,导致程序串行执行

#异步调用+回调机制:提交完任务后,不在原地等待,任务一旦执行完毕就会触发回调函数的执行, 程序是并发执行

#进程的执行状态:

#阻塞

#非阻塞

1.7.1 同步调用示例:

# from multiprocessing import Pool

  1. from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
  2.  
  3. import time,random,os
  4.  
  5. def task(n):
  6.  
  7. print('%s is ruuning' %os.getpid())
  8.  
  9. time.sleep(random.randint(1,3))
  10.  
  11. return n**2
  12.  
  13. def handle(res):
  14.  
  15. print('handle res %s' %res)
  16.  
  17. if __name__ == '__main__':
  18.  
  19. #同步调用
  20.  
  21. pool=ProcessPoolExecutor(2)
  22.  
  23. for i in range(5):
  24.  
  25. res=pool.submit(task,i).result()
  26.  
  27. # print(res)
  28.  
  29. handle(res)
  30.  
  31. pool.shutdown(wait=True)
  32.  
  33. # pool.submit(task,33333)
  34.  
  35. print('主')

1.7.2 异步调用示例:

  1. from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
  2.  
  3. import time,random,os
  4.  
  5. def task(n):
  6.  
  7. print('%s is ruuning' %os.getpid())
  8.  
  9. time.sleep(random.randint(1,3))
  10.  
  11. # res=n**2
  12.  
  13. # handle(res)
  14.  
  15. return n**2
  16.  
  17. def handle(res):
  18.  
  19. res=res.result()
  20.  
  21. print('handle res %s' %res)
  22.  
  23. if __name__ == '__main__':
  24.  
  25. #异步调用
  26.  
  27. pool=ProcessPoolExecutor(2)
  28.  
  29. for i in range(5):
  30.  
  31. obj=pool.submit(task,i)
  32.  
  33. obj.add_done_callback(handle) #handle(obj)
  34.  
  35. pool.shutdown(wait=True)
  36.  
  37. print('主')

1.7.3 线程池

  1. from concurrent.futures import ThreadPoolExecutor
  2.  
  3. from threading import current_thread
  4.  
  5. import requests
  6.  
  7. import time
  8.  
  9. def get(url):
  10.  
  11. print('%s GET %s' %(current_thread().getName(),url))
  12.  
  13. response=requests.get(url)
  14.  
  15. time.sleep(2)
  16.  
  17. if response.status_code == 200:
  18.  
  19. return {'url':url,'content':response.text}
  20.  
  21. def parse(res):
  22.  
  23. res=res.result()
  24.  
  25. print('parse:[%s] res:[%s]' %(res['url'],len(res['content'])))
  26.  
  27. if __name__ == '__main__':
  28.  
  29. pool=ThreadPoolExecutor(2)
  30.  
  31. urls=[
  32.  
  33. 'https://www.baidu.com',
  34.  
  35. 'https://www.python.org',
  36.  
  37. 'https://www.openstack.org',
  38.  
  39. 'https://www.openstack.org',
  40.  
  41. 'https://www.openstack.org',
  42.  
  43. 'https://www.openstack.org',
  44.  
  45. 'https://www.openstack.org',
  46.  
  47. 'https://www.openstack.org',
  48.  
  49. 'https://www.openstack.org',
  50.  
  51. 'https://www.openstack.org',
  52.  
  53. 'https://www.openstack.org',
  54.  
  55. 'https://www.openstack.org',
  56.  
  57. ]
  58.  
  59. for url in urls:
  60.  
  61. pool.submit(get,url).add_done_callback(parse)
  62.  
  63. pool.shutdown(wait=True)

1.8 协程

单纯地切换反而会降低运行效率

协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

总结协程特点:

必须在只有一个单线程里实现并发

修改共享数据不需加锁

用户程序里自己保存多个控制流的上下文栈

附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))

1.8.1 串行执行

  1. import time
  2.  
  3. def consumer(res):
  4.  
  5. '''任务1:接收数据,处理数据'''
  6.  
  7. pass
  8.  
  9. def producer():
  10.  
  11. '''任务2:生产数据'''
  12.  
  13. res=[]
  14.  
  15. for i in range(10000000):
  16.  
  17. res.append(i)
  18.  
  19. return res
  20.  
  21. start=time.time()
  22.  
  23. #串行执行
  24.  
  25. res=producer()
  26.  
  27. consumer(res)
  28.  
  29. stop=time.time()
  30.  
  31. print(stop-start)

1.8.2 基于yield并发执行

  1. import time
  2.  
  3. def consumer():
  4.  
  5. '''任务1:接收数据,处理数据'''
  6.  
  7. while True:
  8.  
  9. print('consumer')
  10.  
  11. x=yield
  12.  
  13. time.sleep(100)
  14.  
  15. def producer():
  16.  
  17. '''任务2:生产数据'''
  18.  
  19. g=consumer()
  20.  
  21. next(g)
  22.  
  23. for i in range(10000000):
  24.  
  25. print('producer')
  26.  
  27. g.send(i)
  28.  
  29. start=time.time()
  30.  
  31. #基于yield保存状态,实现两个任务直接来回切换,即并发的效果
  32.  
  33. #PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
  34.  
  35. producer()
  36.  
  37. stop=time.time()
  38.  
  39. print(stop-start) #

1.9 greenlet模块

如果我们在单个线程内有20个任务,要想实现在多个任务之间切换,使用yield生成器的方式过于麻烦(需要先得到初始化一次的生成器,然后再调用send。。。非常麻烦),而使用greenlet模块可以非常简单地实现这20个任务直接的切换

安装模块

  1. pip3 install greenlet
  1. from greenlet import greenlet
  2.  
  3. import time
  4.  
  5. def eat(name):
  6.  
  7. print('%s eat 1' %name)
  8.  
  9. time.sleep(1000)
  10.  
  11. g2.switch('egon')
  12.  
  13. print('%s eat 2' %name)
  14.  
  15. g2.switch()
  16.  
  17. def play(name):
  18.  
  19. print('%s play 1' % name)
  20.  
  21. g1.switch() #可以在第一次switch时传入参数,以后都不需要
  22.  
  23. print('%s play 2' % name)
  24.  
  25. g1=greenlet(eat)
  26.  
  27. g2=greenlet(play)

greenlet只是提供了一种比generator更加便捷的切换方式,当切到一个任务执行时如果遇到io,那就原地阻塞,仍然是没有解决遇到IO自动切换来提升效率的问题。

单线程里的这20个任务的代码通常会既有计算操作又有阻塞操作,我们完全可以在执行任务1时遇到阻塞,就利用阻塞的时间去执行任务2。。。。如此,才能提高效率,这就用到了Gevent模块。

1.10 gevent模块

Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

#用法

  1. g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat
  2.  
  3. g2=gevent.spawn(func2)
  4.  
  5. g1.join() #等待g1结束
  6.  
  7. g2.join() #等待g2结束
  8.  
  9. #或者上述两步合作一步:gevent.joinall([g1,g2])
  10.  
  11. g1.value#拿到func1的返回值
  1. from gevent import monkey;monkey.patch_all()
  2.  
  3. import gevent
  4.  
  5. import time
  6.  
  7. def eat(name):
  8.  
  9. print('%s eat 1' %name)
  10.  
  11. # gevent.sleep(3)
  12.  
  13. time.sleep(3)
  14.  
  15. print('%s eat 2' %name)
  16.  
  17. def play(name):
  18.  
  19. print('%s play 1' % name)
  20.  
  21. # gevent.sleep(2)
  22.  
  23. time.sleep(3)
  24.  
  25. print('%s play 2' % name)
  26.  
  27. g1=gevent.spawn(eat,'egon')
  28.  
  29. g2=gevent.spawn(play,'alex')
  30.  
  31. # gevent.sleep(1)
  32.  
  33. # g1.join()
  34.  
  35. # g2.join()
  36.  
  37. gevent.joinall([g1,g2])

练习

通过gevent实现单线程下的socket并发(from gevent import monkey;monkey.patch_all()一定要放到导入socket模块之前,否则gevent无法识别socket的阻塞)

服务端

  1. from gevent import monkey,spawn;monkey.patch_all()
  2.  
  3. from threading import current_thread
  4.  
  5. from socket import *
  6.  
  7. def comunicate(conn):
  8.  
  9. print('子线程:%s' %current_thread().getName())
  10.  
  11. while True:
  12.  
  13. try:
  14.  
  15. data=conn.recv(1024)
  16.  
  17. if not data:break
  18.  
  19. conn.send(data.upper())
  20.  
  21. except ConnectionResetError:
  22.  
  23. break
  24.  
  25. conn.close()
  26.  
  27. def server(ip,port):
  28.  
  29. print('主线程:%s' %current_thread().getName())
  30.  
  31. server = socket(AF_INET, SOCK_STREAM)
  32.  
  33. server.bind((ip,port))
  34.  
  35. server.listen(5)
  36.  
  37. while True:
  38.  
  39. conn, addr = server.accept()
  40.  
  41. print(addr)
  42.  
  43. # comunicate(conn)
  44.  
  45. # t=Thread(target=comunicate,args=(conn,))
  46.  
  47. # t.start()
  48.  
  49. spawn(comunicate,conn)
  50.  
  51. server.close()
  52.  
  53. if __name__ == '__main__':
  54.  
  55. g=spawn(server,'127.0.0.1', 8081)
  56.  
  57. g.join()

客户端

多线程并发多个客户端

  1. from socket import *
  2.  
  3. from threading import current_thread,Thread
  4.  
  5. def client():
  6.  
  7. client=socket(AF_INET,SOCK_STREAM)
  8.  
  9. client.connect(('127.0.0.1',8081))
  10.  
  11. while True:
  12.  
  13. client.send(('%s say hello' %current_thread().getName()).encode('utf-8'))
  14.  
  15. data=client.recv(1024)
  16.  
  17. print(data.decode('utf-8'))
  18.  
  19. client.close()
  20.  
  21. if __name__ == '__main__':
  22.  
  23. for i in range(500):
  24.  
  25. t=Thread(target=client)
  26.  
  27. 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包安装

  1. yum -y install mysql-server mysql

二、源码安装

1.解压tar包

  1. cd /software
  2.  
  3. tar -xzvf mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz
  4.  
  5. mv mysql-5.6.21-linux-glibc2.5-x86_64 mysql-5.6.21

2.添加用户与组

  1. groupadd mysql
  2.  
  3. useradd -r -g mysql mysql
  4.  
  5. chown -R mysql:mysql mysql-5.6.21

3.安装数据库

  1. su mysql
  2.  
  3. cd mysql-5.6.21/scripts
  4.  
  5. ./mysql_install_db --user=mysql --basedir=/software/mysql-5.6.21 --datadir=/software/mysql-5.6.21/data

4.配置文件

  1. cd /software/mysql-5.6.21/support-files
  2.  
  3. cp my-default.cnf /etc/my.cnf
  4.  
  5. cp mysql.server /etc/init.d/mysql
  6.  
  7. vim /etc/init.d/mysql #若mysql的安装目录是/usr/local/mysql,则可省略此步
  8.  
  9. 修改文件中的两个变更值
  10.  
  11. basedir=/software/mysql-5.6.21
  12.  
  13. datadir=/software/mysql-5.6.21/data

5.配置环境变量

  1. vim /etc/profile
  2.  
  3. export MYSQL_HOME="/software/mysql-5.6.21"
  4.  
  5. export PATH="$PATH:$MYSQL_HOME/bin"
  6.  
  7. source /etc/profile

6.添加自启动服务

  1. chkconfig --add mysql
  2.  
  3. chkconfig mysql on

7.启动mysql

  1. service mysql start

8.登录mysql及改密码与配置远程访问

  1. mysqladmin -u root password 'your_password' #修改root用户密码
  2.  
  3. mysql -u root -p #登录mysql,需要输入密码
  4.  
  5. mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_password' WITH GRANT OPTION; #允许root用户远程访问
  6.  
  7. mysql>FLUSH PRIVILEGES; #刷新权限

三、源码安装mariadb

  1. 1. 解压
  1. tar zxvf mariadb-5.5.31-linux-x86_64.tar.gz
  2.  
  3. mv mariadb-5.5.31-linux-x86_64 /usr/local/mysql //必需这样,很多脚本或可执行程序都会直接访问这个目录
  1.  
  1. 2. 权限
  1. groupadd mysql //增加 mysql 属组
  2.  
  3. useradd -g mysql mysql //增加 mysql 用户 并归于mysql 属组
  4.  
  5. chown mysql:mysql -Rf /usr/local/mysql // 设置 mysql 目录的用户及用户组归属。
  6.  
  7. chmod +x -Rf /usr/local/mysql //赐予可执行权限
  1.  
  1. 3. 拷贝配置文件
  1. cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf //复制默认mysql配置 文件到/etc目录
  1.  
  1. 4. 初始化
  1. /usr/local/mysql/scripts/mysql_install_db --user=mysql //初始化数据库
  2.  
  3. cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql //复制mysql服务程序 到系统目录
  4.  
  5. chkconfig mysql on //添加mysql 至系统服务并设置为开机启动
  6.  
  7. service mysql start //启动mysql
  1.  
  1. 5. 环境变量配置
  1. vim /etc/profile //编辑profile,将mysql的可执行路径加入系统PATH
  2.  
  3. export PATH=/usr/local/mysql/bin:$PATH
  4.  
  5. source /etc/profile //使PATH生效。
  1.  
  1. 6. 账号密码
  1. mysqladmin -u root password 'yourpassword' //设定root账号及密码
  2.  
  3. mysql -u root -p //使用root用户登录mysql
  4.  
  5. use mysql //切换至mysql数据库。
  6.  
  7. select user,host,password from user; //查看系统权限
  8.  
  9. drop user ''@'localhost'; //删除不安全的账户
  10.  
  11. drop user root@'::1';
  12.  
  13. drop user root@127.0.0.1;
  14.  
  15. select user,host,password from user; //再次查看系统权限,确保不安全的账户均被删除。
  16.  
  17. flush privileges; //刷新权限
  1.  
  1. 7. 一些必要的初始配置
  1. 1)修改字符集为UTF8
  1. vi /etc/my.cnf
  2.  
  3. 在[client]下面添加 default-character-set = utf8
  4.  
  5. 在[mysqld]下面添加 character_set_server = utf8

2)增加错误日志

  1. vi /etc/my.cnf
  2.  
  3. 在[mysqld]下面添加:
  4.  
  5. log-error = /usr/local/mysql/log/error.log
  6.  
  7. general-log-file = /usr/local/mysql/log/mysql.log
  8.  
  9. 3) 设置为不区分大小写,linux下默认会区分大小写。
  10.  
  11. vi /etc/my.cnf
  12.  
  13. 在[mysqld]下面添加:
  14.  
  15. lower_case_table_name=1 
  1. 修改完重启:
  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、初始化

  1. mysqld --initialize-insecure

#5、启动MySQL服务

  1. mysqld # 启动MySQL服务

#6、启动MySQL客户端并连接MySQL服务

  1. mysql -u root -p # 连接MySQL服务器

将MySQL服务制作成windows服务

  1. 上一步解决了一些问题,但不够彻底,因为在执行【mysqd】启动MySQL服务器时,当前终端会被hang住,那么做一下设置即可解决此问题:
  1. 注意:--install前,必须用mysql启动命令的绝对路径
  1. # 制作MySQL的Windows服务,在终端执行此命令:
  1. "c:\mysql-5.7.16-winx64\bin\mysqld" --install
  1.  
  1. # 移除MySQL的Windows服务,在终端执行此命令:
  1. "c:\mysql-5.7.16-winx64\bin\mysqld" --remove
  1. 注册成服务之后,以后再启动和关闭MySQL服务时,仅需执行如下命令:
  1. # 启动MySQL服务
  1. net start mysql
  1. # 关闭MySQL服务
  1. net stop mysql

1.12 重置密码

1.12.1 设置密码

  1. C:\Users\Administrator> mysqladmin -uroot -p password ""

1.12.2 重置密码

  1. net stop MySQL
  2.  
  3. mysqld --skip-grant-tables
  4.  
  5. mysql -uroot -p
  6.  
  7. update mysql.user set password=password("") where user='root' and host="localhost";
  8.  
  9. flush privileges;
  10.  
  11. C:\Users\Administrator>tasklist |findstr mysql
  12.  
  13. mysqld.exe 6316 Console 1 454,544 K
  14.  
  15. C:\Users\Administrator>taskkill /F /PID 6316
  16.  
  17. 成功: 已终止 PID 6316 的进程。
  18.  
  19. C:\Users\Administrator>net start MySQL
  20.  
  21. MySQL 服务正在启动 .
  22.  
  23. MySQL 服务已经启动成功。

1.13 统一字符编码

#1. 修改配置文件

  1. [mysqld]
  2.  
  3. default-character-set=utf8
  4.  
  5. [client]
  6.  
  7. default-character-set=utf8
  8.  
  9. [mysql]
  10.  
  11. default-character-set=utf8
  12.  
  13. #mysql5.5以上:修改方式有所改动
  14.  
  15. [mysqld]
  16.  
  17. character-set-server=utf8
  18.  
  19. collation-server=utf8_general_ci
  20.  
  21. [client]
  22.  
  23. default-character-set=utf8
  24.  
  25. [mysql]
  26.  
  27. default-character-set=utf8

#2. 重启服务

#3. 查看修改结果:

  1. mysql> \s
  2.  
  3. 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  增

  1. create database db1 charset utf8;

1.14.1.2  查

  1. show databases;
  2.  
  3. show create database db1;

1.14.1.3  改

  1. alter database db1 charset gbk;

1.14.1.4  删

  1. drop database db1;

1.14.2 操作文件(表)

1.14.2.1  查看当前所在的文件夹:

  1. select database();

1.14.2.2  切换文件夹:

  1. use db1;

1.14.2.3  增

  1. create table t1(id int,name char);

1.14.2.4  查

  1. show tables;
  2.  
  3. show create table t1;
  4.  
  5. desc t1;

1.14.2.5  改

  1. alter table t1 add sex char;
  2.  
  3. alter table t1 drop sex;
  4.  
  5. alter table t1 modify name char(16);
  6.  
  7. alter table t1 change name Name char(13);

1.14.2.6  删

  1. drop table t1;

1.14.3 操作文件的内容(记录)

1.14.3.1  增

  1. insert into db1.t1 values
  2.  
  3. (1,'egon'),
  4.  
  5. (2,'alex'),
  6.  
  7. (3,'wxx');

1.14.3.2  查

  1. select id,name from db1.t1;
  2.  
  3. select * from db1.t1;

1.14.3.3  改

  1. update t1 set name='SB' where id=2;

1.14.3.4  删

  1. delete from t1 where id=2;

1.15 存储引擎

储引擎即表类型,mysql根据不同的表类型会有不同的处理机制

查看引擎

  1. show engines;

创建引擎

  1. create table t1(id int)engine=innodb;
  2.  
  3. create table t2(id int)engine=myisam;
  4.  
  5. create table t3(id int)engine=memory;
  6.  
  7. create table t4(id int)engine=blackhole;

1.16 数值类型

1.16.1 整型(默认有符号)

  1. create table t8(n tinyint);
  2.  
  3. insert into t8 values(-1);
  4.  
  5. insert into t8 values(128);
  6.  
  7. insert into t8 values(-129);
  8.  
  9. create table t9(n tinyint unsigned);
  10.  
  11. insert into t9 values(-1),(256);

#整型的宽度代表显示宽度

  1. create table t11(n int(3) unsigned zerofill);
  2.  
  3. create table t12(n int unsigned zerofill);
  4.  
  5. create table t13(
  6.  
  7. id int
  8.  
  9. );

1.16.2 浮点型

  1. create table t13(x float(255,30));
  2.  
  3. create table t14(x double(255,30));
  4.  
  5. create table t15(x decimal(65,30));
  6.  
  7. insert into t13 values(1.111111111111111111111111111111);
  8.  
  9. insert into t14 values(1.111111111111111111111111111111);
  10.  
  11. insert into t15 values(1.111111111111111111111111111111);

1.17 日期类型

  1. create table student(
  2.  
  3. id int,
  4.  
  5. name char(16),
  6.  
  7. born_year year,
  8.  
  9. birth_date date,
  10.  
  11. class_time time,
  12.  
  13. reg_time datetime
  14.  
  15. );
  16.  
  17. insert into student values
  18.  
  19. (1,'egon',now(),now(),now(),now())
  20.  
  21. ;
  22.  
  23. insert into student values
  24.  
  25. (2,'alex','','1999-11-11','11:11:11',"1999-11-11 11:11:11")

1.18 字符类型

char:定长

varchar:变长

#宽度代表的是字符的个数

  1. create table t16(name char(5));
  2.  
  3. create table t17(name varchar(5));
  4.  
  5. insert into t16 values('李杰 '); #'李杰 '
  6.  
  7. insert into t17 values('李杰 '); #'李杰 '
  8.  
  9. select char_length(name) from t16; #
  10.  
  11. select char_length(name) from t17; #
  12.  
  13. mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
  14.  
  15. select * from t16 where name='李杰';
  16.  
  17. select * from t17 where name='李杰';
  18.  
  19. select * from t16 where name like '李杰';
  20.  
  21. name char(5)
  22.  
  23. egon |alex |wxx |
  24.  
  25. name varchar(5)
  26.  
  27. 1bytes+egon|1bytes+alex|1bytes+wxx|

1.19 枚举类型与集合类型

  1. create table employee(
  2.  
  3. id int,
  4.  
  5. name char(10),
  6.  
  7. sex enum('male','female','other'),
  8.  
  9. hobbies set('play','eat','music','read')
  10.  
  11. );
  12.  
  13. insert into employee values
  14.  
  15. (1,'egon','male','music,read');
  16.  
  17. insert into employee values
  18.  
  19. (2,'alex','xxxx','music,read');

多线程与MySQL(十)的更多相关文章

  1. 手把手教你mysql(十)索引

    手把手教你mysql(十)索引 一:索引的引入 索引定义:索引是由数据库表中一列或者多列组合而成,其作用是提高对表中数据的查询速度. 类似于图书的目录,方便快速定位,寻找指定的内容,如一本1000页的 ...

  2. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  3. sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇(十五)

    Object中的wait.notify.notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑 通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁( ...

  4. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  5. “全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  7. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. Java 多线程基础(十)interrupt()和线程终止方式

    Java 多线程基础(十)interrupt()和线程终止方式 一.interrupt() 介绍 interrupt() 定义在 Thread 类中,作用是中断本线程. 本线程中断自己是被允许的:其它 ...

  9. Java 多线程基础(十二)生产者与消费者

    Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...

随机推荐

  1. 【Oracle】审计

    1.审计的功能:监控用户在database 的 action (操作) 2.审计分类: 1) session :在同一个session,相同的语句只产生一个审计结果(默认) 2) access : 在 ...

  2. 图像检索中为什么仍用BOW和LSH

    原文链接:http://blog.csdn.net/jwh_bupt/article/details/27713453 去年年底的时候在一篇博客中,用ANN的框架解释了BOW模型[1],并与LSH[2 ...

  3. 资源帖:CV代码库搜集

    2013计算机视觉代码合集一: 原文链接:http://www.yuanyong.org/blog/cv/cv-code-one 切记:一定要看原文链接 原文链接: http://blog.csdn. ...

  4. Windows 10 常用软件推荐

    QQ/TIM 大众的通讯工具,十多年之后的今天,依然是国内常驻用户第一的通讯工具 截图.远程桌面.视频会议.文件传送依旧是非常好用 TIM 算是轻聊版的升级版 微信 for Windows 近年新兴的 ...

  5. nodeJs的一些常识知识

    在项目目录中打开命令窗口 1. npm init 生成一个 package.json.(npm inii -y 直接生成,不用确定). 2.npm i . 下载 package.json devDep ...

  6. 一个单元格占两行三列的HTML代码为

    主要是这两个属性: colspan 单元格占多少列 rowspan 单元格占多少行 <table width="200" border="1">&l ...

  7. MySQL数据库具体一些操作

    创建数据库:CREATE DATABASE 数据库名;删除数据库:drop database <数据库名>;选择使用(需要操作的数据库):use 数据库名称;mysql数据库数据类型:类型 ...

  8. 无法打开文件"CChart_d.lib"

    把4个.lib文件删掉重新加一遍就好了

  9. HMM隐马尔可夫模型(词语粘合)

    HMM用于自然语言处理(NLP)中文分词,是用来描述一个含有隐含未知参数的马尔可夫过程,其目的是希望通过求解这些隐含的参数来进行实体识别,说简单些也就是起到词语粘合的作用. HMM隐马尔可夫模型包括: ...

  10. webpack学习笔记(3)--webpack.config.js

    module 参数 使用下面的实例来说明 module.exports = { module: { rules: [ { test: /\.css$/, use: 'css-loader' }, { ...