大数据测试之使用python快速插入mysql 1万条数据

背景

大数据测试,有时候需要造大量数据(造数可以看我另外一篇文章),而且需要经常使用脚本快速插入数据,插入数据一般常用的两种方式,一种是接口,一种是数据库插入。按照正常的逻辑,使用接口造数是最好的方式,因为不需要去关注数据库字段关联的问题,但接口会有瓶颈,需要依赖接口的稳定型以及性能。如果接口的稳定性,性能不行,那就只能是使用数据库插入的方式进行了。

脚本逻辑

根据业务逻辑,一个流程当作一个事务,一个事务由插入更新等操作。如果事务里某个环节失败,则回滚。使用多进程多协程进行并发造数。下面代码总共插入1万条数据只需要30秒左右。一个进程3000条,3个进程9000条数据。进程的,协程多少对性能会有影响,自己可以试试观察。

代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
# @Author      : lanny8588
# @File        : mysql_insert.py
# @Software    : PyCharm
# @Description :
"""
import pymysql
import random
from faker import Faker,Factory
import time
import gevent
from gevent import monkey; monkey.patch_all() #gevent得加上这个才能生效
import multiprocessing
class mysqlmanager(object):
    def __init__(self,user,password,database,host,port):
        self.user=user
        self.password=password
        self.database=database
        self.host=host
        self.port=port
        self.conn=None
        self.cur=None
    def connectDatabase(self):
        try:
            self.conn = pymysql.connect(self.host, self.user,self.password, self.database ,self.port,charset='utf8')
            print ("connectDatabase sucess")
        except Exception as  err:
            print ("connectDatabase failed",err)
            return False
        self.cur = self.conn.cursor()
        return True
    def dbclose(self):
        self.cur.close()
        self.conn.close()
    def dbcommit(self):
        self.conn.commit()
    def execute(self, sql,params=None):
        ''' 执行sql,每一个表操作都是一个事务,比如insert update 同一个表操作,如果某个环节失败,则回滚,返回fales,正确则返回true。'''
        print("----------插入数据----------" )
        try:
            self.cur.execute(sql,params)
            # self.conn.commit()
        except Exception as  err:
            print ('\033[1;31;0m\t4---插入更新失败,msg:\033[0m',err,sql.replace("\n", ""),params)
            self.conn.rollback() 
            return False
        return True
def run(min,max):
    dbhadle = mysqlmanager(user="xx", password="xxx", database="student", host="xxxxx",port=3306)
    dbhadle.connectDatabase()
    fake = Faker("zh_CN")  #这个申明会有点影响性能。
    for i in range (min,max):
        class_id=random.randint(1,6)
        name=fake.name()
        father=fake.name()
        phone=fake.phone_number()
        sn=fake.ean8()
        data1=(name,class_id,sn)
        sql1= '''
        INSERT into student2 (name,class_id,sn)
        VALUES(%s,%s,%s) 
        '''
        data2=(phone,sn)
        sql2= '''
        UPDATE student2 s2 set s2.phone=%s
        where sn=%s
        '''
        data3=(father,phone)
        sql3='''
        insert into student_family (father,fa_phone)
        VALUES (%s,%s);
        '''
        # print ("----------插入第%d数据----------"%i)
        insertdb=dbhadle.execute(sql1, data1)
        update=dbhadle.execute(sql2, data2)
        if update :  # 只有上一条执行成功了才能做下一步操作
            insertdb1=dbhadle.execute(sql3, data3)
        else:
            pass
        if insertdb and update and insertdb1 : #判断所有的数据成功才打印出成功插入数据的信息
            print("1---插入数据成功,%s,%s" % (sql1.replace("\n", ""), data1))
            print("2---更新数据成功,%s,%s" % (sql2.replace("\n", ""), data2))
            print("3---插入数据成功,%s,%s" % (sql3.replace("\n", ""), data3))

        dbhadle.dbcommit()
    dbhadle.dbclose()

def yibuzhixing():
    max_line = 500  # # 定义每次插入多少条。
    g_l = [gevent.spawn(run, i, i + max_line) for i in range(1, 30000, max_line)]#这里的数据代表是每个进程插入多少,这里的数据除以max_line ,代表启动多少线程。#这里的数据代表是每个进程插入多少,这里的数据除以max_line ,代表启动多少线程。
    gevent.joinall(g_l)    # 等待所以操作都执行完毕
if __name__ == '__main__':
    start_time = time.time()
    p = multiprocessing.Process(target=yibuzhixing)
    p2 = multiprocessing.Process(target=yibuzhixing)
    p3 = multiprocessing.Process(target=yibuzhixing)
    p.start()
    p2.start()
    p3.start()
    p.join()
    p2.join()
    p3.join()
    print("总共耗时%s"%(time.time()-start_time))
    
模拟

在自己本地数据库里创建一个数据库student库。
创建几个表:

 create table `class`( `id`  int not null  AUTO_INCREMENT, 
`name` char(16),
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8    #id是主键


CREATE TABLE `student2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(16) NOT NULL,
  `class_id` int(11) NOT NULL,
  `phone` char(11) DEFAULT NULL,
  `sn` char(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_phone` (`phone`) USING BTREE,
  UNIQUE KEY `IDX_sn` (`sn`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8;

CREATE TABLE `student_family` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `father` char(16) NOT NULL,
  `fa_phone` char(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_faphone` (`fa_phone`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=914 DEFAULT CHARSET=utf8;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值