python - MySQLdb 事務處理及批量執行executemany

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秒……

相關文章
相關標籤/搜索