add rollback interval

This commit is contained in:
dfcao 2017-12-15 11:43:23 +08:00
parent 9a14642281
commit 1201a85406
3 changed files with 32 additions and 29 deletions

View File

@ -92,11 +92,13 @@ UPDATE `test`.`test3` SET `addtime`='2016-12-10 13:03:22', `data`='中文', `id`
-K, --no-primary-key 对INSERT语句去除主键。可选。
-B, --flashback 生成回滚语句可解析大文件不受内存限制每打印一千行加一句SELECT SLEEP(1)。可选。与stop-never或no-primary-key不能同时添加。
-B, --flashback 生成回滚语句可解析大文件不受内存限制。可选。与stop-never或no-primary-key不能同时添加。
--back-interval -B模式下每打印一千行回滚语句加一句SLEEP多少秒如果不需要SLEEP请设为0。可选。默认1.0。
**解析范围控制**
--start-file 起始解析文件。必须。
--start-file 起始解析文件,只需文件名,无需全路径 。必须。
--start-position/--start-pos start-file的起始解析位置。可选。默认为start-file的起始位置。
@ -114,6 +116,7 @@ UPDATE `test`.`test3` SET `addtime`='2016-12-10 13:03:22', `data`='中文', `id`
-t, --tables 只输出目标tables的sql。可选。默认为空。
### 应用案例
#### **误删整张表数据,需要紧急回滚**

View File

@ -11,15 +11,14 @@ from pymysqlreplication.row_event import (
DeleteRowsEvent,
)
from pymysqlreplication.event import QueryEvent, RotateEvent, FormatDescriptionEvent
from binlog2sql_util import command_line_args, concat_sql_from_binlog_event, create_unique_file, \
temp_open, print_rollback_sql
from binlog2sql_util import command_line_args, concat_sql_from_binlog_event, create_unique_file, temp_open, reversed_lines
class Binlog2sql(object):
def __init__(self, connection_settings, start_file=None, start_pos=None, end_file=None, end_pos=None,
start_time=None, stop_time=None, only_schemas=None, only_tables=None, no_pk=False,
flashback=False, stop_never=False):
flashback=False, stop_never=False, back_interval=1.0):
"""
conn_setting: {'host': 127.0.0.1, 'port': 3306, 'user': user, 'passwd': passwd, 'charset': 'utf8'}
"""
@ -43,7 +42,7 @@ class Binlog2sql(object):
self.only_schemas = only_schemas if only_schemas else None
self.only_tables = only_tables if only_tables else None
self.no_pk, self.flashback, self.stop_never = (no_pk, flashback, stop_never)
self.no_pk, self.flashback, self.stop_never, self.back_interval = (no_pk, flashback, stop_never, back_interval)
self.binlogList = []
self.connection = pymysql.connect(**self.conn_setting)
@ -122,9 +121,24 @@ class Binlog2sql(object):
stream.close()
f_tmp.close()
if self.flashback:
print_rollback_sql(filename=tmp_file)
self.print_rollback_sql(filename=tmp_file)
return True
def print_rollback_sql(self, filename):
"""print rollback sql from tmp_file"""
with open(filename, "rb") as f_tmp:
batch_size = 1000
i = 0
for line in reversed_lines(f_tmp):
print(line.rstrip())
if i >= batch_size:
i = 0
if self.back_interval:
print('SELECT SLEEP(%s);' % self.back_interval)
else:
i += 1
def __del__(self):
pass
@ -135,5 +149,6 @@ if __name__ == '__main__':
binlog2sql = Binlog2sql(connection_settings=conn_setting, start_file=args.start_file, start_pos=args.start_pos,
end_file=args.end_file, end_pos=args.end_pos, start_time=args.start_time,
stop_time=args.stop_time, only_schemas=args.databases, only_tables=args.tables,
no_pk=args.no_pk, flashback=args.flashback, stop_never=args.stop_never)
no_pk=args.no_pk, flashback=args.flashback, stop_never=args.stop_never,
back_interval=args.back_interval)
binlog2sql.process_binlog()

View File

@ -78,14 +78,13 @@ def parse_args():
"shell to set it properly).", default='')
interval.add_argument('--stop-datetime', dest='stop_time', type=str,
help="Stop reading the binlog at first event having a datetime equal or posterior "
"to the argument; the argument must be a date and time in the local time zone,"
" in any format accepted by the MySQL server for DATETIME and TIMESTAMP types,"
" for example: 2004-12-25 11:25:56 (you should probably use quotes for your "
"shell to set it properly).", default='')
"to the argument;", default='')
parser.add_argument('--stop-never', dest='stop_never', action='store_true',
help="Wait for more data from the server. default: stop replicate at the last binlog"
" when you start binlog2sql", default=False)
help="Wait for more data from the server. default: stop replicate at the last binlog "
"when you start binlog2sql", default=False)
parser.add_argument('--back-interval', dest='back_interval', type=float,
help="Sleep time between chunks of 1000 rollback sql. If you do not need sleep between chunks, "
" set it to 0", default=1.0)
parser.add_argument('--help', dest='help', action='store_true', help='help information', default=False)
schema = parser.add_argument_group('schema filter')
@ -217,20 +216,6 @@ def generate_sql_pattern(binlog_event, row=None, flashback=False, no_pk=False):
return {'template': template, 'values': list(values)}
def print_rollback_sql(filename):
"""print rollback sql from tmp_file"""
with open(filename, "rb") as f_tmp:
sleep_interval = 1000
i = 0
for line in reversed_lines(f_tmp):
print(line.rstrip())
if i >= sleep_interval:
print('SELECT SLEEP(1);')
i = 0
else:
i += 1
def reversed_lines(fin):
"""Generate the lines of file in reverse order."""
part = ''