Python增量循环删除MySQL表数据的方法


Posted in Python onSeptember 23, 2016

需求场景:

有一业务数据库,使用MySQL 5.5版本,每天会写入大量数据,需要不定期将多表中“指定时期前“的数据进行删除,在SQL SERVER中很容易实现,写几个WHILE循环就搞定,虽然MySQL中也存在类似功能,怎奈自己不精通,于是采用Python来实现

话不多少,上脚本:

# coding: utf-8
import MySQLdb
import time
# delete config
DELETE_DATETIME = '2016-08-31 23:59:59'
DELETE_ROWS = 10000
EXEC_DETAIL_FILE = 'exec_detail.txt'
SLEEP_SECOND_PER_BATCH = 0.5
DATETIME_FORMAT = '%Y-%m-%d %X'
# MySQL Connection Config
Default_MySQL_Host = 'localhost'
Default_MySQL_Port = 3358
Default_MySQL_User = "root"
Default_MySQL_Password = 'roo@01239876'
Default_MySQL_Charset = "utf8"
Default_MySQL_Connect_TimeOut = 120
Default_Database_Name = 'testdb001'
def get_time_string(dt_time):
"""
获取指定格式的时间字符串
:param dt_time: 要转换成字符串的时间
:return: 返回指定格式的字符串
"""
global DATETIME_FORMAT
return time.strftime(DATETIME_FORMAT, dt_time)
def print_info(message):
"""
将message输出到控制台,并将message写入到日志文件
:param message: 要输出的字符串
:return: 无返回
"""
print(message)
global EXEC_DETAIL_FILE
new_message = get_time_string(time.localtime()) + chr(13) + str(message)
write_file(EXEC_DETAIL_FILE, new_message)
def write_file(file_path, message):
"""
将传入的message追加写入到file_path指定的文件中
请先创建文件所在的目录
:param file_path: 要写入的文件路径
:param message: 要写入的信息
:return:
"""
file_handle = open(file_path, 'a')
file_handle.writelines(message)
# 追加一个换行以方便浏览
file_handle.writelines(chr(13))
file_handle.close()
def get_mysql_connection():
"""
根据默认配置返回数据库连接
:return: 数据库连接
"""
conn = MySQLdb.connect(
host=Default_MySQL_Host,
port=Default_MySQL_Port,
user=Default_MySQL_User,
passwd=Default_MySQL_Password,
connect_timeout=Default_MySQL_Connect_TimeOut,
charset=Default_MySQL_Charset,
db=Default_Database_Name
)
return conn
def mysql_exec(sql_script, sql_param=None):
"""
执行传入的脚本,返回影响行数
:param sql_script:
:param sql_param:
:return: 脚本最后一条语句执行影响行数
"""
try:
conn = get_mysql_connection()
print_info("在服务器{0}上执行脚本:{1}".format(
conn.get_host_info(), sql_script))
cursor = conn.cursor()
if sql_param is not None:
cursor.execute(sql_script, sql_param)
row_count = cursor.rowcount
else:
cursor.execute(sql_script)
row_count = cursor.rowcount
conn.commit()
cursor.close()
conn.close()
except Exception, e:
print_info("execute exception:" + str(e))
row_count = 0
return row_count
def mysql_query(sql_script, sql_param=None):
"""
执行传入的SQL脚本,并返回查询结果
:param sql_script:
:param sql_param:
:return: 返回SQL查询结果
"""
try:
conn = get_mysql_connection()
print_info("在服务器{0}上执行脚本:{1}".format(
conn.get_host_info(), sql_script))
cursor = conn.cursor()
if sql_param != '':
cursor.execute(sql_script, sql_param)
else:
cursor.execute(sql_script)
exec_result = cursor.fetchall()
cursor.close()
conn.close()
return exec_result
except Exception, e:
print_info("execute exception:" + str(e))
def get_id_range(table_name):
"""
按照传入的表获取要删除数据最大ID、最小ID、删除总行数
:param table_name: 要删除的表
:return: 返回要删除数据最大ID、最小ID、删除总行数
"""
global DELETE_DATETIME
sql_script = """
SELECT
MAX(ID) AS MAX_ID,
MIN(ID) AS MIN_ID,
COUNT(1) AS Total_Count
FROM {0}
WHERE create_time <='{1}';
""".format(table_name, DELETE_DATETIME)
query_result = mysql_query(sql_script=sql_script, sql_param=None)
max_id, min_id, total_count = query_result[0]
# 此处有一坑,可能出现total_count不为0 但是max_id 和min_id 为None的情况
# 因此判断max_id和min_id 是否为NULL
if (max_id is None) or (min_id is None):
max_id, min_id, total_count = 0, 0, 0
return max_id, min_id, total_count
def delete_data(table_name):
max_id, min_id, total_count = get_id_range(table_name)
temp_id = min_id
while temp_id <= max_id:
sql_script = """
DELETE FROM {0}
WHERE id <= {1}
and id >= {2}
AND create_time <='{3}';
""".format(table_name, temp_id + DELETE_ROWS, temp_id, DELETE_DATETIME)
temp_id += DELETE_ROWS
print(sql_script)
row_count = mysql_exec(sql_script)
print_info("影响行数:{0}".format(row_count))
current_percent = (temp_id - min_id) * 1.0 / (max_id - min_id)
print_info("当前进度{0}/{1},剩余{2},进度为{3}%".format(temp_id, max_id, max_id - temp_id, "%.2f" % current_percent))
time.sleep(SLEEP_SECOND_PER_BATCH)
print_info("当前表{0}已无需要删除的数据".format(table_name))
delete_data('TB001')
delete_data('TB002')
delete_data('TB003')

执行效果:

Python增量循环删除MySQL表数据的方法

实现原理:

由于表存在自增ID,于是给我们增量循环删除的机会,查找出满足删除条件的最大值ID和最小值ID,然后按ID 依次递增,每次小范围内(如10000条)进行删除。

实现优点:

实现“小斧子砍大柴”的效果,事务小,对线上影响较小,打印出当前处理到的“ID”,可以随时关闭,稍微修改下代码便可以从该ID开始,方便。

实现不足:

为防止主从延迟太高,采用每次删除SLEEP1秒的方式,相对比较糙,最好的方式应该是周期扫描这条复制链路,根据延迟调整SLEEP的周期,反正都脚本化,再智能化点又何妨!

以上所述是小编给大家介绍的Python增量循环删除MySQL表数据,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python网络爬虫与信息提取(实例讲解)
Aug 29 Python
Python 使用PIL中的resize进行缩放的实例讲解
Aug 03 Python
Python中对数组集进行按行打乱shuffle的方法
Nov 08 Python
使用Python的toolz库开始函数式编程的方法
Nov 15 Python
python写日志文件操作类与应用示例
Jul 01 Python
python 寻找离散序列极值点的方法
Jul 10 Python
安装Pycharm2019以及配置anconda教程的方法步骤
Nov 11 Python
python解释器pycharm安装及环境变量配置教程图文详解
Feb 26 Python
Python 实现将大图切片成小图,将小图组合成大图的例子
Mar 14 Python
keras slice layer 层实现方式
Jun 11 Python
keras 实现轻量级网络ShuffleNet教程
Jun 19 Python
python list等分并从等分的子集中随机选取一个数
Nov 16 Python
教你用Python脚本快速为iOS10生成图标和截屏
Sep 22 #Python
Python 制作糗事百科爬虫实例
Sep 22 #Python
Python 使用SMTP发送邮件的代码小结
Sep 21 #Python
Python 使用requests模块发送GET和POST请求的实现代码
Sep 21 #Python
Python中将字典转换为列表的方法
Sep 21 #Python
Python 两个列表的差集、并集和交集实现代码
Sep 21 #Python
python代码 if not x: 和 if x is not None: 和 if not x is None:使用介绍
Sep 21 #Python
You might like
浅析PHP的静态成员函数效率更高的原因
2014/06/13 PHP
PHP扩展开发入门教程
2015/02/26 PHP
PHP设置images目录不充许http访问的方法
2016/11/01 PHP
PHP7引入的&quot;??&quot;和&quot;?:&quot;的区别讲解
2019/04/08 PHP
javascript的原生方法获取数组中的最大(最小)值
2012/12/19 Javascript
Javascript模块化编程(一)模块的写法最佳实践
2013/01/17 Javascript
IE下Ajax缓存问题的快速解决方法(get方式)
2014/01/09 Javascript
5个JavaScript经典面试题
2014/10/13 Javascript
使用Javascript简单实现图片无缝滚动
2014/12/05 Javascript
JavaScript使用function定义对象并调用的方法
2015/03/23 Javascript
js实现简单div拖拽功能实例
2015/05/12 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
2016/05/25 Javascript
AngularJs Managing Service Dependencies详解
2016/09/02 Javascript
EasyUI 中combotree 默认不能选择父节点的实现方法
2016/11/07 Javascript
bootstrap选项卡使用方法解析
2017/01/11 Javascript
基于JS实现二维码图片固定在右下角某处并跟随滚动条滚动
2017/02/08 Javascript
vue keep-alive请求数据的方法示例
2018/05/16 Javascript
如何在Vue中使用CleaveJS格式化你的输入内容
2018/12/14 Javascript
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
详解element-ui设置下拉选择切换必填和非必填
2019/06/17 Javascript
vue实现页面内容禁止选中功能,仅输入框和文本域可选
2019/11/09 Javascript
小程序跳转到的H5页面再跳转回跳小程序的方法
2020/03/06 Javascript
python中PIL安装简单教程
2016/04/21 Python
Python通过matplotlib绘制动画简单实例
2017/12/13 Python
Django自定义过滤器定义与用法示例
2018/03/22 Python
Django跨域请求问题的解决方法示例
2018/06/16 Python
基于Python的自媒体小助手---登录页面的实现代码
2020/06/29 Python
浅析Python的命名空间与作用域
2020/11/25 Python
Python3使用Selenium获取session和token方法详解
2021/02/16 Python
如何开启linux的ssh服务
2015/02/14 面试题
授权委托书
2014/09/17 职场文书
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
MySQL 全文检索的使用示例
2021/06/07 MySQL
为什么在foreach循环中JAVA集合不能添加或删除元素
2021/06/11 Java/Android
《极主夫道》真人电影正式预告 定档6月3日上映
2022/04/05 日漫
MySQL数据库安装方法与图形化管理工具介绍
2022/05/30 MySQL