MySQL數據庫有一個自動提交事務的概念,autocommit。含義是,若是開啓autocommit, 則每個語句執行後會自動提交。即一個語句視爲一個事務。
在python使用的MySQLdb中,默認是不開啓autocommit的。因此,只有在顯示commit後,數據庫操做纔會真正提交。或者在rollback()後,回滾到上一次commit的狀態。python
#!/bin/env python #coding=utf-8 import MySQLdb class MYSQL(object): def __init__(self): self.db = MySQLdb.connect("localhost","root","12345678","TESTTABLE",charset='utf8') self.cursor = self.db.cursor() def test(self): try: name = 't5' #insert sql = "insert into test_distinct(name, type) values('%s','1')" % name self.cursor.execute(sql) #search sql = "select * from test_distinct where name = '%s'" % name #查詢新插入的數據 self.cursor.execute(sql) res = self.cursor.fetchone() print res #insert sql = "update test_distinct set type='2' where name='%s'" % name raise #引發異常 self.cursor.execute(sql) except: self.db.rollback() else: self.db.commit() if __name__ == "__main__": obj = MYSQL() obj.test()
結果:sql
能夠正確查詢到新插入的數據,而且數據成功回滾,沒有寫入數據。
結論:數據庫
雖然沒有commit時,數據庫不會真正變化,可是會有一個臨時變化的版本,供咱們查詢還未真正加入的數據。app
=======================================================================================================================================less
批量執行(executemany):oop
轉載自:http://blog.csdn.net/colourless/article/details/41444069性能
先寫sql語句。要注意的是裏面的參數,無論什麼類型,統一使用%s做爲佔位符fetch
例如:url
向user表(username,salt,pwd)插入數據spa
sql = 'INSERT INTO 表名 VALUES(%s,%s,%s)'
對應的param是一個tuple或者list
param = ((username1, salt1, pwd1), (username2, salt2, pwd2), (username3, salt3, pwd3))
這樣就包含了三條數據,經過executemany插入
n=cursor.executemany(sql,param)
實例:
# ------------------------------------------- # Python MySQLdb 循環插入execute與批量插入executemany性能分析 # 插入數據量:10000條 # 每條字段:username, salt, pwd # Author : Lrg # ------------------------------------------- # encoding = utf-8 import MySQLdb import xlrd import time import sys reload(sys) sys.setdefaultencoding("utf-8") # 從users.xls文件獲取10000條用戶數據 # 該文件由create_users.py生成 def get_table(): FILE_NAME = 'users.xls' data = xlrd.open_workbook(FILE_NAME) table = data.sheets()[0] return table # 循環插入execute def insert_by_loop(table): nrows = table.nrows for i in xrange(1,nrows): param=[] try: sql = 'INSERT INTO user values(%s,%s,%s)' # 第一列username,第二列salt,第三列pwd print 'Insert: ',table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value param = (table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value) # 單條插入 cur.execute(sql, param) conn.commit() except Exception as e: print e conn.rollback() print '[insert_by_loop execute] total:',nrows-1 # 批量插入executemany def insert_by_many(table): nrows = table.nrows param=[] for i in xrange(1,nrows): # 第一列username,第二列salt,第三列pwd param.append([table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value]) try: sql = 'INSERT INTO user values(%s,%s,%s)' # 批量插入 cur.executemany(sql, param) conn.commit() except Exception as e: print e conn.rollback() print '[insert_by_many executemany] total:',nrows-1 # 鏈接數據庫 conn = MySQLdb.connect(host="127.0.0.1", port=3306, user="lrg", passwd="lrg", db="pythontest") cur = conn.cursor() # 新建數據庫 cur.execute('DROP TABLE IF EXISTS user') sql = """CREATE TABLE user( username CHAR(255) NOT NULL, salt CHAR(255), pwd CHAR(255) )""" cur.execute(sql) # 從excel文件獲取數據 table = get_table() # 使用循環插入 start = time.clock() insert_by_loop(table) end = time.clock() print '[insert_by_loop execute] Time Usage:',end-start # 使用批量插入 start = time.clock() insert_by_many(table) end = time.clock() print '[insert_by_many executemany] Time Usage:',end-start # 釋放數據鏈接 if cur: cur.close() if conn: conn.close()
一共10000條數據一行行循環execute,耗時200秒左右(下面244秒的數據是每次循環加了輸出語句的,應該有點影響)而用executemany一次提交所有,耗時只有0.86秒……