]>
Commit | Line | Data |
---|---|---|
562fda3a JP |
1 | #!/usr/bin/python |
2 | ||
3 | def get_backup_exceptions(path='/mit/sql/etc/db_no-daily-backup'): | |
4 | return filter(len, map(str.strip, file(path).read().split('\n'))) | |
5 | ||
6 | import MySQLdb, MySQLdb.cursors | |
7 | ||
8 | def use_db(cursor, db): | |
9 | cursor.execute('USE `%s`' % db) | |
10 | ||
0f682eea JP |
11 | def get_dbs(cursor, prefix=None): |
12 | cursor.execute('SHOW DATABASES' + (prefix and (' LIKE \'%s%%\'' % prefix) or '')) | |
562fda3a JP |
13 | return [x.values()[0] for x in cursor.fetchall() if x.values()[0] != 'information_schema'] |
14 | ||
15 | def get_db_tables(cursor, db): | |
16 | cursor.execute('SHOW TABLES FROM `%s`' % db) | |
17 | return [(db, x.values()[0]) for x in cursor.fetchall()] | |
18 | ||
19 | def get_db_tables_ft(cursor, db): | |
20 | r = [] | |
21 | for table in get_db_tables(cursor, db): | |
22 | cursor.execute('SHOW INDEXES FROM `%s`.`%s`' % table) | |
23 | r.extend(set([(db, x['Table']) for x in cursor.fetchall() if x['Index_type'] == 'FULLTEXT'])) | |
24 | return r | |
25 | ||
26 | def get_db_tables_status(cursor, db): | |
27 | cursor.execute('SHOW TABLE STATUS FROM `%s`' % db) | |
28 | return dict([((db, x['Name']), x) for x in cursor.fetchall()]) | |
29 | ||
0f682eea JP |
30 | def get_db_mtime(cursor, db): |
31 | db_mtimes = filter(lambda x: not x is None, [status['Update_time'] for table, status in get_db_tables_status(cursor, db).items()]) | |
32 | if len(db_mtimes): | |
33 | db_mtimes.sort(reverse=True) | |
34 | return db_mtimes[0] | |
35 | return 0 | |
36 | ||
37 | def get_db_size(cursor, db): | |
38 | return sum([status['Data_length'] for table, status in get_db_tables_status(cursor, db).items()]) | |
39 | ||
562fda3a JP |
40 | def get_db_tables_engines(cursor, db): |
41 | return [(table, status['Engine']) for table, status in get_db_tables_status(cursor, db).items()] | |
42 | ||
43 | def repair_table_quick(cursor, table): | |
44 | # REPAIR TABLE tbl QUICK | |
45 | # works when changing ft_min_word_len | |
46 | cursor.execute('REPAIR TABLE `%s`.`%s` QUICK' % table) | |
47 | ||
0f682eea | 48 | def repair_tables_from_stdin(cursor): |
562fda3a JP |
49 | while True: |
50 | data = sys.stdin.readline() | |
51 | if not data: | |
52 | break | |
53 | data = data.strip() | |
54 | table = eval(data) | |
55 | print table | |
56 | repair_table_quick(cursor, table) | |
0f682eea JP |
57 | |
58 | def backup_dbs(cursor): | |
59 | for db in get_dbs(cursor): | |
60 | db_size = get_db_size(cursor, db) | |
61 | if db_size < BACKUP_MAX_SIZE: | |
62 | if len(db.split('+')) <= 1: | |
63 | owner = 'root' | |
64 | else: | |
65 | owner = db.split('+')[0] | |
66 | ||
67 | db_mtime = get_db_mtime(cursor, db) | |
68 | try: | |
69 | bk_mtime = os.stat('%s/%s/%s.sql.gz' % (BACKUP_ROOT, owner, db))[stat.ST_MTIME] | |
70 | except: | |
71 | bk_mtime = 0 | |
72 | if not db_mtime or \ | |
73 | int(time.mktime(db_mtime.timetuple())) > bk_mtime: | |
74 | print db, 'DUMP' | |
75 | else: | |
76 | print db, 'SKIP (mtime: %s < %s)' % (str(db_mtime), | |
77 | time.strftime('%Y-%m-%d %H:%M:%S', | |
78 | time.localtime(bk_mtime))) | |
79 | else: | |
80 | print db, 'SKIP (size: %.2fM > %dM)' % (db_size/1024/1024, BACKUP_MAX_SIZE/1024/1024) | |
81 | ||
82 | if __name__ == '__main__': | |
83 | import sys, os, stat, time | |
84 | BACKUP_ROOT = '/afs/athena.mit.edu/contrib/sql/backup' | |
85 | BACKUP_MAX_SIZE = 200*1024*1024 | |
86 | ||
87 | cursor = MySQLdb.connect('localhost', read_default_group='client', cursorclass=MySQLdb.cursors.DictCursor).cursor() | |
88 | ||
89 |