python 使用連接池 連接 mysql
問題
當我們在Python中連接Mysql時,每次增、刪、改、查如果都申請一個數據庫連接的話,當應用程序對mysql數據庫請求量大時候,運行Python的機器就會大量報time wait(我碰到的是40000+) 。這是因為每次連接mysql數據庫請求時,都是獨立的去請求訪問(看到開發者的代碼后得出結論),相當浪費資源,訪問數量達到一定量時 ,運行程序的機器就報警了。
解決辦法:
訪問數據庫應該使用連接池,來達到復用數據庫連接的目的
python數據庫連接池使用方法:
a、安裝 DBUtils(這里是DBUtils-1.3.tar.gz包)
b、tar -zxvf DBUtils-1.3.tar.gz
c、cd DBUtils-1.3
d、 python setup.py install (安裝)
連接示例:
https://yq.aliyun.com/articles/619548?utm_content=m_1000008987
參考鏈接:https://www.jianshu.com/p/c5a8cccecf32
連接池操作示例:
https://zhuanlan.zhihu.com/p/61050785
安裝 DBUtils:
pip install DBUtils -i https://pypi.tuna.tsinghua.edu.cn/simple
代碼示例:
import pymysql from DBUtils.PooledDB import PooledDB ''' PooledDB() 參數含義 creator:使用鏈接數據庫的模塊 maxconnections:連接池允許的最大連接數,0和None表示沒有限制 mincached:初始化時,連接池至少創建的空閑的連接,0表示不創建 maxcached:連接池空閑的最多連接數,0和None表示沒有限制 maxshared:連接池中最多共享的連接數量,0和None表示全部共享,ps:其實並沒有什么用,因為pymsql和MySQLDB等模塊中的threadsafety都為1,所有值無論設置多少,_maxcahed永遠為0,所以永遠是所有鏈接共享 blocking:鏈接池中如果沒有可用共享連接后,是否阻塞等待,True表示等待,False表示不等待然后報錯 setsession:開始會話前執行的命令列表 ping:ping Mysql 服務端,檢查服務是否可用 ''' global_pool = PooledDB( creator=pymysql, maxconnections=500, mincached=0, maxcached=20, maxshared=0, blocking=True, setsession=[], ping=5, host=global_db_addr, port=3306, user='xxxx', password='xxxxxx', database='xxxxx', charset='utf8mb4') # 以后每次需要數據庫連接用 connection() 函數獲取連接即可 conn = global_pool.connection() # 使用 cursor() 方法創建一個游標對象 cursor cursor = conn.cursor() #sql = 'INSERT INTO ' + tbl_name + ' (`time_key`,`code`,`direct`) VALUES (%s, %s, %s);' #params = (dic_data["time_key"], dic_data["code"], dic_data["direct"]) tbl_name = 'stock_cur_kline_sh' stock_code = 'SH.600161' time_key = '2020-02-28 00:00:00' sql = "SELECT Close FROM " + tbl_name + " where code = '" + stock_code + "' and time_key = '" + time_key + "';" try: # 執行SQL語句 cursor.execute(sql) # 獲取所有記錄列表 results = cursor.fetchall() for row in results: close = row[0] # 打印結果 print("close=%f" %(close)) except Exception as e: print("插入數據庫異常, msg=%s" % (e)) logging.error(traceback.format_exc()) finally: print("插入數據庫成功") cursor.close() conn.close()
python3基礎:操作mysql數據庫
小小小小人ksh 2018-12-10 23:16:49 64543 收藏 494
分類專欄: python mysql
版權
mysql登陸
基本操作:
登陸:mysql -uroot -h127.0.0.1 -P3306 -p
mysql -uroot -p(本機不用寫host)
退出mysql:ctrl+z+回車,或者exit
端口號默認是3306,但是可以通過安裝目錄下的配置文件修改。
使用流程
引用API模塊
獲取與數據庫的連接
執行sql語句與存儲過程
關閉數據庫連接
安裝pymysql
python3 與MySQL 進行交互編程需要安裝 pymysql 庫,故首先使用如下命令安裝pymysql
–>pip install pymysql
如果電腦中py2和py3共存的話,安裝失敗時請參考之前的博客安裝方法
pymysql.connect()連接數據庫函數
代碼示例:
import pymysql
#打開數據庫連接
conn = pymysql.connect('localhost',user = "root",passwd = "123456",db = "testdb")
print (conn)
print (type(conn))
conn.cursor():獲取游標
要想操作數據庫,光連接數據是不夠的,必須拿到操作數據庫的游標,才能進行后續的操作,比如讀取數據、添加數據。通過獲取到的數據庫連接實例conn下的cursor()方法來創建游標。游標用來接收返回結果
代碼示例:
import pymysql
#打開數據庫連接
conn = pymysql.connect('localhost',user = "root",passwd = "123456",db = "testdb")
#獲取游標
cursor=conn.cursor()
print(cursor)
說明:cursor返回一個游標實例對象,其中包含了很多操作數據的方法,比如執行sql語句。
執行sql語句execute和executemany
execute(query,args=None)
函數作用:執行單條的sql語句,執行成功后返回受影響的行數
參數說明:
query:要執行的sql語句,字符串類型
args:可選的序列或映射,用於query的參數值。如果args為序列,query中必須使用%s做占位符;如果args為映射,query中必須使用%(key)s做占位符
executemany(query,args=None)
函數作用:批量執行sql語句,比如批量插入數據,執行成功后返回受影響的行數
參數說明:
query:要執行的sql語句,字符串類型
args:嵌套的序列或映射,用於query的參數值
注意:
1.數據庫性能瓶頸很大一部份就在於網絡IO和磁盤IO,將多個sql語句放在一起,只執行一次IO,可以有效的提升數據庫性能。推薦此方法
2.用executemany()方法一次性批量執行sql語句,固然很好,但是當數據一次傳入過多到server端,可能造成server端的buffer溢出,也可能產生一些意想不到的麻煩。所以,合理、分批次使用executemany是個合理的辦法
創建數據庫
代碼示例:
'''創建數據庫'''
import pymysql
#打開數據庫連接,不需要指定數據庫,因為需要創建數據庫
conn = pymysql.connect('localhost',user = "root",passwd = "123456")
#獲取游標
cursor=conn.cursor()
#創建pythonBD數據庫
cursor.execute('CREATE DATABASE IF NOT EXISTS pythonDB DEFAULT CHARSET utf8 COLLATE utf8_general_ci;')
cursor.close()#先關閉游標
conn.close()#再關閉數據庫連接
print('創建pythonBD數據庫成功')
創建表
代碼示例:
import pymysql
#打開數據庫連接
conn = pymysql.connect('localhost',user = "root",passwd = "123456",db = "testdb")
#獲取游標
cursor=conn.cursor()
print(cursor)
#創建user表
cursor.execute('drop table if exists user')
sql="""CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"""
cursor.execute(sql)
cursor.close()#先關閉游標
conn.close()#再關閉數據庫連接
print('創建數據表成功')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
插入單條數據
代碼示例:
'''插入單條數據'''
import pymysql
#打開數據庫連接,不指定數據庫
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
cur=conn.cursor()#獲取游標
#創建user表
cur.execute('drop table if exists user')
sql="""CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"""
cur.execute(sql)
insert=cur.execute("insert into user values(1,'tom',18)")
print('添加語句受影響的行數:',insert)
#另一種插入數據的方式,通過字符串傳入值
sql="insert into user values(%s,%s,%s)"
cur.execute(sql,(3,'kongsh',20))
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
批量插入多條數據
代碼示例:
'''插入多條數據'''
import pymysql
#打開數據庫連接,不指定數據庫
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#另一種插入數據的方式,通過字符串傳入值
sql="insert into user values(%s,%s,%s)"
insert=cur.executemany(sql,[(4,'wen',20),(5,'tom',10),(6,'test',30)])
print ('批量插入返回受影響的行數:',insert)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
注意:批量插入多條sql語句采用的是executemany(sql,args)函數,返回受影響的行數。args參數是一個包含多個元組的列表,每個元組對應一條mysql中的一條數據。這里的%s不需要加引號,否則插入數據的數據會類型錯誤
查詢數據
使用execute()函數得到的只是受影響的行數,並不能真正拿到查詢的內容。cursor對象還提供了3種提取數據的方法:fetchone、fetchmany、fetchall.。每個方法都會導致游標動,所以必須注意游標的位置。
cursor.fetchone():獲取游標所在處的一行數據,返回元組,沒有返回None
cursor.fetchmany(size):接受size行返回結果行。如果size大於返回的結果行的數量,則會返回cursor.arraysize條數據。
cursor. fetchall():接收全部的返回結果行。
代碼示例:fetchone
'''fetchone'''
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
cur.execute("select * from user;")
while 1:
res=cur.fetchone()
if res is None:
#表示已經取完結果集
break
print (res)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
注意:從execute()函數的查詢結果中取數據,以元組的形式返回游標所在處的一條數據,如果游標所在處沒有數據,將返回空元組,該數據執行一次,游標向下移動一個位置。fetchone()函數必須跟exceute()函數結合使用,並且在exceute()函數之后使用
代碼示例:fetchmany
‘’‘fetchmany’’’
import pymysql
#打開數據庫連接
conn=pymysql.connect(‘localhost’,‘root’,‘123456’)
conn.select_db(‘pythondb’)
#獲取游標
cur=conn.cursor()
cur.execute(“select * from user”)
#取3條數據
resTuple=cur.fetchmany(3)
print(type(resTuple))
for res in resTuple:
print (res)
cur.close()
conn.commit()
conn.close()
print(‘sql執行成功’)
注意:從exceute()函數結果中獲取游標所在處的size條數據,並以元組的形式返回,元組的每一個元素都也是一個由一行數據組成的元組,如果size大於有效的結果行數,將會返回cursor.arraysize條數據,但如果游標所在處沒有數據,將返回空元組。查詢幾條數據,游標將會向下移動幾個位置。fetmany()函數必須跟exceute()函數結合使用,並且在exceute()函數之后使用
代碼示例:fetchall
‘’‘fetchall’’’
import pymysql
#打開數據庫連接
conn=pymysql.connect(‘localhost’,‘root’,‘123456’)
conn.select_db(‘pythondb’)
#獲取游標
cur=conn.cursor()
cur.execute(“select * from user”)
#取所有數據
resTuple=cur.fetchall()
print(type(resTuple))
print (‘共%d條數據’%len(resTuple))
cur.close()
conn.commit()
conn.close()
print(‘sql執行成功’)
注意:獲取游標所在處開始及以下所有的數據,並以元組的形式返回,元組的每一個元素都也是一個由一行數據組成的元組,如果游標所在處沒有數據,將返回空元組。執行完這個方法后,游標將移動到數據庫表的最后
更新數據
代碼示例:更新單條數據
'''更新單條數據'''
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#更新一條數據
update=cur.execute("update user set age=100 where name='kongsh'")
print ('修改后受影響的行數為:',update)
#查詢一條數據
cur.execute(select * from user where name="kongsh";')
print(cur.fetchone())
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
代碼示例:更新多條數據
'''更新多條數據'''
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#更新前查詢所有數據
cur.execute("select * from user where name in ('kongsh','wen');")
print('更新前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#更新2條數據
sql="update user set age=%s where name=%s"
update=cur.executemany(sql,[(15,'kongsh'),(18,'wen')])
#更新2條數據后查詢所有數據
cur.execute("select * from user where name in ('kongsh','wen');")
print('更新后的數據為:')
for res in cur.fetchall():
print (res)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
刪除數據
代碼示例:刪除單條數據
'''刪除單條數據'''
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#刪除前查詢所有數據
cur.execute("select * from user;")
print('刪除前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#刪除1條數據
cur.execute("delete from user where id=1")
#刪除后查詢所有數據
cur.execute("select * from user;")
print('刪除后的數據為:')
for res in cur.fetchall():
print (res)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
代碼示例:刪除多條數據
'''刪除多條數據'''
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#刪除前查詢所有數據
cur.execute("select * from user;")
print('刪除前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#刪除2條數據
sql="delete from user where id=%s"
cur.executemany(sql,[(3),(4)])
#刪除后查詢所有數據
cur.execute("select * from user;")
print('刪除后的數據為:')
for res in cur.fetchall():
print (res)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
事務回滾
代碼示例:’’‘事務回滾’’'
import pymysql
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('pythondb')
#獲取游標
cur=conn.cursor()
#修改前查詢所有數據
cur.execute("select * from user;")
print('修改前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#更新表中第1條數據
cur.execute("update user set name='xiaoxiaoxiaoxiaoren' where id=5")
#修改后查詢所有數據
cur.execute("select * from user;")
print('修改后的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#回滾事務
conn.rollback()
cur.execute("select * from user;")
print('回滾事務后的數據為:')
for res in cur.fetchall():
print (res)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
練習:插入100條數據到數據庫
代碼示例:每次插入一條
'''插入100條數據到數據庫(每次插入一條)'''
import pymysql
import string,random
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('testdb')
#獲取游標
cur=conn.cursor()
#創建user表
cur.execute('drop table if exists user')
sql="""CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"""
cur.execute(sql)
#修改前查詢所有數據
cur.execute("select * from user;")
print('修改前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#循環插入數據
words=list(string.ascii_letters)
sql="insert into user values(%s,%s,%s)"
for i in range(100):
random.shuffle(words)#打亂順序
cur.execute(sql,(i+1,"".join(words[:5]),random.randint(0,80)))
#插入100條后查詢所有數據
cur.execute("select * from user;")
print('修改后的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
代碼示例:一次插入多條
'''插入100條數據到數據庫(一次插入多條)'''
import pymysql
import string,random
#打開數據庫連接
conn=pymysql.connect('localhost','root','123456')
conn.select_db('testdb')
#獲取游標
cur=conn.cursor()
#創建user表
cur.execute('drop table if exists user')
sql="""CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"""
cur.execute(sql)
#修改前查詢所有數據
cur.execute("select * from user;")
print('修改前的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
#循環插入數據
words=list(string.ascii_letters)
sql="insert into user values(%s,%s,%s)"
random.shuffle(words)#打亂順序
cur.executemany(sql,[(i+1,"".join(words[:5]),random.randint(0,80)) for i in range(100) ])
#插入100條后查詢所有數據
cur.execute("select * from user;")
print('修改后的數據為:')
for res in cur.fetchall():
print (res)
print ('*'*40)
cur.close()
conn.commit()
conn.close()
print('sql執行成功')
————————————————
https://blog.csdn.net/kongsuhongbaby/article/details/84948205
版權聲明:本文為CSDN博主「小小小小人ksh」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/kongsuhongbaby/article/details/84948205
https://blog.csdn.net/kongsuhongbaby/article/details/84948205
https://blog.csdn.net/kongsuhongbaby/article/details/84948205
