【MySQL】删除大量数据的具体实现

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:
ourmysql博客中提供了 《 大表删除数据的思路 》,对于大表依据主键删除的思路是必须的,删除几千万的数据还算是比较简单的,如果你的数据库中的表高达数百亿条记录 ,删除其中的几十亿,就需要考虑可用性的问题了。上述文中的 利用生成的文本方式有些不妥。
我的方法是利用存储过程,游标,先根据条件获取要删除的主键,然后依据主键删除,考虑到删除50亿条记录耗费将近7天的时间(事后得出),必须后台执行。使用python 工具写一个脚本,可以针对多个服务器进行并行操作。
1 在各个服务器上创建存过!
delimiter //
CREATE  PROCEDURE `proc_del_tab`(in com_num int , in push_time datetime ) 
begin
    declare curid bigint ;
    DECLARE rowid bigint ;
    declare no_more_departments int ;
    declare curs cursor for
        select id
        from
            tab
        WHERE
            v3 < push_time ;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_departments = 1;
    SET no_more_departments=0;
    set rowid = 1 ;
    set autocommit = 0 ;
    open curs ;
    REPEAT
        fetch curs into curid ;
        delete from tab where id = curid ;
        set rowid = rowid + 1 ;
        if rowid % com_num = 0
        then
            commit;
        end if ;
    UNTIL no_more_departments
    END REPEAT;
    commit ;
    close curs ;
end;
//
delimiter ; 

2 部署python 脚本:
#!/usr/bin/env python
from MySQLdb import *
import sys
import threading
import time
import os
def now() :
        #return str('2011-01-31 00:00:00')
        return str( time.strftime( '%Y-%m-%d %H:%M:%S' , time.localtime() ) )
def log( strs , logs ) :
        f = file( logs , 'a' , 0 )
        f.write( now() + ' ' + str(strs) + '\n' )
        f.close()

def delining( cur , logs ) :
        sql = "SET SQL_LOG_BIN=0"
        try :
                cur['dsn'].execute( sql )
        except Exception , e :
                log( 'Set SQL_LOG_BIN OFF' + str(e) , logs )
        sql = "call proc_del_tab_yang( 3000 , '%s' )" % ('2011-01-31 00:00:00')
        log( 'starting process %s' % ( cur['addr'] ) , logs )
        try :
                cur['dsn'].execute( sql )
        except Exception , e :
                log( 'Execute Procedure ' + str(e) , logs )
        sql = "SET SQL_LOG_BIN=1"
        try :
                cur['dsn'].execute( sql )
        except Exception , e :
                log( 'Set SQL_LOG_BIN ON' + str(e) , logs )
        log( 'process %s End' % ( cur['addr'] ) , logs )
def main() :
        logs = "/root/yangql/python/del_test_tab.log"
        server_list=['10.250.7.110']
        luser="yang"
        lpasswd="yang"
        con = []
        for addr in server_list :
                cons = None
                try :
                        cons = connect( host = addr , user = luser , passwd = lpasswd , port = 3307 , db = 'newcloudapp' )
                except Exception , e :
                        log( 'On Connect %s ' % ( addr ) + str(e) , logs )
                        continue
                con.append(  { 'dsn':cons , 'addr':addr } )
        cur = []
        for cons in con :
                try :
                        cur.append( { 'dsn':cons['dsn'].cursor( cursorclass = cursors.DictCursor ) , 'addr':cons['addr'] } )
                except Exception , e :
                        log( 'On Cusros %s ' % ( cons['addr'] ) + str(e)  , logs )
                        continue
        thpool = []
        for curs in cur :
                th = threading.Thread(target = delining ,args=( curs , logs ) )
                thpool.append( th )
        for th in thpool :
                th.start()
        for th in thpool :
                threading.Thread.join( th )
        while True :
                if threading.activeCount() < 2 :
                        break
                else :
                        time.sleep(1)
                        continue
        for curs in cur :
                try :
                        curs['dsn'].close()
                except Exception , e :
                        log( 'On Close Cusros %s ' % ( curs['addr'] ) + str(e)  , logs )
                        continue
        for cons in con :
                try :
                        cons['dsn'].close()
                except Exception , e :
                        log( 'On Close Connect %s ' % ( str(e)  ) , logs )
                        continue
if __name__ == '__main__' :
        main()


欢迎大家提出更好的方法。。
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
缓存 NoSQL 关系型数据库
13- Redis和Mysql如何保证数据⼀致?
该内容讨论了保证Redis和MySQL数据一致性的几种策略。首先提到的两种方法存在不一致风险:先更新MySQL再更新Redis,或先删Redis再更新MySQL。第三种方案是通过MQ异步同步以达到最终一致性,适用于一致性要求较高的场景。项目中根据不同业务需求选择不同方案,如对一致性要求不高的情况不做处理,时效性数据设置过期时间,高一致性需求则使用MQ确保同步,最严格的情况可能涉及分布式事务(如Seata的TCC模式)。
35 6
|
15天前
|
SQL 关系型数据库 MySQL
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
|
22天前
|
关系型数据库 MySQL
elasticsearch对比mysql以及使用工具同步mysql数据全量增量
elasticsearch对比mysql以及使用工具同步mysql数据全量增量
20 0
|
25天前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
20 1
|
25天前
|
Java 关系型数据库 数据库连接
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
24 1
|
1月前
|
SQL 关系型数据库 MySQL
MySQL怎样删除重复数据,只保留一条?
MySQL怎样删除重复数据,只保留一条?
|
25天前
Mybatis+mysql动态分页查询数据案例——条件类(HouseCondition)
Mybatis+mysql动态分页查询数据案例——条件类(HouseCondition)
15 1
|
25天前
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
20 1
|
25天前
Mybatis+mysql动态分页查询数据案例——房屋信息的实现类(HouseDaoMybatisImpl)
Mybatis+mysql动态分页查询数据案例——房屋信息的实现类(HouseDaoMybatisImpl)
21 2
|
25天前
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
15 1