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的Django框架中的Cookie相关处理
Jul 22 Python
Python切片知识解析
Mar 06 Python
浅谈使用Python内置函数getattr实现分发模式
Jan 22 Python
Python实现JSON反序列化类对象的示例
Jan 31 Python
Numpy数组的保存与读取方法
Apr 04 Python
Python实现的栈、队列、文件目录遍历操作示例
May 06 Python
django多个APP的urls设置方法(views重复问题解决)
Jul 19 Python
如何使用django的MTV开发模式返回一个网页
Jul 22 Python
如何更改 pandas dataframe 中两列的位置
Dec 27 Python
python如何把字符串类型list转换成list
Feb 18 Python
python实现用户名密码校验
Mar 18 Python
用python实现一个简单计算器(完整DEMO)
Oct 14 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
PHP4 与 MySQL 数据库操作函数详解
2006/12/06 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
PHP静态成员变量和非静态成员变量详解
2017/02/14 PHP
PHP+RabbitMQ实现消息队列的完整代码
2019/03/20 PHP
laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
2020/01/25 PHP
Array, Array Constructor, for in loop, typeof, instanceOf
2011/09/13 Javascript
利用javascript打开模态对话框(示例代码)
2014/01/11 Javascript
jquery ajax 如何向jsp提交表单数据
2015/08/23 Javascript
Javascript的表单验证长度
2016/03/16 Javascript
如何消除inline-block属性带来的标签间间隙
2016/03/31 Javascript
jQuery中选择器的基础使用教程
2016/05/23 Javascript
JS中事件冒泡和事件捕获介绍
2016/12/13 Javascript
JS实现复制功能
2017/03/01 Javascript
Angular1.x自定义指令实例详解
2017/03/01 Javascript
vue子组件使用自定义事件向父组件传递数据
2017/05/27 Javascript
浅谈react-native热更新react-native-pushy集成遇到的问题
2017/09/30 Javascript
JsChart组件使用详解
2018/03/04 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
vue3.0中友好使用antdv示例详解
2021/01/05 Vue.js
Python urllib模块urlopen()与urlretrieve()详解
2013/11/01 Python
浅谈Python 字符串格式化输出(format/printf)
2016/07/21 Python
Python爬虫抓取代理IP并检验可用性的实例
2018/05/07 Python
在python中按照特定顺序访问字典的方法详解
2018/12/14 Python
详解python中的生成器、迭代器、闭包、装饰器
2019/08/22 Python
Django实现文件上传下载功能
2019/10/06 Python
python读取raw binary图片并提取统计信息的实例
2020/01/09 Python
tensorflow实现二维平面模拟三维数据教程
2020/02/11 Python
Python Selenium实现无可视化界面过程解析
2020/08/25 Python
CSS3实现彩色进度条动画的示例
2020/10/29 HTML / CSS
世界首屈一指的钓鱼用品商店:TackleDirect
2016/07/26 全球购物
第一范式(1NF)、第二范式(2NF)和第三范式(3NF)之间的区别是什么?
2016/04/28 面试题
高中生打架检讨书1000字
2015/02/17 职场文书
小学感恩节活动总结
2015/03/24 职场文书
2015企业年终工作总结范文
2015/05/27 职场文书
校园安全教育心得体会
2016/01/15 职场文书
PHP使用非对称加密算法RSA
2021/04/21 PHP