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