问题描述:
今天下午跑某项目db需求,百库百表清脏数据,然后自己写了个python脚本,跑完之后通知项目,然后项目给玩家发奖励了,结果悲催了,所有的mysql操作没有执行成功(没有报错,因而以为执行成功)。

以下是我的python脚本,传两个文件作为参数,host.txt 以及 update.sql

点击(此处)折叠或打开

#!/usr/bin/env python
#-*-coding:UTF-8-*-


importsys
importMySQLdb
importdatetime



dbuser='xxx'
dbpwd='xxx'

DB_NUM=100
TB_NUM=100
args=sys.argv
iflen(args)!=3:
print"USAGE: %s host.txt update.sql"%args[0]
sys.exit()

start=datetime.datetime.now()
print"Start Time : %s "%start.strftime('%Y-%m-%d %H:%M:%S')

hostfile=args[1]
sqlfile=args[2]

rhost=open(hostfile)
hostlist=rhost.readlines()
rhost.close()


rsqls=open(sqlfile)
sqllist=rsqls.readlines()
rsqls.close()

forhostinhostlist:
host=host.strip()
ip=host.split(' ')[0]
pt=host.split(' ')[1]
conn=MySQLdb.connect(ip,dbuser,dbpwd,port=int(pt))
cursor=conn.cursor()
cursor.execute('SET NAMES UTF8')
sqls=[]
foriinrange(DB_NUM):
sqls.append("%s"%str(i).zfill(2))
forsqlinsqls:
db=sql
#print'ip=%s ; port=%s ; db=%s'%(ip,pt,db)
forjinrange(TB_NUM):
ifTB_NUM>10:
j=str(j).zfill(2)
forsqlinsqllist:
ct=sql.strip()%(db,str(j)) cursor.execute(ct)
printct

conn.close()
end=datetime.datetime.now()
print"End Time : %s "%end.strftime('%Y-%m-%d %H:%M:%S')
update.sql如下:

点击(此处)折叠或打开

deletefromXSY_%s.t_xsy_equip_cloth_%swhere(clothid>=201675andclothid<=201700)or(clothid>=201725andclothid<=201751); host.txt如下:

点击(此处)折叠或打开

192.168.xx.xx 3306每执行一条语句都print出来,结果是成功打印出了10000条,但是上库看binlog日志并没有任何记录,数据也没有变化

解决:
临时写了个shell脚本,跑完需求,成功执行。
其中传入的$1为包含10000条操作的delete语句文件

点击(此处)折叠或打开

#!/bin/bashuser=xxxpwd=xxxwhile read sqldoecho $sql/usr/bin/mysql -h"192.168.xxx.xx" -P3306 -utab -ptab -e "${sql}"done < $1


发现问题:

开始以为自己远端没有执行,然后重新在test库上使用以上python脚本create百表,登上去查看,发现操作成功。
但是insert、update、以及delete操作无效。

查资料得知,mysql的ddl操作是隐式提交的,而dml是需要显示commit才能提交 成功,而我的这个python脚本没有调用cursor.commit(),故而close之后并没有提交相应的操作。

这里要区分shell中连接执行和python MySQLdb模块中连接执行的区别:

①shell中写的是连接到库上默认autocommit是开启的,故而执行时自动提交的,
②而pyrhon的该模块在dml操作之后调用conn.commit()显示提交或者在连接mysql之后执行设置conn.autocommit(1)。这是由于MySQLdb模块在连接mysql之后关闭了自动提交。需要注意的是这里针对的是innodb存储引擎,因为mysaim不支持事务