Created
April 3, 2012 09:58
-
-
Save methane/2290769 to your computer and use it in GitHub Desktop.
古いレコード削除プログラム
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| # coding: utf-8 | |
| from __future__ import print_function | |
| import datetime as dt | |
| import os | |
| import sys | |
| import time | |
| import logging | |
| from ConfigParser import SafeConfigParser | |
| import optparse | |
| try: | |
| import MySQLdb | |
| except ImportError: | |
| try: | |
| import PyMySQL as MySQLdb | |
| except ImportError: | |
| print("Please install MySQL-python or PyMySQL.", file=sys.stderr) | |
| sys.exit(1) | |
| def connect(conf='~/.my.cnf', section='batch'): | |
| """ | |
| connect to MySQL from conf file. | |
| """ | |
| parser = SafeConfigParser() | |
| parser.read([os.path.expanduser(conf)]) | |
| config = dict(parser.items(section)) | |
| params = {} | |
| for n in ('host', 'user', 'db'): | |
| if n in config: | |
| params[n] = config[n] | |
| if 'port' in config: | |
| params['port'] = int(config['port']) | |
| if 'password' in config: | |
| params['passwd'] = config['password'] | |
| return MySQLdb.connect(**params) | |
| def delete_old_log(con, tablename, days, blocksize=1000): | |
| u"""ログテーブルから古いログを消す. | |
| MySQL への接続 *con* を利用し、 *tablename* で指定された | |
| テーブルから、 *days* で指定された日数よりも古いテーブルを | |
| 削除する. (*days* が 0 の時は、昨日以前のログを消す) | |
| 対象となるテーブルは、PK が整数の `id` というカラム名で | |
| autoincrement されていて、 `created_at` というカラム名で | |
| 作成日時が記録されている必要がある. | |
| *blocksize* は一括で削除する行数. | |
| .. note: | |
| 制限として、 *blocksize* の間に消す日と消さない日の | |
| 区切りがあると、そのブロックにある古いレコードを消さない | |
| まま終了している. (テーブルサイズ肥大化抑止が目的のため) | |
| """ | |
| date = dt.date.today() - dt.timedelta(days=days) | |
| logging.info("delete records befor %s", date) | |
| cur = con.cursor() | |
| cur.execute("SELECT min(id),max(id) from %s" % (tablename,)) | |
| MIN, MAX = map(int, cur.fetchone()) | |
| for s in xrange(MIN, MAX, blocksize): | |
| cur = con.cursor() | |
| e = min(s + blocksize - 1, MAX) | |
| cur.execute("SELECT created_at from %s WHERE id=%s" % (tablename, e)) | |
| d = cur.fetchone()[0] | |
| if d is None: | |
| raise ValueError("created_at is NULL: pk=%r" % (e,)) | |
| if d.date() >= date: | |
| break | |
| logging.debug("deleting %s-%s (%s)", s, e, d) | |
| q = "DELETE LOW_PRIORITY FROM %s WHERE `id`<=%d" % (tablename, e) | |
| logging.debug(q) | |
| cur.execute(q) | |
| con.commit() | |
| time.sleep(1) | |
| def main(): | |
| parser = optparse.OptionParser("%prog [OPTIONS] tablename") | |
| parser.add_option('-d', '--days', type='int', default=30) | |
| parser.add_option('-s', '--section', type='string', action="store", default='batch') | |
| parser.add_option('-b', '--blocksize', type='int', default=1000) | |
| parser.add_option('-v', '--verbose', action='store_const', const=1, default=0) | |
| opts, args = parser.parse_args() | |
| if not args: | |
| parser.error("Only one tablename should be specified.") | |
| loglevel = logging.DEBUG if opts.verbose else logging.INFO | |
| logging.basicConfig(level=loglevel, | |
| format="%(asctime)-15s %(levelname)9s %(message)s", | |
| ) | |
| con = connect(section=opts.section) | |
| for table in args: | |
| logging.info("Start deleting old logs from: %s", table) | |
| delete_old_log(con, table, opts.days) | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment