Ejemplo n.º 1
0
def main():

    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=3,
        blocking=True,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    s3 = boto3.resource('s3')

    previous_events = []

    for binlogevent in stream:
        prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                print vals
            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = row["after_values"]
                print vals
            elif isinstance(binlogevent, WriteRowsEvent):
                s3.Bucket(S3_SETTINGS['bucket_name']).put_object(
                    Key="awef" + str(random.random()) + ".txt",
                    Body=str(row["values"]))

    stream.close()
Ejemplo n.º 2
0
def test_binlog_info():
    binlog_conf = {
        "host": "127.0.0.1",
        "port": 3306,
        "user": "******",
        "passwd": "ekpapi",
        "charset": 'utf8',
        "db": "xserver"
    }
    stream = BinLogStreamReader(
        connection_settings=binlog_conf,
        server_id=2,
        only_tables=["test"],
        only_schemas=["xserver"],
        # only_events=[QueryEvent],
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
        blocking=True)

    count = 0
    for binlog_event in stream:
        print stream.log_file
        print stream.log_pos
        binlog_event.dump()
        print "rows: %s" % binlog_event.rows
        count += 1
    print count
    stream.close()
Ejemplo n.º 3
0
class MySQL(Listener):
    @classmethod
    def new(cls, node: DBNode, dsn: DSN, server_id: int) -> 'Listener':
        return cls(node, dsn, server_id)

    def __init__(self, node: DBNode, dsn: DSN, server_id: int):
        self.node = node
        self.dsn = dsn
        self.server_id = server_id

    def get_stream(self, log_file: Optional[str],
                   log_pos: int) -> BinLogStreamReader:
        blocking = False
        if log_file is None:
            self.stream = BinLogStreamReader(
                connection_settings=self.dsn.get_args(),
                server_id=self.server_id,
                blocking=blocking)
        else:
            self.stream = BinLogStreamReader(
                connection_settings=self.dsn.get_args(),
                server_id=self.server_id,
                blocking=blocking,
                log_file=log_file,
                log_pos=log_pos)
        return self.stream

    def close(self):
        self.stream.close()
def main():
    # connect rethinkdb
    rethinkdb.connect("localhost", 28015, "mysql")
    try:
        rethinkdb.db_drop("mysql").run()
    except:
        pass
    rethinkdb.db_create("mysql").run()

    tables = [
        "dept_emp", "dept_manager", "titles", "salaries", "employees",
        "departments"
    ]
    for table in tables:
        rethinkdb.db("mysql").table_create(table).run()

    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        blocking=True,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
    )

    # process Feed
    for binlogevent in stream:
        if not isinstance(binlogevent, WriteRowsEvent):
            continue

        for row in binlogevent.rows:
            if not binlogevent.schema == "employees":
                continue

            vals = dict((str(k), str(v)) for k, v in row["values"].iteritems())
            rethinkdb.table(binlogevent.table).insert(vals).run()

    stream.close()
Ejemplo n.º 5
0
    def transfer(self):
        """
        sync mysql binlog data to redis
        :return:
        """
        log_file, log_pos = self._get_log_pos()
        log_pos = int(log_pos) if log_pos else log_pos
        stream = BinLogStreamReader(
            connection_settings=self.MYSQL_SETTINGS,
            server_id=int(self.SELF['server_id']),
            only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
            resume_stream=True,
            log_file=log_file,
            log_pos=log_pos,
            blocking=True)
        for binlog_event in stream:
            prefix = f'{binlog_event.schema}:{binlog_event.table}:'
            self._set_log_pos(stream.log_file, stream.log_pos)
            for row in binlog_event.rows:
                if isinstance(binlog_event, DeleteRowsEvent):
                    self._delete_handler(prefix=prefix, row=row)
                if isinstance(binlog_event, UpdateRowsEvent):
                    self._update_handler(prefix=prefix, row=row)
                if isinstance(binlog_event, WriteRowsEvent):
                    self._write_handler(prefix=prefix, row=row)

        stream.close()
Ejemplo n.º 6
0
def main():
    producer = Kafka_producer("10.40.58.114", 9092, "tmysql")
    mysql_settings = {'host': '10.40.63.52', 'port': 3306, 'user': '******', 'passwd': 'zaq1xsw2'}
    stream = BinLogStreamReader(connection_settings=mysql_settings, server_id=7765,
                                only_schemas=["test"],
                                only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
                                resume_stream=True,
                                blocking=True)

    for binlogevent in stream:
        for row in binlogevent.rows:
            event = {"schema": binlogevent.schema, "table": binlogevent.table,
                     "log_pos": binlogevent.packet.log_pos}
            if isinstance(binlogevent, DeleteRowsEvent):
                event["action"] = "delete"
                event["values"] = dict(row["values"].items())
                event = dict(event.items())
            elif isinstance(binlogevent, UpdateRowsEvent):
                event["action"] = "update"
                event["before_values"] = dict(row["before_values"].items())
                event["after_values"] = dict(row["after_values"].items())
                event = dict(event.items())
            elif isinstance(binlogevent, WriteRowsEvent):
                event["action"] = "insert"
                event["values"] = dict(row["values"].items())
                event = dict(event.items())
            print(json.dumps(event, cls=DateEncoder))
            producer.sendjsondata(json.dumps(event, cls=DateEncoder))
            sys.stdout.flush()

    stream.close()
Ejemplo n.º 7
0
def main():
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=3,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    s3 = boto3.resource('s3')

    for binlogevent in stream:
        dump = []

        for row in binlogevent.rows:
            event = {"schema": binlogevent.schema, "table": binlogevent.table}

            #if isinstance(binlogevent, DeleteRowsEvent):
                #event["action"] = "delete"
                #event = dict(event.items() + row["values"].items())
            
            if isinstance(binlogevent, WriteRowsEvent):
                event["action"] = "insert"
                event = dict(event.items())
                event["values"] = row["values"]

                if "created_at" in event["values"].keys():
                    dump.append( event )

            elif isinstance(binlogevent, UpdateRowsEvent):
                event["action"] = "update"
                event = dict(event.items() + row["after_values"].items())
            
            if len(dump) > MAX_DUMP_SIZE:
                s3.Bucket(S3_SETTINGS['bucket_name']).put_object(Key=event["table"] + "/"+ partition(event["values"]) + "/0" ".json", Body=str(event["values"]))

    stream.close()
Ejemplo n.º 8
0
class MySQLConnector:
    """
    The Elastic Replicator create a stream to the MySQL database
    and allow to send the specific row to the elastic.
    """
    def __init__(self,
                 mysql_settings,
                 events,
                 blocking,
                 id_label="_id",
                 skip_to_timestamp=None):
        self.stream = BinLogStreamReader(connection_settings=mysql_settings,
                                         server_id=3,
                                         only_events=events,
                                         blocking=blocking,
                                         skip_to_timestamp=skip_to_timestamp)
        self.id_label = id_label

    def get_id_label(self):
        return self.id_label

    def get_stream(self):
        return self.stream

    def get_id(self, row):
        return row[self.id_label]

    def __del__(self):
        self.stream.close()
Ejemplo n.º 9
0
	def proc_binlog(self):
		stream = BinLogStreamReader(
			connection_settings = self.config['mysql'],
			server_id = self.config['slave']['server_id'],
			log_file = self.log_file,
			log_pos = self.log_pos,
			only_schemas = self.config['slave']['schemas'],
			blocking = True,
			resume_stream = bool(self.log_file and self.log_pos),
			only_events=[WriteRowsEvent, UpdateRowsEvent, DeleteRowsEvent]
		)
		for binlogevent in stream:
			self.log_file = stream.log_file
			self.log_pos  = stream.log_pos
			for row in binlogevent.rows:		
				pk     = binlogevent.primary_key			
				table  = binlogevent.table
				schema = binlogevent.schema

				if isinstance(binlogevent, WriteRowsEvent):
					yield self.es.index_op(self._format(row['values']), doc_type=table, index=schema, id=row['values'][pk])
				elif isinstance(binlogevent, UpdateRowsEvent):
					yield self.es.update_op(self._format(row['after_values']), doc_type=table, index=schema, id=row['after_values'][pk])
				elif isinstance(binlogevent, DeleteRowsEvent):
					yield self.es.delete_op(doc_type=table, index=schema, id=row['values'][pk])
				else:
					logging.warning("unsupport event type")
					continue
	
		stream.close()
Ejemplo n.º 10
0
def main():
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=1,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
        only_tables=ONLY_Tables)

    for binlogevent in stream:
        prefix = "%s-%s-" % (binlogevent.schema, binlogevent.table)
        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                print "[Delete] SQLBinLog Row :" + str(row)
                updateRediSCache(False, prefix, vals.keys(), vals)
            elif isinstance(binlogevent, UpdateRowsEvent):
                before_values = row["before_values"]
                after_values = row["after_values"]
                print "[Update] SQLBinLog Row :" + str(row)
                updateRediSCache(True, prefix,
                                 diff(before_values, after_values).keys(),
                                 after_values)
            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                print "[Insert] SQLBinLog Row :" + str(row)
                updateRediSCache(True, prefix, vals.keys(), vals)

    stream.close()
def main():
    # connect rethinkdb
    rethinkdb.connect("localhost", 28015, "mysql")
    try:
        rethinkdb.db_drop("mysql").run()
    except:
        pass
    rethinkdb.db_create("mysql").run()

    tables = ["dept_emp", "dept_manager", "titles",
              "salaries", "employees", "departments"]
    for table in tables:
        rethinkdb.db("mysql").table_create(table).run()

    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        blocking=True,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
    )

    # process Feed
    for binlogevent in stream:
        if not isinstance(binlogevent, WriteRowsEvent):
            continue

        for row in binlogevent.rows:
            if not binlogevent.schema == "employees":
                continue

            vals = {}
            vals = {str(k): str(v) for k, v in row["values"].iteritems()}
            rethinkdb.table(binlogevent.table).insert(vals).run()

    stream.close()
Ejemplo n.º 12
0
    def transfer(self):
        log_file, log_pos = self.get_log_pos()
        stream = BinLogStreamReader(
            connection_settings=self.MYSQL_SETTINGS,
            server_id=int(self.SELF["server_id"]),
            only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
            log_file=log_file,
            log_pos=log_pos,
            blocking=True)

        print "sync"
        for binlogevent in stream:
            prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)
            self.set_log_pos(stream.log_file, stream.log_pos)

            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    self.delete_handler(prefix, row)

                elif isinstance(binlogevent, UpdateRowsEvent):
                    self.update_handler(prefix, row)

                elif isinstance(binlogevent, WriteRowsEvent):
                    self.insert_handler(prefix, row)

        stream.close()
Ejemplo n.º 13
0
def main():
    log_file, log_pos = get_log_pos()
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=11,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
        #log_file = "mysql-bin.000001",
        #log_pos = "12812",
        blocking=True)

    print "sync"
    for binlogevent in stream:
        prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)
        set_log_pos(stream.log_file, stream.log_pos)

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                r.delete(prefix + str(vals["id"]))

            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = row["after_values"]
                r.hmset(prefix + str(vals["id"]), vals)

            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                r.hmset(prefix + str(vals["id"]), vals)

    stream.close()
def main():
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    for binlogevent in stream:
        for row in binlogevent.rows:
            event = {}
            event["schema"] = binlogevent.schema
            event["table"] = binlogevent.table

            if isinstance(binlogevent, DeleteRowsEvent):
                event["action"] = "delete"
                event = dict(event.items() + row["values"].items())
            elif isinstance(binlogevent, UpdateRowsEvent):
                event["action"] = "update"
                event = dict(event.items() + row["after_values"].items())
            elif isinstance(binlogevent, WriteRowsEvent):
                event["action"] = "insert"
                event = dict(event.items() + row["values"].items())
            print json.dumps(event)
            sys.stdout.flush()


    stream.close()
Ejemplo n.º 15
0
def readBinLog():
    stream = BinLogStreamReader(
        connection_settings=mysql_settings,
        server_id=3,
        blocking=True,
        only_tables=['order_info','log_info'],
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    for binlogevent in stream:
        for row in binlogevent.rows:
            event = { "schema": binlogevent.schema, "table": binlogevent.table, "log_pos": binlogevent.packet.log_pos }
            if isinstance(binlogevent, DeleteRowsEvent):
                event["action"] = "delete"
                event["origin"] = dict(row["values"].items())
                event["current"] = None
                event = dict(event.items())
            elif isinstance(binlogevent, UpdateRowsEvent):
                event["action"] = "update"
                event["origin"] = dict(row["before_values"].items())
                event["current"] = dict(row["after_values"].items())
                event = dict(event.items())
            elif isinstance(binlogevent, WriteRowsEvent):
                event["action"] = "insert"
                event["origin"] = None
                event["current"] = dict(row["values"].items())
                event = dict(event.items())
            sendBinLog(event)
    stream.close()
Ejemplo n.º 16
0
def main():
    stream = BinLogStreamReader(connection_settings=SMYSQL_SETTINGS,
                                server_id=server_id,
                                resume_stream=True,
                                auto_position=gtid_next,
                                only_schemas=only_schemas,
                                ignored_schemas=ignored_schemas,
                                only_tables=only_tables,
                                ignored_tables=ignored_tables,
                                only_events=[
                                    DeleteRowsEvent, WriteRowsEvent,
                                    UpdateRowsEvent, GtidEvent
                                ])

    con = pymysql.connect(**SMYSQL_SETTINGS)
    template = ''
    values = []
    cursor = con.cursor()
    redis_con = redis_pool(REDIS_SETTINGS)
    for binlogevent in stream:
        if isinstance(binlogevent, GtidEvent):
            pre_gtid_next = redis_con.hget('gtid_next', redis_chanel)
            redis_con.hset('pre_gtid_next', redis_chanel, pre_gtid_next)
            redis_con.hset('gtid_next', redis_chanel, binlogevent.gtid)
        else:
            #schema = binlogevent.schema
            if target_schemas.has_key(binlogevent.schema):
                schema = target_schemas[binlogevent.schema]
            else:
                schema = binlogevent.schema
            table = binlogevent.table
            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    template = 'DELETE FROM `{0}`.`{1}` WHERE {2} LIMIT 1;'.format(
                        schema, table,
                        ' AND '.join(map(compare_items,
                                         row['values'].items())))
                    values = map(fix_object, row['values'].values())
                elif isinstance(binlogevent, UpdateRowsEvent):
                    template = 'UPDATE `{0}`.`{1}` SET {2} WHERE {3} LIMIT 1;'.format(
                        schema, table, ', '.join([
                            '`%s`=%%s' % k for k in row['after_values'].keys()
                        ]), ' AND '.join(
                            map(compare_items, row['before_values'].items())))
                    values = map(
                        fix_object,
                        list(row['after_values'].values()) +
                        list(row['before_values'].values()))
                elif isinstance(binlogevent, WriteRowsEvent):
                    template = 'INSERT INTO `{0}`.`{1}`({2}) VALUES({3});'.format(
                        schema, table, ', '.join(
                            map(lambda key: '`%s`' % key,
                                row['values'].keys())),
                        ', '.join(['%s'] * len(row['values'])))
                    values = map(fix_object, row['values'].values())
                sql = cursor.mogrify(template, values)
                #redis_con.publish(redis_chanel, sql)
                con, cursor = con_mysql(DMYSQL_SETTINGS)
                sync_binlog(con, cursor, sql)
    stream.close()
Ejemplo n.º 17
0
 def process_binlog(self):
     """
     :parameter last_events 标志是否读取到最后一个事件
     :parameter 允许读取的MySQL语句
     """
     last_events = False
     allow_sql = ['update', 'delete', 'insert', 'CREATE', 'DROP']
     stream = BinLogStreamReader(connection_settings=self.conn_setting,
                                 server_id=1)
     for binlog_events in stream:
         if binlog_events.event_type == 2:
             # 读取query语句
             query = binlog_events.query
             # 空格分割 获取命令query[0]
             query_ = query.split(' ')
             # print(query_)
             if query_[0] in allow_sql:
                 self.current.append(binlog_events.query)
             #print(self.current)
         # 读取到最后一个事件
         #if stream.log_file == self.end_file and stream.log_pos == self.eof_pos:
         #last_events = True
         # 不退出循环表示获取实时mysql语句
         if last_events == True: break
     stream.close()
     print(self.current)
Ejemplo n.º 18
0
    def process_binlog(self):
        sqlList = []
        stream = BinLogStreamReader(connection_settings=self.conn_setting, server_id=self.server_id,
                                    log_file=self.start_file, log_pos=self.start_pos, only_schemas=self.only_schemas,
                                    only_tables=self.only_tables, resume_stream=True)

        flag_last_event = False
        e_start_pos, last_pos = stream.log_pos, stream.log_pos
        # to simplify code, we do not use flock for tmp_file.
        tmp_file = create_unique_file('%s.%s' % (self.conn_setting['host'], self.conn_setting['port']))
        with temp_open(tmp_file, "w") as f_tmp, self.connection as cursor:
            for binlog_event in stream:
                if not self.stop_never:
                    try:
                        event_time = datetime.datetime.fromtimestamp(binlog_event.timestamp)
                    except OSError:
                        event_time = datetime.datetime(1980, 1, 1, 0, 0)
                    if (stream.log_file == self.end_file and stream.log_pos == self.end_pos) or \
                            (stream.log_file == self.eof_file and stream.log_pos == self.eof_pos):
                        flag_last_event = True
                    elif event_time < self.start_time:
                        if not (isinstance(binlog_event, RotateEvent)
                                or isinstance(binlog_event, FormatDescriptionEvent)):
                            last_pos = binlog_event.packet.log_pos
                        continue
                    elif (stream.log_file not in self.binlogList) or \
                            (self.end_pos and stream.log_file == self.end_file and stream.log_pos > self.end_pos) or \
                            (stream.log_file == self.eof_file and stream.log_pos > self.eof_pos) or \
                            (event_time >= self.stop_time):
                        break
                    # else:
                    #     raise ValueError('unknown binlog file or position')

                if isinstance(binlog_event, QueryEvent) and binlog_event.query == 'BEGIN':
                    e_start_pos = last_pos

                if isinstance(binlog_event, QueryEvent) and not self.only_dml:
                    sql = concat_sql_from_binlog_event(cursor=cursor, binlog_event=binlog_event,
                                                       flashback=self.flashback, no_pk=self.no_pk)
                    if sql:
                        sqlList.append(sql)
                elif is_dml_event(binlog_event) and event_type(binlog_event) in self.sql_type:
                    for row in binlog_event.rows:
                        sql = concat_sql_from_binlog_event(cursor=cursor, binlog_event=binlog_event, no_pk=self.no_pk,
                                                           row=row, flashback=self.flashback, e_start_pos=e_start_pos)
                        if self.flashback:
                            f_tmp.write(sql + '\n')
                        else:
                            sqlList.append(sql)

                if not (isinstance(binlog_event, RotateEvent) or isinstance(binlog_event, FormatDescriptionEvent)):
                    last_pos = binlog_event.packet.log_pos
                if flag_last_event:
                    break

            stream.close()
            f_tmp.close()
            if self.flashback:
                return self.get_rollback_sql(filename=tmp_file)
        return sqlList
Ejemplo n.º 19
0
def main():
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=3,
        blocking=True,
        only_schemas=["jintui"],
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])
    producer = KafkaProducer(kafka_setting, topic_setting)
    for binlogevent in stream:
        for row in binlogevent.rows:
            event = {"schema": binlogevent.schema, "table": binlogevent.table}
            if isinstance(binlogevent, DeleteRowsEvent):
                event["action"] = "delete"
                event["values"] = dict(row["values"].items())
                event = dict(event.items())
            elif isinstance(binlogevent, UpdateRowsEvent):
                event["action"] = "update"
                event["before_values"] = dict(row["before_values"].items())
                event["after_values"] = dict(row["after_values"].items())
                event = dict(event.items())
            elif isinstance(binlogevent, WriteRowsEvent):
                event["action"] = "insert"
                event["values"] = dict(row["values"].items())
                event = dict(event.items())
            print json.dumps(event)
            sys.stdout.flush()

    stream.close()
Ejemplo n.º 20
0
def main():
    rclient = redis.from_url(redis_url)
    cache = rcache.Rcache(cache_url, server_id)
 
    log_file = rclient.get("log_file")
    log_pos = rclient.get("log_pos")
    log_pos = int(log_pos) if log_pos else None
 
    only_events = _trans_events(events)
    only_events.append(RotateEvent)
 
    stream = BinLogStreamReader(
        connection_settings=mysql_settings,
        server_id=server_id,
        blocking=blocking,
        only_events=only_events,                                                                                                                                                       
        only_tables=tables,
        only_schemas=schemas,
        resume_stream=True,  # for resuming
        freeze_schema=False, # do not support alter table event for faster
        log_file=log_file,
        log_pos=log_pos)
    row_count = 0
 
    for binlogevent in stream:
        if int(time.time()) - binlogevent.timestamp > binlog_max_latency:
            logger.warn("latency[{}] too large".format(
                int(time.time()) - binlogevent.timestamp))
        logger.debug("catch {}".format(binlogevent.__class__.__name__))
        if isinstance(binlogevent, RotateEvent):  #listen log_file changed event
            rclient.set("log_file", binlogevent.next_binlog)
            rclient.set("log_pos", binlogevent.position)
            logger.info("log_file:{}, log_position:{}".format(
                binlogevent.next_binlog, binlogevent.position))
        else:
            row_count += 1
            table = "%s.%s" % (binlogevent.schema, binlogevent.table)
            vals_lst = _get_row_values(binlogevent)
            if not binlogevent.primary_key:
                tables_without_primary_key.get(table, None)
            try:
                cache.save(table, binlogevent.primary_key, vals_lst)
                logger.debug("save {} {} rows to cache".format(
                    table, len(vals_lst)))
            except rcache.SaveIgnore as err:
                logger.warning(str(err))
            except rcache.FullError as err:
                logger.info("cache OOM occured: {}.trigger dump command".format(
                    str(err)))
                dump_code = _trigger_dumping()
                cache.save(table, binlogevent.primary_key, vals_lst)
            if cache_max_rows and cache.size > cache_max_rows:
                logger.info("cache size:{} >= {}, trigger dumping".format(
                   cache.size, cache_max_rows))
                _trigger_dumping()
            rclient.set("log_pos", binlogevent.packet.log_pos)
        if row_count % 1000 == 0:
            logger.info("save {} changed rows".format(row_count))
 
    stream.close()
Ejemplo n.º 21
0
    def process_binlog(self):
        stream = BinLogStreamReader(connection_settings=self.conn_setting, server_id=self.server_id,
                                    log_file=self.start_file, log_pos=self.start_pos, only_schemas=self.only_schemas,
                                    only_tables=self.only_tables, resume_stream=True, blocking=True)

        flag_last_event = False
        e_start_pos, last_pos = stream.log_pos, stream.log_pos
        # to simplify code, we do not use flock for tmp_file.
        tmp_file = create_unique_file('%s.%s' % (self.conn_setting['host'], self.conn_setting['port']))
        with open(tmp_file, "w") as f_tmp, self.connection as cursor:
            for binlog_event in stream:
                if isinstance(binlog_event, QueryEvent) and binlog_event.query == 'BEGIN':
                    e_start_pos = last_pos

                if isinstance(binlog_event, QueryEvent) and not self.only_dml:
                    sql = concat_sql_from_binlog_event(cursor=cursor, binlog_event=binlog_event,
                                                       flashback=False, no_pk=self.no_pk)
                    if sql:
                        print(sql)
                elif is_dml_event(binlog_event) and event_type(binlog_event) in self.sql_type:
                    for row in binlog_event.rows:
                        sql = concat_sql_from_binlog_event(cursor=cursor, binlog_event=binlog_event, no_pk=self.no_pk,
                                                           row=row, flashback=False, e_start_pos=e_start_pos)
                        print(sql)

                if not (isinstance(binlog_event, RotateEvent) or isinstance(binlog_event, FormatDescriptionEvent)):
                    last_pos = binlog_event.packet.log_pos
                if flag_last_event:
                    break

            stream.close()
            f_tmp.close()
        return True
Ejemplo n.º 22
0
    def _binlog_info(self):
        if self._is_binlog_data():
            resume_stream = True
            self.logger.info(
                "Resume from binlog_file: {file}  binlog_pos: {pos}".format(
                    file=self.log_file, pos=self.log_pos))
        else:
            resume_stream = False

        stream = BinLogStreamReader(
            connection_settings=self._mysql_config,
            server_id=config.mysql_server_id,
            only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
            only_tables=[config.table],
            resume_stream=resume_stream,
            blocking=True,
            log_file=self.binlog_file,
            log_pos=self.binlog_pos)
        for binlog_event in stream:
            self.binlog_file = stream.log_file
            self.binlog_pos = stream.log_pos
            for row in binlog_event.rows:
                # row is a list, every element is a map.
                result = {}
                if isinstance(binlog_event, DeleteRowsEvent):
                    result['delete'] = {"delete": self._load_delete_data(row)}
                elif isinstance(binlog_event, UpdateRowsEvent) or isinstance(
                        binlog_event, WriteRowsEvent):
                    result['update'] = self._load_index_update_data(row)
                else:
                    self.logger.error("not handle event type.")
                    raise TypeError('not handle event type.')
                yield result
        stream.close()
        raise IOError('mysql connection closed')
Ejemplo n.º 23
0
class Listener(object):
    def __init__(self, connection_settings, server_id, blocking=True, resume_stream=True):
        self._stream = BinLogStreamReader(
            connection_settings=connection_settings,
            server_id=server_id,
            only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
            blocking=blocking,
            resume_stream=resume_stream
        )

    def __del__(self):
        self._stream.close()

    def accept(self, callback):
        for log in self._stream:
            for row in log.rows:
                fields = {}
                method = ''
                if isinstance(log, DeleteRowsEvent):
                    fields = row["values"]
                    method = 'DELETE'
                elif isinstance(log, UpdateRowsEvent):
                    fields = row["after_values"]
                    method = 'UPDATE'
                elif isinstance(log, WriteRowsEvent):
                    method = 'INSERT'
                    fields = row["values"]

                logger.debug(
                    "捕获mysql %r事件, 值为: %r",
                    method, json.dumps(fields)
                )
                callback(log.schema, log.table, method, fields)
Ejemplo n.º 24
0
	def proc_binlog(self):
		stream = BinLogStreamReader(
			connection_settings = self.config['mysql'],
			server_id = self.config['slave']['server_id'],
			log_file = self.log_file,
			log_pos = self.log_pos,
			only_schemas = self.config['slave']['schemas'],
			blocking = True,
			resume_stream = bool(self.log_file and self.log_pos),
			only_events=[WriteRowsEvent, UpdateRowsEvent, DeleteRowsEvent]
		)
		for binlogevent in stream:
			#binlogevent.dump()
			self.log_file = stream.log_file
			self.log_pos  = stream.log_pos
			for row in binlogevent.rows:
				pk = binlogevent.primary_key
				table = binlogevent.table
				schema = binlogevent.schema
				if isinstance(binlogevent, WriteRowsEvent):
					yield self.es.index_op(self._format(row['values']), doc_type=table, index=schema, id=row['values'][pk])
				elif isinstance(binlogevent, UpdateRowsEvent):
					yield self.es.update_op(self._format(row['after_values']), doc_type=table, index=schema, id=row['after_values'][pk])
				elif isinstance(binlogevent, DeleteRowsEvent):
					yield self.es.delete_op(doc_type=table, index=schema, id=row['values'][pk])
				else:
					continue

		stream.close()
Ejemplo n.º 25
0
class Listener(object):
    def __init__(self,
                 connection_settings,
                 server_id,
                 blocking=True,
                 resume_stream=True):
        self._stream = BinLogStreamReader(
            connection_settings=connection_settings,
            server_id=server_id,
            only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
            blocking=blocking,
            resume_stream=resume_stream)

    def __del__(self):
        self._stream.close()

    def accept(self, callback):
        for log in self._stream:
            for row in log.rows:
                fields = {}
                method = ''
                if isinstance(log, DeleteRowsEvent):
                    fields = row["values"]
                    method = 'DELETE'
                elif isinstance(log, UpdateRowsEvent):
                    fields = row["after_values"]
                    method = 'UPDATE'
                elif isinstance(log, WriteRowsEvent):
                    method = 'INSERT'
                    fields = row["values"]

                logger.debug("捕获mysql %r事件, 值为: %r", method,
                             json.dumps(fields))
                callback(log.schema, log.table, method, fields)
Ejemplo n.º 26
0
def main():
    utils.drop_privileges()
    if BinLogStreamReader is None:
        utils.err("error: Python module `pymysqlreplication' is missing")
        return 1
    settings = zabbix_bridge_conf.get_settings()

    # Set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=settings['mysql'],
                                server_id=settings['slaveid'],
                                only_events=[WriteRowsEvent],
                                resume_stream=True,
                                blocking=True)

    db_filename = settings['sqlitedb']
    dbcache = sqlite3.connect(':memory:')
    cachecur = dbcache.cursor()
    cachecur.execute("ATTACH DATABASE '%s' as 'dbfile'" % (db_filename,))
    cachecur.execute('CREATE TABLE zabbix_cache AS SELECT * FROM dbfile.zabbix_cache')
    cachecur.execute('CREATE UNIQUE INDEX uniq_zid on zabbix_cache (id)')

    # tcollector.zabbix_bridge namespace for internal Zabbix bridge metrics.
    log_pos = 0
    key_lookup_miss = 0
    sample_last_ts = int(time.time())
    last_key_lookup_miss = 0

    for binlogevent in stream:
        if binlogevent.schema == settings['mysql']['db']:
            table = binlogevent.table
            log_pos = binlogevent.packet.log_pos
            if table == 'history' or table == 'history_uint':
                for row in binlogevent.rows:
                    r = row['values']
                    itemid = r['itemid']
                    cachecur.execute('SELECT id, key, host, proxy FROM zabbix_cache WHERE id=?', (itemid,))
                    row = cachecur.fetchone()
                    if (row is not None):
                        print("zbx.%s %d %s host=%s proxy=%s" % (row[1], r['clock'], r['value'], row[2], row[3]))
                        if ((int(time.time()) - sample_last_ts) > settings['internal_metric_interval']): # Sample internal metrics @ 10s intervals
                            sample_last_ts = int(time.time())
                            print("tcollector.zabbix_bridge.log_pos %d %s" % (sample_last_ts, log_pos))
                            print("tcollector.zabbix_bridge.key_lookup_miss %d %s" % (sample_last_ts, key_lookup_miss))
                            print("tcollector.zabbix_bridge.timestamp_drift %d %s" % (sample_last_ts, (sample_last_ts - r['clock'])))
                            if ((key_lookup_miss - last_key_lookup_miss) > settings['dbrefresh']):
                                print("tcollector.zabbix_bridge.key_lookup_miss_reload %d %s" % (sample_last_ts, (key_lookup_miss - last_key_lookup_miss)))
                                cachecur.execute('DROP TABLE zabbix_cache')
                                cachecur.execute('CREATE TABLE zabbix_cache AS SELECT * FROM dbfile.zabbix_cache')
                                cachecur.execute('CREATE UNIQUE INDEX uniq_zid on zabbix_cache (id)')
                                last_key_lookup_miss = key_lookup_miss
                    else:
                        # TODO: Consider https://wiki.python.org/moin/PythonDecoratorLibrary#Retry
                        utils.err("error: Key lookup miss for %s" % (itemid))
                        key_lookup_miss += 1
                sys.stdout.flush()

    dbcache.close()
    stream.close()
Ejemplo n.º 27
0
    def run_by_rows(self):
        try:
            stream = BinLogStreamReader(connection_settings=self.mysql_setting,
                                        server_id=101213112,
                                        only_events=[
                                            DeleteRowsEvent, WriteRowsEvent,
                                            UpdateRowsEvent, GtidEvent
                                        ],
                                        resume_stream=True,
                                        blocking=False,
                                        log_file=self.binlog_file,
                                        log_pos=self.start_pos,
                                        only_schemas=self.only_schemas,
                                        only_tables=self.only_tables)
            rows = []
            for binlogevent in stream:
                log_pos = stream.log_pos
                if log_pos >= self.end_pos:
                    print('binlog syncer exit...')
                    stream.close()
                    break
                else:
                    if binlogevent.event_type == GTID_LOG_EVENT:
                        # 此处获取每个事务的GTID
                        # 不做处理
                        gtid = binlogevent.gtid
                        rows.append(gtid)
                    else:
                        # 判断当前事务的GTID的影响行数是否等于传入的影响行数
                        # 由于pymysql执行无法获取到当前事务的GTID以及pymysqlreplication无法获取到binlog的thread_id
                        # 所以无法实现精确定位,只能通过该方式实现,可能存在多备份数据的情况
                        for row in binlogevent.rows:
                            binlog = {
                                'database': binlogevent.schema,
                                'table': binlogevent.table,
                                'primary_key': binlogevent.primary_key
                            }
                            if self.sql_type == 'DELETE':
                                if isinstance(binlogevent, DeleteRowsEvent):
                                    binlog['values'] = row["values"]
                                    binlog['type'] = 'DELETE'
                                    rows.append(binlog)
                            if self.sql_type == 'UPDATE':
                                if isinstance(binlogevent, UpdateRowsEvent):
                                    binlog["before"] = row["before_values"]
                                    binlog["after"] = row["after_values"]
                                    binlog['type'] = 'UPDATE'
                                    rows.append(binlog)
                            if self.sql_type == 'INSERT':
                                if isinstance(binlogevent, WriteRowsEvent):
                                    binlog['values'] = row["values"]
                                    binlog['type'] = 'INSERT'
                                    rows.append(binlog)
            stream.close()
            result = {'status': 'success', 'data': self._filter_gtid(rows)}
        except Exception as err:
            result = {'status': 'fail', 'msg': str(err)}

        return result
Ejemplo n.º 28
0
def mysql_stream(conf, mongo, queue_out):
    logger = logging.getLogger(__name__)

    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    mysql_settings = {
        "host": conf['host'],
        "port": conf.getint('port'),
        "user": conf['user'],
        "passwd": conf['password']
    }

    last_log = mongo.get_log_pos()
    if last_log['log_file'] == 'NA':
        log_file = None
        log_pos = None
        resume_stream = False
    else:
        log_file = last_log['log_file']
        log_pos = int(last_log['log_pos'])
        resume_stream = True

    stream = BinLogStreamReader(
        connection_settings=mysql_settings,
        server_id=conf.getint('slaveid'),
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
        blocking=True,
        resume_stream=resume_stream,
        log_file=log_file,
        log_pos=log_pos,
        only_schemas=conf['databases'].split(','))

    for binlogevent in stream:
        binlogevent.dump()
        schema = "%s" % binlogevent.schema
        table = "%s" % binlogevent.table

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                event_type = 'delete'
            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = dict()
                vals["before"] = row["before_values"]
                vals["after"] = row["after_values"]
                event_type = 'update'
            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                event_type = 'insert'

            seqnum = mongo.write_to_queue(event_type, vals, schema, table)
            mongo.write_log_pos(stream.log_file, stream.log_pos)
            queue_out.put({'seqnum': seqnum})
            logger.debug(row)
            logger.debug(stream.log_pos)
            logger.debug(stream.log_file)

    stream.close()
Ejemplo n.º 29
0
def mysql_stream(conf, mongo, queue_out):
    logger = logging.getLogger(__name__)

    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    mysql_settings = {
        "host": conf['host'],
        "port": conf.getint('port'),
        "user": conf['user'],
        "passwd": conf['password']
    }

    last_log = mongo.get_log_pos()
    if last_log['log_file'] == 'NA':
        log_file = None
        log_pos = None
        resume_stream = False
    else:
        log_file = last_log['log_file']
        log_pos = int(last_log['log_pos'])
        resume_stream = True

    stream = BinLogStreamReader(connection_settings=mysql_settings,
                                server_id=conf.getint('slaveid'),
                                only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
                                blocking=True,
                                resume_stream=resume_stream,
                                log_file=log_file,
                                log_pos=log_pos,
                                only_schemas=conf['databases'].split(','))

    for binlogevent in stream:
        binlogevent.dump()
        schema = "%s" % binlogevent.schema
        table = "%s" % binlogevent.table

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                event_type = 'delete'
            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = dict()
                vals["before"] = row["before_values"]
                vals["after"] = row["after_values"]
                event_type = 'update'
            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                event_type = 'insert'

            seqnum = mongo.write_to_queue(event_type, vals, schema, table)
            mongo.write_log_pos(stream.log_file, stream.log_pos)
            queue_out.put({'seqnum': seqnum})
            logger.debug(row)
            logger.debug(stream.log_pos)
            logger.debug(stream.log_file)

    stream.close()
def main():
  global repLogFile
  global repLogPosition
  global repLogConfig

  graphiteConfig = readGraphiteConfig()

  try:
    print "Start"
    sock = socket.socket()
    sock.connect((CARBON_SERVER, CARBON_PORT))
    print 'Carbon socket opened.'
    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=2, #server id needs to be unique
        only_events=[WriteRowsEvent,DeleteRowsEvent,UpdateRowsEvent],
        blocking=True,
        log_file=repLogFile,
        log_pos=repLogPosition,
        resume_stream=False if repLogPosition==None else True)
    print "Binlog stream opened"

    for binlogevent in stream:
      #put replication log file and position in variables so we can save them later
      repLogFile = stream.log_file
      repLogPosition = stream.log_pos
      #also check for changes in graphite configuration and read again if needed
      if binlogevent.schema == "weather" and binlogevent.table == "graphite":
        graphiteConfig = readGraphiteConfig()
      #this is the data we are interested in
      if binlogevent.schema == "weather" and binlogevent.table == "data":

        for row in binlogevent.rows:
          #we only care about inserts
          if isinstance(binlogevent, WriteRowsEvent):
            vals = row["values"]
            #check if the sensor is one that we have configuration for
            if vals["sensorid"] in graphiteConfig:
              conf = graphiteConfig[vals["sensorid"]]
              value = float(vals["value"])
              #do a conversion if needed
              if conf["formula"]!=None and conf["formula"]!="":
                value=eval(conf["formula"], {"__builtins__": {}}, {"value":value,"round":round})
              #construc the message and send it to carbon
              message = '%s %f %d\n' % (conf["graphitepath"], value, round((vals["time"] - _EPOCH).total_seconds()))
              sock.sendall(message)
              print str(vals["sensorid"]), str(vals["time"]), str(value)
              print message

  except KeyboardInterrupt:
    #close open connections
    stream.close()
    sock.close()
    #save replication log position
    repLogConfig.set('replicationlog','file',repLogFile)
    repLogConfig.set('replicationlog','position',str(repLogPosition))
    with open('replogposition.ini', 'w') as f:
      repLogConfig.write(f)
Ejemplo n.º 31
0
def main():
    utils.drop_privileges()
    if BinLogStreamReader is None:
        utils.err("error: Python module `pymysqlreplication' is missing")
        return 1
    settings = zabbix_bridge_conf.get_settings()

    # Set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=settings['mysql'],
                                server_id=settings['slaveid'],
                                only_events=[WriteRowsEvent],
                                resume_stream=True,
                                blocking=True)

    db_filename = settings['sqlitedb']
    dbcache = sqlite3.connect(':memory:')
    cachecur = dbcache.cursor()
    cachecur.execute("ATTACH DATABASE '%s' as 'dbfile'" % (db_filename,))
    cachecur.execute('CREATE TABLE zabbix_cache AS SELECT * FROM dbfile.zabbix_cache')
    cachecur.execute('CREATE UNIQUE INDEX uniq_zid on zabbix_cache (id)')

    # tcollector.zabbix_bridge namespace for internal Zabbix bridge metrics.
    log_pos = 0
    key_lookup_miss = 0
    sample_last_ts = int(time.time())
    last_key_lookup_miss = 0

    for binlogevent in stream:
        if binlogevent.schema == settings['mysql']['db']:
            table = binlogevent.table
            log_pos = binlogevent.packet.log_pos
            if table == 'history' or table == 'history_uint':
                for row in binlogevent.rows:
                    r = row['values']
                    itemid = r['itemid']
                    cachecur.execute('SELECT id, key, host, proxy FROM zabbix_cache WHERE id=?', (itemid,))
                    row = cachecur.fetchone()
                    if (row is not None):
                        print "zbx.%s %d %s host=%s proxy=%s" % (row[1], r['clock'], r['value'], row[2], row[3])
                        if ((int(time.time()) - sample_last_ts) > settings['internal_metric_interval']): # Sample internal metrics @ 10s intervals
                            sample_last_ts = int(time.time())
                            print "tcollector.zabbix_bridge.log_pos %d %s" % (sample_last_ts, log_pos)
                            print "tcollector.zabbix_bridge.key_lookup_miss %d %s" % (sample_last_ts, key_lookup_miss)
                            print "tcollector.zabbix_bridge.timestamp_drift %d %s" % (sample_last_ts, (sample_last_ts - r['clock']))
                            if ((key_lookup_miss - last_key_lookup_miss) > settings['dbrefresh']):
                                print "tcollector.zabbix_bridge.key_lookup_miss_reload %d %s" % (sample_last_ts, (key_lookup_miss - last_key_lookup_miss))
                                cachecur.execute('DROP TABLE zabbix_cache')
                                cachecur.execute('CREATE TABLE zabbix_cache AS SELECT * FROM dbfile.zabbix_cache')
                                last_key_lookup_miss = key_lookup_miss
                    else:
                        # TODO: Consider https://wiki.python.org/moin/PythonDecoratorLibrary#Retry
                        utils.err("error: Key lookup miss for %s" % (itemid))
                        key_lookup_miss += 1
                sys.stdout.flush()

    dbcache.close()
    stream.close()
Ejemplo n.º 32
0
    def _binlog_loader(self):
        """
        read row from binlog
        """
        if self.is_binlog_sync:
            resume_stream = True
            logging.info(
                "Resume from binlog_file: {file}  binlog_pos: {pos}".format(
                    file=self.log_file, pos=self.log_pos))
        else:
            resume_stream = False

        stream = BinLogStreamReader(
            connection_settings=self.binlog_conf,
            server_id=self.config['mysql']['server_id'],
            only_events=[
                DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent, RotateEvent
            ],
            only_tables=self.tables,
            resume_stream=resume_stream,
            blocking=True,
            log_file=self.log_file,
            log_pos=self.log_pos)
        for binlogevent in stream:
            self.log_file = stream.log_file
            self.log_pos = stream.log_pos

            # RotateEvent to update binlog record when no related table changed
            if isinstance(binlogevent, RotateEvent):
                self._save_binlog_record()
                continue
            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    if binlogevent.table == self.master:
                        rv = {'action': 'delete', 'doc': row['values']}
                    else:
                        rv = {
                            'action': 'update',
                            'doc': {
                                k: row['values'][k]
                                if self.id_key and self.id_key == k else None
                                for k in row['values']
                            }
                        }
                elif isinstance(binlogevent, UpdateRowsEvent):
                    rv = {'action': 'update', 'doc': row['after_values']}
                elif isinstance(binlogevent, WriteRowsEvent):
                    if binlogevent.table == self.master:
                        rv = {'action': 'create', 'doc': row['values']}
                    else:
                        rv = {'action': 'update', 'doc': row['values']}
                else:
                    logging.error('unknown action type in binlog')
                    raise TypeError('unknown action type in binlog')
                yield rv
                # print(rv)
        stream.close()
        raise IOError('mysql connection closed')
Ejemplo n.º 33
0
class DB_fetcher(multiprocessing.Process):
    def __init__(self, share_image_queue, MYSQL_SETTINGS ,target_schema = "capstone",
                 target_table = "crack_detection_result",
                 start_time = datetime.datetime(1970,1,2,0,1,0)): # 1970,1,1 is almost 0 second
        multiprocessing.Process.__init__(self)
        self.share_image_queue = share_image_queue
        self.target_schema = target_schema
        self.target_table = target_table
        self.skip_to_timestamp = convert_to_second_int(start_time)
        print(" >>>>> start time is {}".format(self.skip_to_timestamp))

    def run(self):
        while True:
            self.stream = BinLogStreamReader(
                connection_settings=MYSQL_SETTINGS,
                only_events=[WriteRowsEvent],  # [DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
                server_id=3,
                slave_heartbeat=1
                ,skip_to_timestamp = self.skip_to_timestamp)

            # self.idx = 0
            # self.show_slave_status()
            for binlogevent in self.stream:
                prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)
                if prefix == self.target_schema + ":" + self.target_table + ":":
                    # print(binlogevent.rows)
                    for new_update_row in binlogevent.rows:
                        logging.info(" >>> find new row {} time: {}".format(new_update_row, binlogevent.timestamp))
                        # format for a row: {'values':
                        #       {'video_id': 1, 'frame_id': 4, 'insert_time': datetime.datetime(2008, 6, 19, 0, 0),
                        #       'frame_loc': 'RANDOM_LL', 'detect_flag': boolean, 'result_loc': None}}

                        # if new_update_row["values"]["detect_flag"] == 0 and  \
                        #         (new_update_row["values"]['insert_time'] is not None or new_update_row["values"]['insert_time'] != '' )\
                        #         and  ((new_update_row["values"]['frame_id'] > 170 and new_update_row["values"]['frame_id' ] < 200)
                        #               or (new_update_row["values"]['frame_id'] > 1010 and new_update_row["values"]['frame_id' ] < 1035)
                        #               or (new_update_row["values"]['frame_id'] > 1155 and new_update_row["values"]['frame_id' ] < 1177)
                        #               or (new_update_row["values"]['frame_id'] > 1312 and new_update_row["values"]['frame_id' ] < 1316)
                        #               or (new_update_row["values"]['frame_id'] > 2127 and new_update_row["values"]['frame_id' ] < 2150)):

                        if new_update_row["values"]["detect_flag"] == 0 and  \
                                (new_update_row["values"]['insert_time'] is not None or new_update_row["values"]['insert_time'] != ''
                                 ):
                            #logging.info(" >>> for this row, the flag is {}".format(new_update_row['detect_flag']))
                            try:
                                self.share_image_queue.put(new_update_row["values"],True,1)
                                logging.info(" >>> adding 1 image to queue {}".format(new_update_row))
                            except Exception as e:
                                logging.error(e)
                            self.skip_to_timestamp = convert_to_second_int(datetime.datetime.now())

            time.sleep(2)

    def close_stream(self):
        self.stream.close()
Ejemplo n.º 34
0
def binlog_process(args):
    file = None
    stream = None
    sql_list = []
    try:
        file = open(args.out_file, "w+")
        stream = BinLogStreamReader(connection_settings=connection_settings,
                                    log_file=args.log_file,
                                    log_pos=args.start_pos,
                                    resume_stream=True,
                                    only_schemas=args.databases,
                                    only_tables=args.tables,
                                    server_id=args.server_id)

        for binlogevent in stream:
            if (args.log_file != stream.log_file):
                break

            if (args.end_pos != None):
                if (binlogevent.packet.log_pos > args.end_pos):
                    break

            if (args.start_datetime != None):
                if (datetime.datetime.fromtimestamp(binlogevent.timestamp) <
                        args.start_datetime):
                    continue

            if (args.end_datetime != None):
                if (datetime.datetime.fromtimestamp(binlogevent.timestamp) >
                        args.end_datetime):
                    break

            if (isinstance(binlogevent, WriteRowsEvent)):
                for row in binlogevent.rows:
                    if (args.flashback):
                        sql_list.append(delete_to_sql(row, binlogevent) + "\n")
                    else:
                        sql_list.append(insert_to_sql(row, binlogevent) + "\n")
            elif (isinstance(binlogevent, DeleteRowsEvent)):
                for row in binlogevent.rows:
                    if (args.flashback):
                        sql_list.append(insert_to_sql(row, binlogevent) + "\n")
                    else:
                        sql_list.append(delete_to_sql(row, binlogevent) + "\n")
            elif (isinstance(binlogevent, UpdateRowsEvent)):
                for row in binlogevent.rows:
                    sql_list.append(
                        update_to_sql(row, binlogevent, args.flashback) + "\n")
        file.writelines(sql_list)
    finally:
        if (stream != None):
            stream.close()
        if (file != None):
            file.close()
def main():
    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                server_id=3,
                                blocking=True)

    for binlogevent in stream:
        binlogevent.dump()

    stream.close()
Ejemplo n.º 36
0
def main():
    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                server_id=3,
                                blocking=True)

    for binlogevent in stream:
        binlogevent.dump()

    stream.close()
Ejemplo n.º 37
0
    def process_binlog(self):
        stream = BinLogStreamReader(connection_settings=self.connectionSettings, server_id=self.serverId,
                                    log_file=self.startFile, log_pos=self.startPos, only_schemas=self.only_schemas,
                                    only_tables=self.only_tables, resume_stream=True)

        cur = self.connection.cursor()
        tmpFile = create_unique_file('%s.%s' % (self.connectionSettings['host'],self.connectionSettings['port'])) # to simplify code, we do not use file lock for tmpFile.
        ftmp = open(tmpFile ,"w")
        flagLastEvent = False
        eStartPos, lastPos = stream.log_pos, stream.log_pos
        try:
            for binlogevent in stream:
                if not self.stopnever:
                    if (stream.log_file == self.endFile and stream.log_pos == self.endPos) or (stream.log_file == self.eofFile and stream.log_pos == self.eofPos):
                        flagLastEvent = True
                    elif datetime.datetime.fromtimestamp(binlogevent.timestamp) < self.startTime:
                        if not (isinstance(binlogevent, RotateEvent) or isinstance(binlogevent, FormatDescriptionEvent)):
                            lastPos = binlogevent.packet.log_pos
                        continue
                    elif (stream.log_file not in self.binlogList) or (self.endPos and stream.log_file == self.endFile and stream.log_pos > self.endPos) or (stream.log_file == self.eofFile and stream.log_pos > self.eofPos) or (datetime.datetime.fromtimestamp(binlogevent.timestamp) >= self.stopTime):
                        break
                    # else:
                    #     raise ValueError('unknown binlog file or position')

                if isinstance(binlogevent, QueryEvent) and binlogevent.query == 'BEGIN':
                    eStartPos = lastPos

                if isinstance(binlogevent, QueryEvent):
                    sql = concat_sql_from_binlogevent(cursor=cur, binlogevent=binlogevent, flashback=self.flashback, nopk=self.nopk)
                    if sql:
                        print sql
                elif isinstance(binlogevent, WriteRowsEvent) or isinstance(binlogevent, UpdateRowsEvent) or isinstance(binlogevent, DeleteRowsEvent):
                    for row in binlogevent.rows:
                        sql = concat_sql_from_binlogevent(cursor=cur, binlogevent=binlogevent, row=row , flashback=self.flashback, nopk=self.nopk, eStartPos=eStartPos)
                        if self.flashback:
                            ftmp.write(sql + '\n')
                        else:
                            print sql

                if not (isinstance(binlogevent, RotateEvent) or isinstance(binlogevent, FormatDescriptionEvent)):
                    lastPos = binlogevent.packet.log_pos
                if flagLastEvent:
                    break
            ftmp.close()
            if self.flashback:
                with open(tmpFile) as ftmp:
                    for line in reversed_lines(ftmp):
                        print line.rstrip()
        finally:
            os.remove(tmpFile)
        cur.close()
        stream.close()
        return True
def doRep(logPosConObj, MYSQL_SETTINGS):
    key = MYSQL_SETTINGS["host"] + ":" + str(MYSQL_SETTINGS["port"])
    try:
        stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                    server_id=100,
                                    only_events=[
                                        DeleteRowsEvent, WriteRowsEvent,
                                        UpdateRowsEvent, RotateEvent,
                                        QueryEvent
                                    ],
                                    blocking=True,
                                    log_file=logPosConObj["log_file"],
                                    log_pos=logPosConObj["log_pos"])
        for binlogevent in stream:
            #prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)

            if isinstance(binlogevent, RotateEvent):
                #pprint (vars(binlogevent.packet))
                logPosConObj["log_file"] = binlogevent.packet.event.next_binlog
                logPosConObj["log_pos"] = binlogevent.packet.log_pos
                #logPosObject.setData(logPosConObj)
                continue
            if isinstance(binlogevent, QueryEvent):
                #pprint (vars(binlogevent.packet))
                sendMsg(key, binlogevent.query, binlogevent.timestamp)
                #logPosObject.setData(logPosConObj)
                continue
            for row in binlogevent.rows:
                #dbtable = binlogevent.schema+"_"+binlogevent.table
                if isinstance(binlogevent, DeleteRowsEvent):
                    #print 'DeleteRowsEvent'
                    sendMsg(key, row.get("values", object),
                            binlogevent.timestamp)
                    #func(row.get("values",object))
                elif isinstance(binlogevent, UpdateRowsEvent):
                    #print 'UpdateRowsEvent'
                    #print row
                    sendMsg(key, row, binlogevent.timestamp)
                    #func(row.get("after_values",object))
                elif isinstance(binlogevent, WriteRowsEvent):
                    #print 'WriteRowsEvent'
                    #print row
                    sendMsg(key, row.get("values", object),
                            binlogevent.timestamp)
                    #func(row.get("values",object))
                #logPosConObj["log_pos"]=binlogevent.packet.log_pos
                #logPosObject.setData(logPosConObj)

        stream.close()
    except BaseException, e:
        print(e)
        return
Ejemplo n.º 39
0
def main():
    configuration = {'log_file': 'mysql-bin-changelog.004416', 'log_pos': 0}

    for config in open('configuration').read().split('\n'):
        config_k_v = config.split('=')
        configuration[config_k_v[0]] = config_k_v[1]

    MYSQL_SETTINGS = {
        "host": configuration['hostname'],
        "port": 3306,
        "user": configuration['username'],
        "password": configuration['password'],
        "database": configuration['database']
    }

    print configuration

    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        server_id=1234,
        log_file=configuration['log_file'],
        log_pos=configuration['log_pos'],
        blocking=True,
        only_events=[WriteRowsEvent, UpdateRowsEvent, DeleteRowsEvent])

    s3 = boto3.resource('s3')
    buffer_events = []
    buffer_max_size = 1

    cur_log_file = ''
    cur_log_pos = ''

    for binlog_event in stream:
        cur_log_file = stream.log_file
        cur_log_pos = stream.log_pos

        print "Processing " + cur_log_file + " at " + str(cur_log_pos)

        buffer_events.append(binlog_event)
        if len(buffer_events) == buffer_max_size:
            upload_to_s3(
                s3, s3_file_name(cur_log_file, cur_log_pos),
                map(lambda binlog_event: binlog_event_to_json(binlog_event),
                    buffer_events))
            buffer_events = []

    stream.close()
    if len(buffer) > 0:
        upload_to_s3(
            s3, s3_file_name(cur_log_file, cur_log_pos),
            map(lambda binlog_event: binlog_event_to_json(binlog_event, table),
                buffer_events))
def main():
    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                server_id=3,
                                log_file="mysql-bin.000002",
                                blocking=True,
                                only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    for binlogevent in stream:
        binlogevent.dump()

    stream.close()
Ejemplo n.º 41
0
def consume_events():
    stream = BinLogStreamReader(connection_settings=database,
                                server_id=3,
                                resume_stream=False,
                                blocking=True,
                                only_events = [UpdateRowsEvent],
                                only_tables = ['test'] )
    start = time.clock()
    i = 0.0
    for binlogevent in stream:
            i += 1.0
            if i % 1000 == 0:
                print("%d event by seconds (%d total)" % (i / (time.clock() - start), i))
    stream.close()
Ejemplo n.º 42
0
def binlog_process(args):
    file = None
    stream = None
    sql_list = []
    try:
        file = open(args.out_file, "w+")
        stream = BinLogStreamReader(connection_settings=connection_settings, log_file=args.log_file, log_pos=args.start_pos,
                                    resume_stream=True, only_schemas=args.databases, only_tables=args.tables, server_id=args.server_id)

        for binlogevent in stream:
            if(args.log_file != stream.log_file):
                break

            if(args.end_pos != None):
                if(binlogevent.packet.log_pos > args.end_pos):
                    break

            if(args.start_datetime != None):
                if(datetime.datetime.fromtimestamp(binlogevent.timestamp) < args.start_datetime):
                    continue

            if(args.end_datetime != None):
                if(datetime.datetime.fromtimestamp(binlogevent.timestamp) > args.end_datetime):
                    break

            if (isinstance(binlogevent, WriteRowsEvent)):
                for row in binlogevent.rows:
                    if(args.flashback):
                        sql_list.append(delete_to_sql(row, binlogevent) + "\n")
                    else:
                        sql_list.append(insert_to_sql(row, binlogevent) + "\n")
            elif (isinstance(binlogevent, DeleteRowsEvent)):
                for row in binlogevent.rows:
                    if(args.flashback):
                        sql_list.append(insert_to_sql(row, binlogevent) + "\n")
                    else:
                        sql_list.append(delete_to_sql(row, binlogevent) + "\n")
            elif (isinstance(binlogevent, UpdateRowsEvent)):
                for row in binlogevent.rows:
                    sql_list.append(update_to_sql(row, binlogevent, args.flashback) + "\n")
        file.writelines(sql_list)
    finally:
        if(stream != None):
            stream.close()
        if(file != None):
            file.close()
    def _binlog_loader(self):
        """
        read row from binlog
        """
        if self.is_binlog_sync:
            resume_stream = True
            logging.info("Resume from binlog_file: {file}  binlog_pos: {pos}".format(file=self.log_file,
                                                                                     pos=self.log_pos))
        else:
            resume_stream = False

        stream = BinLogStreamReader(connection_settings=self.binlog_conf,
                                    server_id=self.config['mysql']['server_id'],
                                    only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent],
                                    only_tables=[self.config['mysql']['table']],
                                    resume_stream=resume_stream,
                                    blocking=True,
                                    log_file=self.log_file,
                                    log_pos=self.log_pos)
        for binlogevent in stream:
            self.log_file = stream.log_file
            self.log_pos = stream.log_pos
            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    rv = {
                        'action': 'delete',
                        'doc': row['values']
                    }
                elif isinstance(binlogevent, UpdateRowsEvent):
                    rv = {
                        'action': 'update',
                        'doc': row['after_values']
                    }
                elif isinstance(binlogevent, WriteRowsEvent):
                    rv = {
                        'action': 'index',
                        'doc': row['values']
                    }
                else:
                    logging.error('unknown action type in binlog')
                    raise TypeError('unknown action type in binlog')
                yield rv
                # print(rv)
        stream.close()
        raise IOError('mysql connection closed')
def doRep(logPosConObj,MYSQL_SETTINGS):
	key = MYSQL_SETTINGS["host"]+":"+str(MYSQL_SETTINGS["port"])
	try:
		stream = BinLogStreamReader(
			connection_settings=MYSQL_SETTINGS,server_id=100,
			only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent, RotateEvent,QueryEvent],blocking=True,
			log_file=logPosConObj["log_file"],log_pos=logPosConObj["log_pos"])
		for binlogevent in stream:
			#prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)
		
			if isinstance(binlogevent, RotateEvent):
				#pprint (vars(binlogevent.packet))
				logPosConObj["log_file"]=binlogevent.packet.event.next_binlog
				logPosConObj["log_pos"]=binlogevent.packet.log_pos
				#logPosObject.setData(logPosConObj)
				continue
			if isinstance(binlogevent, QueryEvent):
				#pprint (vars(binlogevent.packet))
				sendMsg(key,binlogevent.query,binlogevent.timestamp)
				#logPosObject.setData(logPosConObj)
				continue
			for row in binlogevent.rows:
				#dbtable = binlogevent.schema+"_"+binlogevent.table
				if isinstance(binlogevent, DeleteRowsEvent):
					#print 'DeleteRowsEvent'
					sendMsg(key,row.get("values",object),binlogevent.timestamp)
					#func(row.get("values",object))
				elif isinstance(binlogevent, UpdateRowsEvent):
					#print 'UpdateRowsEvent'
					#print row
					sendMsg(key,row,binlogevent.timestamp)
					#func(row.get("after_values",object))
				elif isinstance(binlogevent, WriteRowsEvent):
					#print 'WriteRowsEvent'
					#print row
					sendMsg(key,row.get("values",object),binlogevent.timestamp)
					#func(row.get("values",object))
				#logPosConObj["log_pos"]=binlogevent.packet.log_pos
				#logPosObject.setData(logPosConObj)
		
		stream.close()
	except BaseException,e :
		print(e)
		return
Ejemplo n.º 45
0
def main():
    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                server_id=3,
                                blocking=True)

    for binlogevent in stream:
        #print binlogevent
        #if isinstance(binlogevent, QueryEvent):
        #    print binlogevent.query
        if isinstance(binlogevent, WriteRowsEvent):
            for rows in binlogevent.rows:
                print rows
                #print binlogevent.query
        #binlogevent.dump()

    stream.close()
Ejemplo n.º 46
0
def main():
    print 'Replicator Started'
    io = Emitter(dict(
        host=settings.SOCKETIO_SETTINGS['host'],
        port=settings.SOCKETIO_SETTINGS['port']
        )).Of(settings.SOCKETIO_SETTINGS['namespace'])
    stream = BinLogStreamReader(connection_settings=settings.MYSQL_SETTINGS,
                                server_id=3,
                                blocking=True,
                                resume_stream=True,
                                only_events=[UpdateRowsEvent],
                                only_tables=[settings.DB_SETTINGS['source_table']])

    for binlogevent in stream:
         for row in binlogevent.rows:
             vals = row["after_values"]
             print 'Updated rows for ' + json.dumps(vals)
             io.Emit('update', json.dumps(vals))

    stream.close()
Ejemplo n.º 47
0
def main():
    ## 几个初始化工作
    parse_conf()
    set_mysql_setting()
    parse_binlog_conf()

    stream = BinLogStreamReader(
        connection_settings= MYSQL_SETTINGS,
        server_id          = serverid,
        resume_stream      = True,
        log_file           = binlog_info["binlog"],
        log_pos            = int(binlog_info["position"]),
        only_events        = [DeleteRowsEvent, 
                              WriteRowsEvent, 
                              UpdateRowsEvent,
                              RotateEvent,
                              XidEvent],
        blocking           = True)

    currentbinlogfilename = ""
    currentbinlogposition = ""
    for binlogevent in stream:
        if isinstance(binlogevent, RotateEvent):
            currentbinlogfilename = binlogevent.next_binlog
            currentbinlogposition = binlogevent.position
            print currentbinlogfilename, currentbinlogposition
            #sync_binlog_to_file(currentbinlogfilename,currentbinlogposition)
        elif isinstance(binlogevent, XidEvent):
            currentbinlogposition = binlogevent.packet.log_pos
            print currentbinlogfilename, currentbinlogposition
            #sync_binlog_to_file(currentbinlogfilename,currentbinlogposition)
        elif (binlogevent.schema == sourcedb_conf["db_dbname"] and 
                binlogevent.table == sourcedb_conf["db_table"]):
            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    syncDelete(row)
                elif isinstance(binlogevent, UpdateRowsEvent):
                    syncUpdate(row)
                elif isinstance(binlogevent, WriteRowsEvent):
                    syncInsert(row)
    stream.close()
Ejemplo n.º 48
0
def main():
    utils.drop_privileges()
    if BinLogStreamReader is None:
        utils.err("error: Python module `pymysqlreplication' is missing")
        return 1
    if pymysql is None:
        utils.err("error: Python module `pymysql' is missing")
        return 1
    settings = zabbix_bridge_conf.get_settings()

    # Set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    stream = BinLogStreamReader(connection_settings=settings['mysql'],
                                server_id=settings['slaveid'],
                                only_events=[WriteRowsEvent],
                                resume_stream=True,
                                blocking=True)

    hostmap = gethostmap(settings) # Prime initial hostmap
    for binlogevent in stream:
        if binlogevent.schema == settings['mysql']['db']:
            table = binlogevent.table
            log_pos = binlogevent.packet.log_pos
            if table == 'history' or table == 'history_uint':
                for row in binlogevent.rows:
                    r = row['values']
                    itemid = r['itemid']
                    try:
                        hm = hostmap[itemid]
                        print "zbx.%s %d %s host=%s proxy=%s" % (hm['key'], r['clock'], r['value'], hm['host'], hm['proxy'])
                    except KeyError:
                        # TODO: Consider https://wiki.python.org/moin/PythonDecoratorLibrary#Retry
                        hostmap = gethostmap(settings)
                        utils.err("error: Key lookup miss for %s" % (itemid))
                sys.stdout.flush()
                # if n seconds old, reload
                # settings['gethostmap_interval']

    stream.close()
Ejemplo n.º 49
0
def main():
    r = redis.Redis()

    stream = BinLogStreamReader(
        connection_settings=MYSQL_SETTINGS,
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

    for binlogevent in stream:
        prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                r.delete(prefix + str(vals["id"]))
            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = row["after_values"]
                r.hmset(prefix + str(vals["id"]), vals)
            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                r.hmset(prefix + str(vals["id"]), vals)

    stream.close()
class TestGtidBinLogStreamReader(base.PyMySQLReplicationTestCase):
    def test_read_query_event(self):
        query = "CREATE TABLE test (id INT NOT NULL, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "SELECT @@global.gtid_executed;"
        gtid = self.execute(query).fetchone()[0]

        self.stream.close()
        self.stream = BinLogStreamReader(self.database, server_id=1024, blocking=True, auto_position=gtid)

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        # Insert first event
        query = "BEGIN;"
        self.execute(query)
        query = "INSERT INTO test (id, data) VALUES(1, 'Hello');"
        self.execute(query)
        query = "COMMIT;"
        self.execute(query)

        firstevent = self.stream.fetchone()
        self.assertIsInstance(firstevent, GtidEvent)

        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), WriteRowsEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)

        # Insert second event
        query = "BEGIN;"
        self.execute(query)
        query = "INSERT INTO test (id, data) VALUES(2, 'Hello');"
        self.execute(query)
        query = "COMMIT;"
        self.execute(query)

        secondevent = self.stream.fetchone()
        self.assertIsInstance(secondevent, GtidEvent)

        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), WriteRowsEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)

        self.assertEqual(secondevent.gno, firstevent.gno + 1)

    def test_position_gtid(self):
        query = "CREATE TABLE test (id INT NOT NULL, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "BEGIN;"
        self.execute(query)
        query = "INSERT INTO test (id, data) VALUES(1, 'Hello');"
        self.execute(query)
        query = "COMMIT;"
        self.execute(query)

        query = "CREATE TABLE test2 (id INT NOT NULL, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "SELECT @@global.gtid_executed;"
        gtid = self.execute(query).fetchone()[0]

        self.stream.close()
        self.stream = BinLogStreamReader(self.database, server_id=1024, blocking=True, auto_position=gtid)

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        self.assertIsInstance(self.stream.fetchone(), GtidEvent)
        event = self.stream.fetchone()

        self.assertEqual(
            event.query, "CREATE TABLE test2 (id INT NOT NULL, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        )
Ejemplo n.º 51
0
class MysqlEventStream(object):
    def __init__(self, mysql_settings, server_id, dump_file_path,
                 log_file=None, log_pos=None,
                 gtid_set=None, table_filters=None):
        # TODO: gtid mode support
        # https://dev.mysql.com/doc/refman/en/replication-gtids.html
        # TODO: wild chars in table_filters
        self.mysql_settings = mysql_settings
        self.server_id = server_id
        self.log_file = log_file
        self.log_pos = log_pos
        self.dump_file_path = dump_file_path

        if table_filters:
            self.table_filters = {schema:frozenset(tables) for schema, tables in table_filters.items()}
            only_schemas = [schema for schema in table_filters]
        else:
            self.table_filters = None
            only_schemas = None

        self.binlog_stream_reader = BinLogStreamReader(
            connection_settings=self.mysql_settings,
            server_id=self.server_id,
            log_file=self.log_file,
            log_pos=self.log_pos,
            resume_stream=True,
            blocking=False,
            freeze_schema=True,
            only_schemas=only_schemas,
        )

    def __iter__(self):
        for ev in self.binlog_stream_reader:
            yield (
                self.binlog_stream_reader.log_file,
                self.binlog_stream_reader.log_pos,
                ev,
            )

    def process_commit(self, new_log_file, new_log_pos):
        self.log_file = new_log_file
        self.log_pos = new_log_pos

    def close(self):
        """close connection to MySQL
        """
        self.binlog_stream_reader.close()

    def dumpf(self):
        """dump currently read binlog file and offset to a file
        """
        data = {
            'server_id': self.server_id,
            'log_file':self.log_file,
            'log_pos':self.log_pos,
        }
        data_str = six.u(json.dumps(data))
        with io.open(self.dump_file_path, 'w', encoding='utf-8') as f:
            f.write(data_str)

    @classmethod
    def loadf(cls, path, mysql_settings, table_filters=None):
        """construct from dump file
        """
        with io.open(path, 'r', encoding='utf-8') as f:
            data_str = f.read()

        data = json.loads(data_str)

        ev_stream = cls(
            mysql_settings=mysql_settings,
            server_id=data['server_id'],
            log_file=data['log_file'],
            log_pos=data['log_pos'],
            dump_file_path=path,
            table_filters=table_filters,
        )

        return ev_stream
Ejemplo n.º 52
0
        #print("Update+++++++++++++++++")
        #print(binlogevent.schema, binlogevent.table)
        for row in binlogevent.rows:
            #print(row)
            str123 = "update `{0}`.`{1}` set {2} where {3};".format(binlogevent.schema, binlogevent.table, sql_format(row['after_values'], ", "), sql_format(row['before_values'], " AND "))
            #list.append(str(str123))
            sql_list.append(str123+"\n")

    elif (isinstance(binlogevent, DeleteRowsEvent)):
        #delete from db1.t1 where c1 = 'bbb';
        #print("Delete>>>>>>>>>>>>>>>>>>>>")
        #print(binlogevent.schema, binlogevent.table)
        for row in binlogevent.rows:
            #print(row)
            str123 = "delete from `{0}`.`{1}` where {2};".format(binlogevent.schema, binlogevent.table, sql_format(row['values'], " AND "))
            #list.append(str(str123))
            sql_list.append(str123+"\n")

'''

stream.close()

bb = time.time()
print("binlog ok", bb - aa)

#my_file.writelines(sql_list)
#my_file.close()
bb = time.time()

print(bb - aa)
def main():
    r = redis.Redis(host = config.REDIS_SETTINGS["host"],port = config.REDIS_SETTINGS["port"])

    stream = BinLogStreamReader(
        connection_settings=config.MYSQL_SETTINGS,
        server_id=4,
        blocking=True,
	#log_file="mysql-bin.000028",
	#log_pos=706478611,
	resume_stream=True,
	only_tables=["ax_newdata"],
        only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])
   
    now = int(math.floor(time.time()))

    for binlogevent in stream:
        prefix = "%s:%s:" % (binlogevent.schema, binlogevent.table)
        statPrefix = "%s:%s:" % (binlogevent.schema,"statistics")

        for row in binlogevent.rows:
			#print str(binlogevent.table)
			if binlogevent.table.find(config.DB_SETTINGS["newdata"]) == -1:
				#print "newdata"
				continue
			elif isinstance(binlogevent, UpdateRowsEvent) and (row["after_values"]["ctime"] < now):
				#if row["after_values"]["symbol"].find("EURGBP") != -1:
				#	print "olddata",row["after_values"]["volume"],row["after_values"]["high"],row["after_values"]["symbol"],now,row["after_values"]["ctime"]
				continue#filter old data
			elif isinstance(binlogevent, UpdateRowsEvent) and (binlogevent.table.find(config.DB_SETTINGS["newdata"]) != -1):
				vals = row["after_values"]	
				#print vals	
				r.set("lastDbUpdateTime",int(math.floor(time.time())))
				result = {}
				result["price"]=vals["bid"]
				result["timestamp"]=vals["ctime"]
				for k,v in vals.items():
					if isinstance(v,basestring):
						result[k.encode("utf-8")] = v.encode("utf-8")
					else:
						result[k.encode("utf-8")] = v 
				r.set("R_" + vals["symbol"],str(result).replace("'","\""))
						
				if config.STAT_SETTINGS["enabled"] == "true":	
					vals["date"] = datetime.now()
					vals["event"] = time.time()
					r.hmset(prefix + vals["symbol"], vals)
					r.incr(statPrefix + "ALL")		

					eventTime = int(math.floor(vals["event"]))
					cTime = vals["ctime"]
					diffTime = eventTime - cTime
					#print eventTime,cTime,diffTime
					if diffTime <= 1:
						r.incr(statPrefix + "1s")
					elif diffTime <= 3:
						r.incr(statPrefix + "3s")
					elif diffTime <= 5:
						r.incr(statPrefix + "5s")
					elif diffTime <= 10:
						r.incr(statPrefix + "10s")
					elif diffTime > 10:
						r.incr(statPrefix + "B10")

			
				print datetime.now(),time.time(),vals["ctime"],vals["symbol"],vals["bid"],vals["ask"],vals["high"],vals["low"]

    stream.close()
Ejemplo n.º 54
0
class TestBasicBinLogStreamReader(base.PyMySQLReplicationTestCase):
    def test_read_query_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        #RotateEvent
        self.stream.fetchone()
        #FormatDescription
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_connection_lost_event(self):
        self.stream.close()
        self.stream = BinLogStreamReader(connection_settings = self.database, blocking = True)
        
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query2 = "INSERT INTO test (data) VALUES('a')";
        for i in range(0, 10000):
            self.execute(query2)
        self.execute("COMMIT")

        #RotateEvent
        self.stream.fetchone()


        #FormatDescription
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

        self.conn_control.kill(self.stream._stream_connection.thread_id())
        for i in range(0, 1000):
            event = self.stream.fetchone()
            self.assertIsNotNone(event)

    def test_filtering_events(self):
        self.stream.close()
        self.stream = BinLogStreamReader(connection_settings = self.database, only_events = [QueryEvent])        
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_write_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)
        self.execute("COMMIT")

        #RotateEvent
        self.stream.fetchone()
        #FormatDescription
        self.stream.fetchone()
        #QueryEvent for the Create Table
        self.stream.fetchone()

        #QueryEvent for the BEGIN
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, TableMapEvent)

        event = self.stream.fetchone()
        self.assertEqual(event.event_type, WRITE_ROWS_EVENT)        
        self.assertIsInstance(event, WriteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)        
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")
        self.assertEqual(event.schema, "pymysqlreplication_test")
        self.assertEqual(event.table, "test")
        self.assertEqual(event.columns[1].name, 'data')

    def test_delete_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)

        self.resetBinLog()
        
        query = "DELETE FROM test WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        #RotateEvent
        self.stream.fetchone()
        #FormatDescription
        self.stream.fetchone()

        #QueryEvent for the BEGIN
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, TableMapEvent)

        event = self.stream.fetchone()
        self.assertEqual(event.event_type, DELETE_ROWS_EVENT)        
        self.assertIsInstance(event, DeleteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)        
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World") 

    def test_update_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)

        self.resetBinLog()
        
        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        #RotateEvent
        self.stream.fetchone()
        #FormatDescription
        self.stream.fetchone()

        #QueryEvent for the BEGIN
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, TableMapEvent)

        event = self.stream.fetchone()
        self.assertEqual(event.event_type, UPDATE_ROWS_EVENT)        
        self.assertIsInstance(event, UpdateRowsEvent)
        self.assertEqual(event.rows[0]["before_values"]["id"], 1)        
        self.assertEqual(event.rows[0]["before_values"]["data"], "Hello")
        self.assertEqual(event.rows[0]["after_values"]["id"], 1)        
        self.assertEqual(event.rows[0]["after_values"]["data"], "World")
def main():
    signal.signal(signal.SIGINT, signal_handler)
    global patternGeneralCollector
    global opsGeneralCollector
    global totalOps # Reset on each interval
    global countOps
    global countPatterns
    global patternC
    global binLogEventSizes
    global binLogReadBytes

    patternGeneralCollector = {}
    opsGeneralCollector = {}
    queryStats = {}
    rotateStats = {}
    loadQueryStats = {}
    totalOps = 0 # Reset on each interval
    countOps = 0
    countPatterns = 0
    prevTimeFlag = 0
    binLogEventSizes = 0
    binLogReadBytes = 0
    queryStats['count'] = 0
    rotateStats['count'] = 0
    rotateStats['size'] = 0
    loadQueryStats['count'] = 0
    firstRun = 1


    # Great resource http://blog.mattheworiordan.com/post/13174566389/url-regular-expression-for-links-with-or-without
    patternC = re.compile(r'[A-Za-z]{3,9}:\/\/(?:[A-Za-z0-9\.\-]+)')

    # server_id is your slave identifier, it should be unique.
    # set blocking to True if you want to block and wait for the next event at
    # the end of the stream
    #timeCheck = datetime.today()  # If event is bigger, sets it to now() and prints stats.
    timeCheck = time.time()
    #print "Starting at %s " % (timeCheck)
    # We always want to use MASTER_AUTO_POSITION = 1
    # Only events help us to keep the stream shorter as we can.
    stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                server_id=OPTIONS["serverid"],
                                log_file=OPTIONS["log_file"],
                                log_pos=OPTIONS["log_pos"],
                                resume_stream= True, # If no log_pos, set to False
                                #auto_position=1,
                                blocking=True,
                                only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent,QueryEvent, RotateEvent,BeginLoadQueryEvent, ExecuteLoadQueryEvent])


    for binlogevent in stream:
        patternCollector = None
        occurrence = None
        #if prevTimeFlag == 0:
        #    txTimeCheck = binlogevent.timestamp
        #    prevTimeFlag = 1

        if firstRun == 1:
            print "Binlog: %s Position: %s First Event TS: %s " % (OPTIONS["log_file"],OPTIONS["log_pos"], datetime.fromtimestamp(timeCheck))
            firstRun = 0

        if isinstance(binlogevent,QueryEvent):
            queryStats['count'] += 1
            continue
        elif isinstance(binlogevent,RotateEvent):
            rotateStats['count'] += 1
            rotateStats['size'] += binlogevent.event_size
            continue
        elif isinstance(binlogevent,ExecuteLoadQueryEvent) or isinstance(binlogevent,BeginLoadQueryEvent):
            loadQueryStats['count'] +=1
            continue

        for row in binlogevent.rows:
            if isinstance(binlogevent, DeleteRowsEvent):
                vals = row["values"]
                eventType = "delete"
            elif isinstance(binlogevent, UpdateRowsEvent):
                vals = row["after_values"]
                eventType = "update"
            elif isinstance(binlogevent, WriteRowsEvent):
                vals = row["values"]
                eventType = "insert"

            prefix = "%s.%s" %( binlogevent.schema, binlogevent.table)
            if (eventType, prefix) in opsGeneralCollector:
                opsGeneralCollector[eventType,prefix] += 1
            else:
                opsGeneralCollector[eventType,prefix] = 1

            occurrence = re.search(patternC, str(vals) )
            if  occurrence:
                occurrence = re.sub('[A-Za-z]{3,9}:\/\/','',occurrence.group())
                if (eventType,prefix,occurrence) in patternGeneralCollector.keys():
                    patternGeneralCollector[eventType,prefix,occurrence] += 1
                else:
                    patternGeneralCollector[eventType,prefix,occurrence] = 1

            totalOps += 1

        binLogEventSizes += binlogevent.event_size
        binLogReadBytes += binlogevent.packet.read_bytes

        # If interval has been committed, print stats and reset everything
        if (timeCheck + OPTIONS["interval"]) < time.time():
            #or txTimeCheck + OPTIONS["interval"] > time.time():
            printStats(opsGeneralCollector, \
                       patternGeneralCollector, \
                       binLogEventSizes, \
                       binLogReadBytes, \
                       queryStats,\
                       rotateStats,\
                       loadQueryStats)
            # Reset everything to release memory
            totalOps = 0
            patternGeneralCollector = {}
            opsGeneralCollector = {}
            queryStats['count'] = 0
            rotateStats['count'] = 0
            rotateStats['size'] = 0
            loadQueryStats['count'] = 0
            timeCheck = time.time()
            prevTimeFlag = 0
            binLogEventSizes = 0
            binLogReadBytes = 0
            firstRun = 0

    stream.close()
    def _binlog_loader(self):
        """
        read row from binlog
        """
        if self.is_binlog_sync:
            resume_stream = True
            logging.info("Resume from binlog_file: {file}  binlog_pos: {pos}".format(file=self.log_file,
                                                                                     pos=self.log_pos))
        else:
            resume_stream = False

        stream = BinLogStreamReader(connection_settings=self.binlog_conf,
                                    server_id=self.config['mysql']['server_id'],
                                    only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent, RotateEvent],
                                    only_tables=self.tables,
                                    resume_stream=resume_stream,
                                    blocking=True,
                                    log_file=self.log_file,
                                    log_pos=self.log_pos)
        for binlogevent in stream:
            self.log_file = stream.log_file
            self.log_pos = stream.log_pos

            # RotateEvent to update binlog record when no related table changed
            if isinstance(binlogevent, RotateEvent):
                self._save_binlog_record()
                continue
            for row in binlogevent.rows:
                if isinstance(binlogevent, DeleteRowsEvent):
                    if binlogevent.table == self.master:
                        rv = {
                            'action': 'delete',
                            'doc': row['values']
                        }
                    else:
                        rv = {
                            'action': 'update',
                            'doc': {k: row['values'][k] if self.id_key and self.id_key == k else None for k in row['values']}
                        }
                elif isinstance(binlogevent, UpdateRowsEvent):
                    rv = {
                        'action': 'update',
                        'doc': row['after_values']
                    }
                elif isinstance(binlogevent, WriteRowsEvent):
                    if binlogevent.table == self.master:
                        rv = {
                                'action': 'create',
                                'doc': row['values']
                            }
                    else:
                        rv = {
                                'action': 'update',
                                'doc': row['values']
                            }
                else:
                    logging.error('unknown action type in binlog')
                    raise TypeError('unknown action type in binlog')
                yield rv
                # print(rv)
        stream.close()
        raise IOError('mysql connection closed')
class TestBasicBinLogStreamReader(base.PyMySQLReplicationTestCase):
    def ignoredEvents(self):
        return [GtidEvent]

    def test_read_query_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertEqual(event.position, 4)
        self.assertEqual(event.next_binlog, "mysql-bin.000001")
        self.assertIsInstance(event, RotateEvent)

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_read_query_event_with_unicode(self):
        query = u"CREATE TABLE `testÈ` (id INT NOT NULL AUTO_INCREMENT, dataÈ VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertEqual(event.position, 4)
        self.assertEqual(event.next_binlog, "mysql-bin.000001")
        self.assertIsInstance(event, RotateEvent)

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_reading_rotate_event(self):
        query = "CREATE TABLE test_2 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.stream.close()

        query = "CREATE TABLE test_3 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        # Rotate event
        self.assertIsInstance(self.stream.fetchone(), RotateEvent)

    def test_connection_stream_lost_event(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database, server_id=1024, blocking=True, ignored_events=self.ignoredEvents()
        )

        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query2 = "INSERT INTO test (data) VALUES('a')"
        for i in range(0, 10000):
            self.execute(query2)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()

        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

        self.conn_control.kill(self.stream._stream_connection.thread_id())
        for i in range(0, 1000):
            event = self.stream.fetchone()
            self.assertIsNotNone(event)

    def test_filtering_events(self):
        self.stream.close()
        self.stream = BinLogStreamReader(self.database, server_id=1024, only_events=[QueryEvent])
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_write_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        # QueryEvent for the Create Table
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        # QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
        self.assertIsInstance(event, WriteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")
        self.assertEqual(event.schema, "pymysqlreplication_test")
        self.assertEqual(event.table, "test")
        self.assertEqual(event.columns[1].name, "data")

    def test_delete_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)

        self.resetBinLog()

        query = "DELETE FROM test WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        # QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V1)
        self.assertIsInstance(event, DeleteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")

    def test_update_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)

        self.resetBinLog()

        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        # QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V1)
        self.assertIsInstance(event, UpdateRowsEvent)
        self.assertEqual(event.rows[0]["before_values"]["id"], 1)
        self.assertEqual(event.rows[0]["before_values"]["data"], "Hello")
        self.assertEqual(event.rows[0]["after_values"]["id"], 1)
        self.assertEqual(event.rows[0]["after_values"]["data"], "World")

    def test_log_pos(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        self.execute("COMMIT")

        for i in range(6):
            self.stream.fetchone()
        # record position after insert
        log_file, log_pos = self.stream.log_file, self.stream.log_pos

        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        # resume stream from previous position
        if self.stream is not None:
            self.stream.close()
        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            resume_stream=True,
            log_file=log_file,
            log_pos=log_pos,
            ignored_events=self.ignoredEvents(),
        )

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)
        # QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), UpdateRowsEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)

    def test_log_pos_handles_disconnects(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            resume_stream=False,
            only_events=[FormatDescriptionEvent, QueryEvent, TableMapEvent, WriteRowsEvent, XidEvent],
        )

        query = "CREATE TABLE test (id INT  PRIMARY KEY AUTO_INCREMENT, data VARCHAR (50) NOT NULL)"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        self.assertGreater(self.stream.log_pos, 0)
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), WriteRowsEvent)

        self.assertIsInstance(self.stream.fetchone(), XidEvent)

        self.assertGreater(self.stream.log_pos, 0)
Ejemplo n.º 58
0
class TestMultipleRowBinLogStreamReader(base.PyMySQLReplicationTestCase):
    def ignoredEvents(self):
        return [GtidEvent]

    def test_insert_multiple_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        self.resetBinLog()

        query = "INSERT INTO test (data) VALUES('Hello'),('World')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
        self.assertIsInstance(event, WriteRowsEvent)
        self.assertEqual(len(event.rows), 2)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello")

        self.assertEqual(event.rows[1]["values"]["id"], 2)
        self.assertEqual(event.rows[1]["values"]["data"], "World")

    def test_update_multiple_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('World')"
        self.execute(query)

        self.resetBinLog()

        query = "UPDATE test SET data = 'Toto'"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V1)
        self.assertIsInstance(event, UpdateRowsEvent)
        self.assertEqual(len(event.rows), 2)
        self.assertEqual(event.rows[0]["before_values"]["id"], 1)
        self.assertEqual(event.rows[0]["before_values"]["data"], "Hello")
        self.assertEqual(event.rows[0]["after_values"]["id"], 1)
        self.assertEqual(event.rows[0]["after_values"]["data"], "Toto")

        self.assertEqual(event.rows[1]["before_values"]["id"], 2)
        self.assertEqual(event.rows[1]["before_values"]["data"], "World")
        self.assertEqual(event.rows[1]["after_values"]["id"], 2)
        self.assertEqual(event.rows[1]["after_values"]["data"], "Toto")

    def test_delete_multiple_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('World')"
        self.execute(query)

        self.resetBinLog()

        query = "DELETE FROM test"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V1)
        self.assertIsInstance(event, DeleteRowsEvent)
        self.assertEqual(len(event.rows), 2)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello")

        self.assertEqual(event.rows[1]["values"]["id"], 2)
        self.assertEqual(event.rows[1]["values"]["data"], "World")

    def test_drop_table(self):
        self.execute("CREATE TABLE test (id INTEGER(11))")
        self.execute("INSERT INTO test VALUES (1)")
        self.execute("DROP TABLE test")
        self.execute("COMMIT")

        #RotateEvent
        self.stream.fetchone()
        #FormatDescription
        self.stream.fetchone()
        #QueryEvent for the Create Table
        self.stream.fetchone()

        #QueryEvent for the BEGIN
        self.stream.fetchone()

        event = self.stream.fetchone()
        self.assertIsInstance(event, TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
        self.assertIsInstance(event, WriteRowsEvent)

        self.assertEqual([], event.rows)

    def test_drop_column(self):
        self.stream.close()
        self.execute("CREATE TABLE test_drop_column (id INTEGER(11), data VARCHAR(50))")
        self.execute("INSERT INTO test_drop_column VALUES (1, 'A value')")
        self.execute("COMMIT")
        self.execute("ALTER TABLE test_drop_column DROP COLUMN data")
        self.execute("INSERT INTO test_drop_column VALUES (2)")
        self.execute("COMMIT")

        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            only_events=(WriteRowsEvent,),
            )
        try:
            self.stream.fetchone()  # insert with two values
            self.stream.fetchone()  # insert with one value
        except Exception as e:
            self.fail("raised unexpected exception: {exception}".format(exception=e))
        finally:
            self.resetBinLog()

    @unittest.expectedFailure
    def test_alter_column(self):
        self.stream.close()
        self.execute("CREATE TABLE test_alter_column (id INTEGER(11), data VARCHAR(50))")
        self.execute("INSERT INTO test_alter_column VALUES (1, 'A value')")
        self.execute("COMMIT")
        # this is a problem only when column is added in position other than at the end
        self.execute("ALTER TABLE test_alter_column ADD COLUMN another_data VARCHAR(50) AFTER id")
        self.execute("INSERT INTO test_alter_column VALUES (2, 'Another value', 'A value')")
        self.execute("COMMIT")

        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            only_events=(WriteRowsEvent,),
            )
        event = self.stream.fetchone()  # insert with two values
        # both of these asserts fail because of issue underlying proble described in issue #118
        # because it got table schema info after the alter table, it wrongly assumes the second
        # column of the first insert is 'another_data'
        # ER: {'id': 1, 'data': 'A value'}
        # AR: {'id': 1, 'another_data': 'A value'}
        self.assertIn("data", event.rows[0]["values"])
        self.assertNot("another_data", event.rows[0]["values"])
        self.assertEqual(event.rows[0]["values"]["data"], 'A value')
        self.stream.fetchone()  # insert with three values
Ejemplo n.º 59
0
class BinLogDumper(object):

    def __init__(self, master_connect_setting,
                 server_id, log_file, log_pos,
                 outputer,
                 only_tables=None,
                 used_update_sql_tables=[]):
        '''
        used_update_sql_tables: tables which used `UPDATE` SQL instead of `REPLACE INTO` SQL.
        '''

        self.server_id = server_id
        self._master_connect_setting = master_connect_setting
        self._output = outputer
        assert callable(getattr(outputer, 'write')
                        ), 'outputer must hash interface `write(event)`'

        self._start_file = log_file
        self._start_pos = log_pos

        self.reading_file = self._start_pos
        self.reading_pos = self._start_file
        self.reading_timestamp = 0
        self.reading_event = 0

        self._master = sqlpool.SqlPool(**master_connect_setting)
        self._master_log_file = None
        self._master_log_pos = None
        self._stop = False
        self._running = False

        self._tables_desc = {}

        self._used_update_sql_tables = dict(
            [(t, True) for t in used_update_sql_tables])
        m = master_connect_setting
        hostname, user, password, port = socket.gethostname(), m['user'], m[
            'passwd'], m['port']

        self._stream = BinLogStreamReader(connection_settings=master_connect_setting,
                                          server_id=self.server_id,
                                          log_pos=self._start_pos, log_file=self._start_file,
                                          blocking=True, resume_stream=True,
                                          freeze_schema=True,
                                          only_tables=only_tables,
                                          report_slave=(
                                              hostname, user, password, port),
                                          slave_uuid=uuid.uuid4(),
                                          only_events=[QueryEvent,
                                                       WriteRowsEvent,
                                                       UpdateRowsEvent,
                                                       DeleteRowsEvent,
                                                       RotateEvent])

    def status(self):
        self._master_log_file, self._master_log_pos = self.show_master_status()

        return (self._master_log_file, self._master_log_pos,
                self.reading_file, self.reading_pos, self.reading_timestamp, self.reading_event)

    def set_timer_status(self, second):
        if self._stop:
            return
        threading.Timer(second, self.set_timer_status, (second,)).start()
        mfile, mpos, rfile, rpos, timestamp, cnt = self.status()
        logging.warn("Master.file[%s]:pos[%d]; Read.file[%s]:pos[%s];Seconds_Behind[%d],event.Cnt=[%d]",
                     mfile, mpos, rfile, rpos, time.time()-timestamp, cnt)

    def stop(self):
        self._stop = True
        logging.warn('BinLogDumper.Stop() was called. stop binlog dump.')
        if self._stream:
            logging.warn("Close binlog stream.")
            self._stream.close()
        wait = 3
        while wait and self._running:
            logging.warn("wait running exit.")
            time.sleep(1)
            wait -= 1

    def run(self):
        try:
            self._running = True
            self._loop()
            logging.warn("end loop in run()")
        except AttributeError, a:
            logging.info("AttributeError: %s", a.args)
        except Exception, e:
            if self._stop:
                logging.warn("Exception:%s", e)
            else:
                self.stop()
                logging.error("Exception:%s", traceback.format_exc())
                raise e
Ejemplo n.º 60
0
class TestBasicBinLogStreamReader(base.PyMySQLReplicationTestCase):
    def ignoredEvents(self):
        return [GtidEvent]

    def test_allowed_event_list(self):
        self.assertEqual(len(self.stream._allowed_event_list(None, None, False)), 13)
        self.assertEqual(len(self.stream._allowed_event_list(None, None, True)), 12)
        self.assertEqual(len(self.stream._allowed_event_list(None, [RotateEvent], False)), 12)
        self.assertEqual(len(self.stream._allowed_event_list([RotateEvent], None, False)), 1)

    def test_read_query_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertEqual(event.position, 4)
        self.assertEqual(event.next_binlog, "mysql-bin.000001")
        self.assertIsInstance(event, RotateEvent)

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_read_query_event_with_unicode(self):
        query = u"CREATE TABLE `testÈ` (id INT NOT NULL AUTO_INCREMENT, dataÈ VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertEqual(event.position, 4)
        self.assertEqual(event.next_binlog, "mysql-bin.000001")
        self.assertIsInstance(event, RotateEvent)

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)


    def test_reading_rotate_event(self):
        query = "CREATE TABLE test_2 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.stream.close()

        query = "CREATE TABLE test_3 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        # Rotate event
        self.assertIsInstance(self.stream.fetchone(), RotateEvent)

    """ `test_load_query_event` needs statement-based binlog
    def test_load_query_event(self):
        # prepare csv
        with open("/tmp/test_load_query.csv", "w") as fp:
            fp.write("1,aaa\n2,bbb\n3,ccc\n4,ddd\n")

        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "LOAD DATA INFILE '/tmp/test_load_query.csv' INTO TABLE test \
                FIELDS TERMINATED BY ',' \
                ENCLOSED BY '\"' \
                LINES TERMINATED BY '\r\n'"
        self.execute(query)

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        # create table
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        # begin
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), BeginLoadQueryEvent)
        self.assertIsInstance(self.stream.fetchone(), ExecuteLoadQueryEvent)

        self.assertIsInstance(self.stream.fetchone(), XidEvent)
    """

    def test_connection_stream_lost_event(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database, server_id=1024, blocking=True,
            ignored_events=self.ignoredEvents())

        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query2 = "INSERT INTO test (data) VALUES('a')"
        for i in range(0, 10000):
            self.execute(query2)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        event = self.stream.fetchone()

        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

        self.conn_control.kill(self.stream._stream_connection.thread_id())
        for i in range(0, 1000):
            event = self.stream.fetchone()
            self.assertIsNotNone(event)

    def test_filtering_only_events(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database, server_id=1024, only_events=[QueryEvent])
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query)

    def test_filtering_ignore_events(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database, server_id=1024, ignored_events=[QueryEvent])
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        event = self.stream.fetchone()
        self.assertIsInstance(event, RotateEvent)

    def test_filtering_table_event(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            only_events=[WriteRowsEvent],
            only_tables = ["test_2"])

        query = "CREATE TABLE test_2 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "CREATE TABLE test_3 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)

        self.execute("INSERT INTO test_2 (data) VALUES ('alpha')")
        self.execute("INSERT INTO test_3 (data) VALUES ('alpha')")
        self.execute("INSERT INTO test_2 (data) VALUES ('beta')")
        self.execute("COMMIT")
        event = self.stream.fetchone()
        self.assertEqual(event.table, "test_2")
        event = self.stream.fetchone()
        self.assertEqual(event.table, "test_2")

    def test_write_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        #QueryEvent for the Create Table
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
        self.assertIsInstance(event, WriteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")
        self.assertEqual(event.schema, "pymysqlreplication_test")
        self.assertEqual(event.table, "test")
        self.assertEqual(event.columns[1].name, 'data')

    def test_delete_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)

        self.resetBinLog()

        query = "DELETE FROM test WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V1)
        self.assertIsInstance(event, DeleteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")

    def test_update_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)

        self.resetBinLog()

        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V1)
        self.assertIsInstance(event, UpdateRowsEvent)
        self.assertEqual(event.rows[0]["before_values"]["id"], 1)
        self.assertEqual(event.rows[0]["before_values"]["data"], "Hello")
        self.assertEqual(event.rows[0]["after_values"]["id"], 1)
        self.assertEqual(event.rows[0]["after_values"]["data"], "World")

    def test_minimal_image_write_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "SET SESSION binlog_row_image = 'minimal'"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        #QueryEvent for the Create Table
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
        self.assertIsInstance(event, WriteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], "Hello World")
        self.assertEqual(event.schema, "pymysqlreplication_test")
        self.assertEqual(event.table, "test")
        self.assertEqual(event.columns[1].name, 'data')

    def test_minimal_image_delete_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello World')"
        self.execute(query)
        query = "SET SESSION binlog_row_image = 'minimal'"
        self.execute(query)
        self.resetBinLog()

        query = "DELETE FROM test WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, DELETE_ROWS_EVENT_V1)
        self.assertIsInstance(event, DeleteRowsEvent)
        self.assertEqual(event.rows[0]["values"]["id"], 1)
        self.assertEqual(event.rows[0]["values"]["data"], None)

    def test_minimal_image_update_row_event(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        query = "SET SESSION binlog_row_image = 'minimal'"
        self.execute(query)
        self.resetBinLog()

        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)

        #QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)

        event = self.stream.fetchone()
        if self.isMySQL56AndMore():
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V2)
        else:
            self.assertEqual(event.event_type, UPDATE_ROWS_EVENT_V1)
        self.assertIsInstance(event, UpdateRowsEvent)
        self.assertEqual(event.rows[0]["before_values"]["id"], 1)
        self.assertEqual(event.rows[0]["before_values"]["data"], None)
        self.assertEqual(event.rows[0]["after_values"]["id"], None)
        self.assertEqual(event.rows[0]["after_values"]["data"], "World")

    def test_log_pos(self):
        query = "CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        self.execute("COMMIT")

        for i in range(6):
            self.stream.fetchone()
        # record position after insert
        log_file, log_pos = self.stream.log_file, self.stream.log_pos

        query = "UPDATE test SET data = 'World' WHERE id = 1"
        self.execute(query)
        self.execute("COMMIT")

        # resume stream from previous position
        if self.stream is not None:
            self.stream.close()
        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            resume_stream=True,
            log_file=log_file,
            log_pos=log_pos,
            ignored_events=self.ignoredEvents()
        )

        self.assertIsInstance(self.stream.fetchone(), RotateEvent)
        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)
        # QueryEvent for the BEGIN
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), UpdateRowsEvent)
        self.assertIsInstance(self.stream.fetchone(), XidEvent)


    def test_log_pos_handles_disconnects(self):
        self.stream.close()
        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            resume_stream=False,
            only_events = [FormatDescriptionEvent, QueryEvent, TableMapEvent, WriteRowsEvent, XidEvent]
        )

        query = "CREATE TABLE test (id INT  PRIMARY KEY AUTO_INCREMENT, data VARCHAR (50) NOT NULL)"
        self.execute(query)
        query = "INSERT INTO test (data) VALUES('Hello')"
        self.execute(query)
        self.execute("COMMIT")

        self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
        self.assertGreater(self.stream.log_pos, 0)
        self.assertIsInstance(self.stream.fetchone(), QueryEvent)

        self.assertIsInstance(self.stream.fetchone(), QueryEvent)
        self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
        self.assertIsInstance(self.stream.fetchone(), WriteRowsEvent)

        self.assertIsInstance(self.stream.fetchone(), XidEvent)

        self.assertGreater(self.stream.log_pos, 0)

    def test_skip_to_timestamp(self):
        self.stream.close()
        query = "CREATE TABLE test_1 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query)
        time.sleep(1)
        query = "SELECT UNIX_TIMESTAMP();"
        timestamp = self.execute(query).fetchone()[0]
        query2 = "CREATE TABLE test_2 (id INT NOT NULL AUTO_INCREMENT, data VARCHAR (50) NOT NULL, PRIMARY KEY (id))"
        self.execute(query2)

        self.stream = BinLogStreamReader(
            self.database,
            server_id=1024,
            skip_to_timestamp=timestamp,
            ignored_events=self.ignoredEvents(),
            )
        event = self.stream.fetchone()
        self.assertIsInstance(event, QueryEvent)
        self.assertEqual(event.query, query2)