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

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()

欢迎大家提出更好的方法。。

时间: 2024-12-23 19:00:29

【MySQL】删除大量数据的具体实现的相关文章

MySQL删除/更新数据时报1175错误

原文 MySQL删除/更新数据时报1175错误 今天删除mysql数据库中的一条记录的时候,一直不能删除,提示错误信息如下: [html] view plaincopy Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that    [html] view plaincopy uses a KEY column To disable safe mode

MYSQL删除重复数据的简单方法_Mysql

复制代码 代码如下: CREATETABLE`users`(`id`int(10)NOTNULLAUTO_INCREMENT,`name`char(50)NOTNULL,PRIMARYKEY(`id`)) 复制代码 代码如下: deletefromuserswhereidin(selectmin(id)fromusersgroupbynamehavingcount(name)>1); 结果报错:1093youcan'tspecifytargettable.... 原因是mysql删除动作不能带有

mysql删除重复数据记录sql语句总结

我最常用的方法是  代码如下 复制代码 //删除id重复的数据,适合id是手工主键 delete person as a from person as a, (     select *,min(id) from person group by id having count(1) > 1 ) as b where a.id = b.id //查找重复的,并且除掉最小的那个  代码如下 复制代码 delete tb_person as a from tb_person as a, ( selec

MySQL中删除重复数据的简单方法_Mysql

MYSQL里有五百万数据,但大多是重复的,真实的就180万,于是想怎样把这些重复的数据搞出来,在网上找了一圈,好多是用NOT IN这样的代码,这样效率很低,自己琢磨组合了一下,找到一个高效的处理方式,用这个方式,五百万数据,十来分钟就全部去除重复了,请各位参考. 第一步:从500万数据表data_content_152里提取出不重复的字段SFZHM对应的ID字段到TMP3表 create table tmp3 as select min(id) as col1 from data_content

MySQL 删除数据库中重复数据方法小结_Mysql

刚开始,根据我的想法,这个很简单嘛,上sql语句 delete from zqzrdp where tel in (select min(dpxx_id) from zqzrdp group by tel having count(tel)>1); 执行,报错!!~!~ 异常意为:你不能指定目标表的更新在FROM子句.傻了,MySQL 这样写,不行,让人郁闷. 难倒只能分步操作,蛋疼 以下是网友写的,同样是坑爹的代码,我机器上运行不了. 1. 查询需要删除的记录,会保留一条记录. select

sql 删除重复数据

sql 删除重复数据 本文章提供一款mysql删除重复数据,就是数据表中存在二条以上的重复数据,删除编号最小的一条信息. delete `borough_name` as a from fke_borough as a, ( select *,min(id) from fke_borough group by `borough_name` having count(1) > 1 ) as b  where a.`borough_name` = b.`borough_name` and a.id

select-Mysql删除重复数据只保留一条

问题描述 Mysql删除重复数据只保留一条 Mysql删除重复数据只保留一条,我的sql这样的 DELETE from t_patient WHERE pa_iid IN (select pa_iid from t_patient group by pa_vname having count(pa_vname)>1) 但是报错了: [Err] 1093 - You can't specify target table 't_patient' for update in FROM clause 求

mysql-MySQL 删除重复数据(两个字段)

问题描述 MySQL 删除重复数据(两个字段) 表full中userID和movieID两个字段确定一条唯一的数据. 现在表中有少量重复数据和大量非重复数据. 重复数据中,preference列和timestamp列不为空的这些,需要保留:preference列和timestamp列为空的这些需要删除,应该怎么办? 初学者,希望答案详细:) 感激不尽 +------------+---------+------+-----+---------+-------+ | Field | Type |

MySQL处理重复数据的方法_Mysql

有些 MySQL 数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据. 本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据.防止表中出现重复数据 你可以在MySQL数据表中设置指定的字段为 PRIMARY KEY(主键) 或者 UNIQUE(唯一) 索引来保证数据的唯一性. 让我们尝试一个实例:下表中无索引及主键,所以该表允许出现多条重复记录. CREATE TABLE person_tbl ( first_name CHA

很全面的MySQL处理重复数据代码_Mysql

有些 MySQL 数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据. 本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据. 一.防止表中出现重复数据 你可以在MySQL数据表中设置指定的字段为 PRIMARY KEY(主键) 或者 UNIQUE(唯一) 索引来保证数据的唯一性. 让我们尝试一个实例:下表中无索引及主键,所以该表允许出现多条重复记录. CREATE TABLE person_tbl ( first_name