Coder Social home page Coder Social logo

go-mysql's Introduction

go-mysql

A pure go library to handle MySQL network protocol and replication.

semver example workflow gomod version

How to migrate to this repo

To change the used package in your repo it's enough to add this replace directive to your go.mod:

replace github.com/siddontang/go-mysql => github.com/go-mysql-org/go-mysql v1.8.0

v1.8.0 - is the last tag in repo, feel free to choose what you want.

Changelog

This repo uses Changelog.


Content

Replication

Replication package handles MySQL replication protocol like python-mysql-replication.

You can use it as a MySQL replica to sync binlog from master then do something, like updating cache, etc...

Example

import (
	"github.com/go-mysql-org/go-mysql/replication"
	"os"
)
// Create a binlog syncer with a unique server id, the server id must be different from other MySQL's. 
// flavor is mysql or mariadb
cfg := replication.BinlogSyncerConfig {
	ServerID: 100,
	Flavor:   "mysql",
	Host:     "127.0.0.1",
	Port:     3306,
	User:     "root",
	Password: "",
}
syncer := replication.NewBinlogSyncer(cfg)

// Start sync with specified binlog file and position
streamer, _ := syncer.StartSync(mysql.Position{binlogFile, binlogPos})

// or you can start a gtid replication like
// streamer, _ := syncer.StartSyncGTID(gtidSet)
// the mysql GTID set likes this "de278ad0-2106-11e4-9f8e-6edd0ca20947:1-2"
// the mariadb GTID set likes this "0-1-100"

for {
	ev, _ := streamer.GetEvent(context.Background())
	// Dump event
	ev.Dump(os.Stdout)
}

// or we can use a timeout context
for {
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	ev, err := streamer.GetEvent(ctx)
	cancel()

	if err == context.DeadlineExceeded {
		// meet timeout
		continue
	}

	ev.Dump(os.Stdout)
}

The output looks:

=== RotateEvent ===
Date: 1970-01-01 08:00:00
Log position: 0
Event size: 43
Position: 4
Next log name: mysql.000002

=== FormatDescriptionEvent ===
Date: 2014-12-18 16:36:09
Log position: 120
Event size: 116
Version: 4
Server version: 5.6.19-log
Create date: 2014-12-18 16:36:09

=== QueryEvent ===
Date: 2014-12-18 16:38:24
Log position: 259
Event size: 139
Salve proxy ID: 1
Execution time: 0
Error code: 0
Schema: test
Query: DROP TABLE IF EXISTS `test_replication` /* generated by server */

Canal

Canal is a package that can sync your MySQL into everywhere, like Redis, Elasticsearch.

First, canal will dump your MySQL data then sync changed data using binlog incrementally.

You must use ROW format for binlog, full binlog row image is preferred, because we may meet some errors when primary key changed in update for minimal or noblob row image.

A simple example:

package main

import (
	"github.com/go-mysql-org/go-mysql/canal"
	"github.com/siddontang/go-log/log"
)

type MyEventHandler struct {
	canal.DummyEventHandler
}

func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
	log.Infof("%s %v\n", e.Action, e.Rows)
	return nil
}

func (h *MyEventHandler) String() string {
	return "MyEventHandler"
}

func main() {
	cfg := canal.NewDefaultConfig()
	cfg.Addr = "127.0.0.1:3306"
	cfg.User = "root"
	// We only care table canal_test in test db
	cfg.Dump.TableDB = "test"
	cfg.Dump.Tables = []string{"canal_test"}

	c, err := canal.NewCanal(cfg)
	if err != nil {
		log.Fatal(err)
	}

	// Register a handler to handle RowsEvent
	c.SetEventHandler(&MyEventHandler{})

	// Start canal
	c.Run()
}

You can see go-mysql-elasticsearch for how to sync MySQL data into Elasticsearch.

Client

Client package supports a simple MySQL connection driver which you can use it to communicate with MySQL server.

Example

import (
	"github.com/go-mysql-org/go-mysql/client"
)

// Connect MySQL at 127.0.0.1:3306, with user root, an empty password and database test
conn, _ := client.Connect("127.0.0.1:3306", "root", "", "test")

// Or to use SSL/TLS connection if MySQL server supports TLS
//conn, _ := client.Connect("127.0.0.1:3306", "root", "", "test", func(c *Conn) {c.UseSSL(true)})

// Or to set your own client-side certificates for identity verification for security
//tlsConfig := NewClientTLSConfig(caPem, certPem, keyPem, false, "your-server-name")
//conn, _ := client.Connect("127.0.0.1:3306", "root", "", "test", func(c *Conn) {c.SetTLSConfig(tlsConfig)})

conn.Ping()

// Insert
r, _ := conn.Execute(`insert into table (id, name) values (1, "abc")`)

// Get last insert id
println(r.InsertId)
// Or affected rows count
println(r.AffectedRows)

// Select
r, err := conn.Execute(`select id, name from table where id = 1`)

// Close result for reuse memory (it's not necessary but very useful)
defer r.Close()

// Handle resultset
v, _ := r.GetInt(0, 0)
v, _ = r.GetIntByName(0, "id")

// Direct access to fields
for _, row := range r.Values {
	for _, val := range row {
		_ = val.Value() // interface{}
		// or
		if val.Type == mysql.FieldValueTypeFloat {
			_ = val.AsFloat64() // float64
		}
	}   
}

Tested MySQL versions for the client include:

  • 5.5.x
  • 5.6.x
  • 5.7.x
  • 8.0.x

Example for SELECT streaming (v1.1.1)

You can use also streaming for large SELECT responses. The callback function will be called for every result row without storing the whole resultset in memory. result.Fields will be filled before the first callback call.

// ...
var result mysql.Result
err := conn.ExecuteSelectStreaming(`select id, name from table LIMIT 100500`, &result, func(row []mysql.FieldValue) error {
    for idx, val := range row {
    	field := result.Fields[idx]
    	// You must not save FieldValue.AsString() value after this callback is done.
    	// Copy it if you need.
    	// ...
    }
    return nil
}, nil)

// ...

Example for connection pool (v1.3.0)

import (
    "github.com/go-mysql-org/go-mysql/client"
)

pool := client.NewPool(log.Debugf, 100, 400, 5, "127.0.0.1:3306", `root`, ``, `test`)
// ...
conn, _ := pool.GetConn(ctx)
defer pool.PutConn(conn)

conn.Execute() / conn.Begin() / etc...

Server

Server package supplies a framework to implement a simple MySQL server which can handle the packets from the MySQL client. You can use it to build your own MySQL proxy. The server connection is compatible with MySQL 5.5, 5.6, 5.7, and 8.0 versions, so that most MySQL clients should be able to connect to the Server without modifications.

Example

Minimalistic MySQL server implementation:

package main

import (
	"log"
	"net"

	"github.com/go-mysql-org/go-mysql/server"
)

func main() {
	// Listen for connections on localhost port 4000
	l, err := net.Listen("tcp", "127.0.0.1:4000")
	if err != nil {
		log.Fatal(err)
	}

	// Accept a new connection once
	c, err := l.Accept()
	if err != nil {
		log.Fatal(err)
	}

	// Create a connection with user root and an empty password.
	// You can use your own handler to handle command here.
	conn, err := server.NewConn(c, "root", "", server.EmptyHandler{})
	if err != nil {
		log.Fatal(err)
	}

	// as long as the client keeps sending commands, keep handling them
	for {
		if err := conn.HandleCommand(); err != nil {
			log.Fatal(err)
		}
	}
}

Another shell

$ mysql -h127.0.0.1 -P4000 -uroot
Your MySQL connection id is 10001
Server version: 5.7.0

MySQL [(none)]>
// Since EmptyHandler implements no commands, it will throw an error on any query that you will send

NewConn() will use default server configurations:

  1. automatically generate default server certificates and enable TLS/SSL support.
  2. support three mainstream authentication methods 'mysql_native_password', 'caching_sha2_password', and 'sha256_password' and use 'mysql_native_password' as default.
  3. use an in-memory user credential provider to store user and password.

To customize server configurations, use NewServer() and create connection via NewCustomizedConn().

Failover

Failover supports to promote a new master and let replicas replicate from it automatically when the old master was down.

Failover supports MySQL >= 5.6.9 with GTID mode, if you use lower version, e.g, MySQL 5.0 - 5.5, please use MHA or orchestrator.

At the same time, Failover supports MariaDB >= 10.0.9 with GTID mode too.

Why only GTID? Supporting failover with no GTID mode is very hard, because replicas can not find the proper binlog filename and position with the new master. Although there are many companies use MySQL 5.0 - 5.5, I think upgrade MySQL to 5.6 or higher is easy.

Driver

Driver is the package that you can use go-mysql with go database/sql like other drivers. A simple example:

package main

import (
	"database/sql"

	_ "github.com/go-mysql-org/go-mysql/driver"
)

func main() {
	// dsn format: "user:password@addr?dbname"
	dsn := "[email protected]:3306?test"
	db, _ := sql.Open(dsn)
	db.Close()
}

We pass all tests in https://github.com/bradfitz/go-sql-test using go-mysql driver. :-)

Donate

If you like the project and want to buy me a cola, you can through:

PayPal 微信
[

Feedback

go-mysql is still in development, your feedback is very welcome.

Gmail: [email protected]

go-mysql's People

Contributors

amyangfei avatar atercattus avatar atomicules avatar blazz avatar btoonk avatar d3hunter avatar domyway avatar dveeden avatar dvilaverde avatar fizic avatar fungaren avatar gdey avatar gleonid avatar gmhdbjd avatar guoyuanchao1202 avatar holys avatar huangjunwen avatar ianthereal avatar lance6716 avatar lintanghui avatar moredure avatar neartan avatar rainjoe avatar siddontang avatar skoef avatar taylorchu avatar viciious avatar wangxiangustc avatar zeminzhou avatar zhiiw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-mysql's Issues

Handling 'invalid data size' errors

Getting this error, unsure what the event is: invalid data size 57 in event WriteRowsEventV0, less event length 3215523821

If this is a protocol error, what's the best way to capture the data that's causing it to fail? I got there with #12, but that was painful. :-) How do I continue from this or any other error where I'd like to skip to the next event? There appears to be no way to retrieve the current position.

gtid replication, how to tell the master our GTID_PURGED

Thanks for this nice library. It is super helpful.

I'm trying to start gtid based binlog replication, but my server is closing the connection before my (Go) slave can get started:

binlogstreamer.go:47: [error] close sync with err: ERROR 1236 (HY000): 
The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, 
but the master has purged binary logs containing GTIDs that the slave requires.

According to https://www.percona.com/blog/2013/02/08/how-to-createrestore-a-slave-using-gtid-replication-in-mysql-5-6/ I simply need to set GTID_PURGED on the (Go) slave, so that it gets communicated to the server.

I don't see any place in the Go api of go-mysql to set the GTID_PURGED value. Is there one? I'm not sure how the master is asking the slave; or maybe the slave is just passing along that info in some initialization message?

panic decoding packet

I'm in pretty deep over my head here, but in attempting to write a simple program that dumps replication events from one of my MySQL 5.6.20 servers (based on the example in the README), I'm getting a panic in parser.go. Here's a test that reproduces the problem, but I had to build up parser.format and parser.tables from the parser state just before my program crashes. It's possible that earlier events are the true cause of the problem, but I do feel like an index bounds check in RowsEvent.decodeRows would help avoid the panic.

Here's parser_test.go:

package replication

import (
    "testing"
)

func TestIndexOutOfRange(t *testing.T) {
    parser := NewBinlogParser()

    parser.format = &FormatDescriptionEvent{
        Version:                0x4,
        ServerVersion:          []uint8{0x35, 0x2e, 0x36, 0x2e, 0x32, 0x30, 0x2d, 0x6c, 0x6f, 0x67, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
        CreateTimestamp:        0x0,
        EventHeaderLength:      0x13,
        EventTypeHeaderLengths: []uint8{0x38, 0xd, 0x0, 0x8, 0x0, 0x12, 0x0, 0x4, 0x4, 0x4, 0x4, 0x12, 0x0, 0x0, 0x5c, 0x0, 0x4, 0x1a, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x2, 0x0, 0x0, 0x0, 0xa, 0xa, 0xa, 0x19, 0x19, 0x0},
        ChecksumAlgorithm:      0x1,
    }

    parser.tables = map[uint64]*TableMapEvent{
        0x3043b:  &TableMapEvent{tableIDSize:6, TableID:0x3043b, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x61, 0x70, 0x70, 0x5f, 0x63, 0x72, 0x6f, 0x6e}, ColumnCount:0x15, ColumnType:[]uint8{0x3, 0xf, 0xc, 0xc, 0xf, 0x3, 0xc, 0x3, 0xfc, 0xf, 0x1, 0xfe, 0x2, 0xc, 0xf, 0xf, 0xc, 0xf, 0xf, 0x3, 0xf}, ColumnMeta:[]uint16{0x0, 0x180, 0x0, 0x0, 0x2fd, 0x0, 0x0, 0x0, 0x2, 0x180, 0x0, 0xfe78, 0x0, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x0, 0x2fd}, NullBitmap:[]uint8{0xf8, 0xfb, 0x17}},
        0x30453:  &TableMapEvent{tableIDSize:6, TableID:0x30453, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x73, 0x74, 0x67, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70}, ColumnCount:0x36, ColumnType:[]uint8{0x3, 0x3, 0x3, 0x3, 0x3, 0xf, 0xf, 0x8, 0x3, 0x3, 0x3, 0xf, 0xf, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xfe, 0x12, 0xf, 0xf, 0xf, 0xf6, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xfe, 0xf6, 0x12, 0x3, 0xf, 0xf, 0x1, 0x1, 0x12, 0xf, 0xf, 0xf, 0xf, 0x3, 0xf, 0x3}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x0, 0x2fd, 0x12c, 0x0, 0x0, 0x0, 0x0, 0x180, 0x180, 0x0, 0x30, 0x180, 0x180, 0x180, 0x30, 0xc0, 0xfe03, 0x0, 0x180, 0x180, 0x180, 0xc02, 0x0, 0x5a, 0x5a, 0x5a, 0x5a, 0x2fd, 0x2fd, 0x2fd, 0xc0, 0x12c, 0x30, 0xc, 0xfe06, 0xb02, 0x0, 0x0, 0x180, 0x180, 0x0, 0x0, 0x0, 0x180, 0x180, 0x2d, 0x2fd, 0x0, 0x2fd, 0x0}, NullBitmap:[]uint8{0xee, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x17}},
        0x30504:  &TableMapEvent{tableIDSize:6, TableID:0x30504, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x74, 0x67, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70}, ColumnCount:0x13, ColumnType:[]uint8{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xf, 0xc, 0xc, 0xc, 0xf, 0xf, 0x3, 0xf}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180, 0x0, 0x0, 0x0, 0x180, 0x180, 0x0, 0x2fd}, NullBitmap:[]uint8{0x6, 0xfb, 0x5}},
        0x30450:  &TableMapEvent{tableIDSize:6, TableID:0x30450, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74}, ColumnCount:0x16, ColumnType:[]uint8{0x3, 0xfc, 0xc, 0x3, 0xc, 0xf, 0x3, 0xf, 0xc, 0xf, 0xf, 0xf, 0xf, 0x3, 0xc, 0xf, 0xf, 0xf, 0xf, 0x3, 0x3, 0xf}, ColumnMeta:[]uint16{0x0, 0x2, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x180, 0x0, 0x180, 0x180, 0x2fd, 0x2d, 0x0, 0x0, 0x180, 0x180, 0x2fd, 0x2d, 0x0, 0x0, 0x2fd}, NullBitmap:[]uint8{0xfe, 0xff, 0x2f}},
        0x305bb:  &TableMapEvent{tableIDSize:6, TableID:0x305bb, Flags:0x1, Schema:[]uint8{0x79, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x67, 0x6f}, Table:[]uint8{0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x6c, 0x6f, 0x67}, ColumnCount:0x11, ColumnType:[]uint8{0x3, 0x3, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xc, 0xf, 0xf, 0xc, 0xf, 0xf, 0x3, 0xf}, ColumnMeta:[]uint16{0x0, 0x0, 0x2fd, 0x12c, 0x2fd, 0x2fd, 0x2d, 0x12c, 0x2fd, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x0, 0x2fd}, NullBitmap:[]uint8{0xfe, 0x7f, 0x1}},
        0x16c36b: &TableMapEvent{tableIDSize:6, TableID:0x16c36b, Flags:0x1, Schema:[]uint8{0x61, 0x63, 0x70}, Table:[]uint8{0x73, 0x74, 0x67, 0x5f, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x32}, ColumnCount:0xe, ColumnType:[]uint8{0x8, 0x8, 0x3, 0x3, 0x2, 0x2, 0xf, 0x12, 0xf, 0xf, 0x12, 0xf, 0xf, 0xf}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x2fd}, NullBitmap:[]uint8{0xba, 0x3f}},
        0x16c368: &TableMapEvent{tableIDSize:6, TableID:0x16c368, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x73, 0x74, 0x67, 0x5f, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x32}, ColumnCount:0xe, ColumnType:[]uint8{0x8, 0x8, 0x3, 0x3, 0x2, 0x2, 0xf, 0x12, 0xf, 0xf, 0x12, 0xf, 0xf, 0xf}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x2fd}, NullBitmap:[]uint8{0xba, 0x3f}},
        0x3045a:  &TableMapEvent{tableIDSize:6, TableID:0x3045a, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x63, 0x6f, 0x6e, 0x73}, ColumnCount:0x1e, ColumnType:[]uint8{0x3, 0x3, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xfe, 0x12, 0xf, 0xf, 0xf, 0xf6, 0xf, 0xf, 0xf, 0xf, 0x1, 0x1, 0x1, 0x12, 0xf, 0xf, 0x12, 0xf, 0xf, 0x3, 0xf, 0x1}, ColumnMeta:[]uint16{0x0, 0x0, 0x30, 0x180, 0x180, 0x180, 0x30, 0xc0, 0xfe03, 0x0, 0x180, 0x180, 0x180, 0xc02, 0x180, 0x180, 0x180, 0x180, 0x0, 0x0, 0x0, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x0, 0x2fd, 0x0}, NullBitmap:[]uint8{0xfc, 0xff, 0xe3, 0x37}},
        0x3045f:  &TableMapEvent{tableIDSize:6, TableID:0x3045f, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x63, 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72}, ColumnCount:0x19, ColumnType:[]uint8{0x3, 0x3, 0x3, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xfe, 0x3, 0xc, 0x1, 0xc, 0xf, 0xf, 0xc, 0xf, 0xf, 0x3, 0xf, 0x4, 0x4}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x2fd, 0x2fd, 0x2fd, 0xc0, 0x12c, 0x30, 0xc, 0xfe06, 0x0, 0x0, 0x0, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x0, 0x2fd, 0x4, 0x4}, NullBitmap:[]uint8{0xf0, 0xef, 0x5f, 0x0}},
        0x3065f:  &TableMapEvent{tableIDSize:6, TableID:0x3065f, Flags:0x1, Schema:[]uint8{0x73, 0x65, 0x69, 0x75, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72}, Table:[]uint8{0x63, 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72}, ColumnCount:0xd, ColumnType:[]uint8{0x3, 0x3, 0x3, 0x3, 0x1, 0x12, 0xf, 0xf, 0x12, 0xf, 0xf, 0x3, 0xf}, ColumnMeta:[]uint16{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180, 0x180, 0x0, 0x180, 0x180, 0x0, 0x2fd}, NullBitmap:[]uint8{0xe0, 0x17}},
    }

    _, err := parser.parse([]byte{
        /* 0x00, */ 0xc1, 0x86, 0x8e, 0x55, 0x1e, 0xa5, 0x14, 0x80, 0xa, 0x55, 0x0, 0x0, 0x0, 0x7, 0xc,
        0xbf, 0xe, 0x0, 0x0, 0x5f, 0x6, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2, 0x0, 0xd, 0xff,
        0x0, 0x0, 0x19, 0x63, 0x7, 0x0, 0xca, 0x61, 0x5, 0x0, 0x5e, 0xf7, 0xc, 0x0, 0xf5, 0x7,
        0x0, 0x0, 0x1, 0x99, 0x96, 0x76, 0x74, 0xdd, 0x10, 0x0, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70,
        0x5f, 0x64, 0x62, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6, 0x0, 0x73, 0x79, 0x73, 0x74,
        0x65, 0x6d, 0xb1, 0x3c, 0x38, 0xcb,
    })

    if err != nil {
        t.Errorf("error: %+v", err)
    }
}

And the test output:

=== RUN TestIndexOutOfRange
--- FAIL: TestIndexOutOfRange (0.00s)
panic: runtime error: index out of range [recovered]
    panic: runtime error: index out of range

goroutine 5 [running]:
testing.func·006()
    /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:441 +0x181
github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeRows(0xc208090140, 0xc208052320, 0x31, 0x35, 0xc2080900a0, 0xc20805231e, 0x2, 0x37, 0xc208090140, 0x0, ...)
    /tmp/gopathtmp/src/github.com/siddontang/go-mysql/replication/row_event.go:292 +0x60c
github.com/siddontang/go-mysql/replication.(*RowsEvent).Decode(0xc208090140, 0xc208052313, 0x3e, 0x42, 0x0, 0x0)
    /tmp/gopathtmp/src/github.com/siddontang/go-mysql/replication/row_event.go:261 +0x6a6
github.com/siddontang/go-mysql/replication.(*BinlogParser).parseEvent(0xc20801e260, 0xc20801e400, 0xc208052313, 0x3e, 0x42, 0x0, 0x0, 0x0, 0x0)
    /tmp/gopathtmp/src/github.com/siddontang/go-mysql/replication/parser.go:188 +0x12f
github.com/siddontang/go-mysql/replication.(*BinlogParser).parse(0xc20801e260, 0xc208052313, 0x42, 0x42, 0x0, 0x0, 0x0)
    /tmp/gopathtmp/src/github.com/siddontang/go-mysql/replication/parser.go:223 +0x33b
github.com/siddontang/go-mysql/replication.TestIndexOutOfRange(0xc20808e000)
    /tmp/gopathtmp/src/github.com/siddontang/go-mysql/replication/parser_test.go:42 +0x2434
testing.tRunner(0xc20808e000, 0x4350a0)
    /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:447 +0xbf
created by testing.RunTests
    /usr/local/Cellar/go/1.4.2/libexec/src/testing/testing.go:555 +0xa8b

Replication, binlogreader: "connection was bad"

While using binlogreader, as in:

... = binlogReader.binlogSyncer.RegisterSlave(connectionConfig.Key.Hostname, uint16(connectionConfig.Key.Port), connectionConfig.User, connectionConfig.Password)
...
<time passes>
...
ev, err := this.binlogStreamer.GetEvent()

I get a non nil err, which says "connection was bad"

This happens when enough time passes for the connection to invalidate. I'm trying to figure out if there is support for the equivalent MASTER_CONNECT_RETRY, MASTER_RETRY_COUNT, such that I would be able to configure the connection to retry as much as I want, with as small interval that I want.

I haven't figured this out yet -- is there such support?

Kind regards

replication block when network down

when the network is down (such as unplug the network cable) and recover after, the replication client will block at ReadPacket, this is the info of pprof:

goroutine 19 [IO wait, 14 minutes]:
net.runtime_pollWait(0x7fe48c176b70, 0x72, 0xc82177e000)
    /home/cdyf/go/src/runtime/netpoll.go:160 +0x60
net.(*pollDesc).Wait(0xc82176a760, 0x72, 0x0, 0x0)
    /home/cdyf/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc82176a760, 0x0, 0x0)
    /home/cdyf/go/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).Read(0xc82176a700, 0xc82177e000, 0x1000, 0x1000, 0x0, 0x7fe48c171050, 0xc82000a0f8)
    /home/cdyf/go/src/net/fd_unix.go:250 +0x23a
net.(*conn).Read(0xc821768120, 0xc82177e000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    /home/cdyf/go/src/net/net.go:172 +0xe4
bufio.(*Reader).fill(0xc8217783c0)
    /home/cdyf/go/src/bufio/bufio.go:97 +0x1e9
bufio.(*Reader).Read(0xc8217783c0, 0xc821c66148, 0x4, 0x4, 0x8, 0x0, 0x0)
    /home/cdyf/go/src/bufio/bufio.go:207 +0x260
io.ReadAtLeast(0x7fe48c131078, 0xc8217783c0, 0xc821c66148, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0)
    /home/cdyf/go/src/io/io.go:297 +0xe6
io.ReadFull(0x7fe48c131078, 0xc8217783c0, 0xc821c66148, 0x4, 0x4, 0x20, 0x0, 0x0)
    /home/cdyf/go/src/io/io.go:315 +0x62
mysql_byroad/vendor/github.com/siddontang/go-mysql/packet.(*Conn).ReadPacketTo(0xc82101e8c0, 0x7fe48c175d78, 0xc821a388c0, 0x0, 0x0)
    /home/cdyf/goworkspace/src/mysql_byroad/vendor/github.com/siddontang/go-mysql/packet/conn.go:81 +0xf1
mysql_byroad/vendor/github.com/siddontang/go-mysql/packet.(*Conn).ReadPacket(0xc82101e8c0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /home/cdyf/goworkspace/src/mysql_byroad/vendor/github.com/siddontang/go-mysql/packet/conn.go:35 +0x92
mysql_byroad/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream(0xc821717480, 0xc82101eca0)
    /home/cdyf/goworkspace/src/mysql_byroad/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:479 +0xa8
created by mysql_byroad/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).startDumpStream
    /home/cdyf/goworkspace/src/mysql_byroad/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:220 +0x111

I think this is because mysql server closed the connection and replication client didn't receive any close data because of bad network, so it blocked at reading data from this connection. Is there any solution for this condition?

replication:index out of range error

在运行的过程中,对于某一binlog位置,会报index out of range 错误,之前有邮件询问过,经过分析是发现RowEvent数据中最后多了一个字节,之后看了python-replication的代码,发现在https://github.com/noplay/python-mysql-replication/blob/master/pymysqlreplication/row_event.py#L391 判断是否结束是通过 while self.packet.read_bytes + 1 < self.event_size 来判断的,而你的代码https://github.com/siddontang/go-mysql/blob/master/replication/row_event.go#L260for pos < len(data) 来判断是否结束,因此如果最后多了一个字节,会使得循环继续下去而报错,在改为for pos+1 < len(data) 之后能够顺利的解析,不知道这样是否正确,希望能够解答下。

add syncer lib

Abstract some go-mysql-elasticsearch codes to build up a common syncer lib, not only for elasticsearch but also for others, like redis.

server端预处理执行的接口问题

对于代理服务器,往往需要转发客户端请求给服务端,在预处理的执行函数HandleStmtExecute(context interface{}, query string, args []interface{}) (_Result, error)中,args的类型为interface的数组,在client端,预处理执行函数func (s *Stmt) Execute(args ...interface{}) (_Result, error),args表示不定参数,用户在实现HandleStmtExecute时,很容易会将args []interface{}传递给args ...interface{},这很容易引起接口的误用

BinlogSyncer.Close() will be blocked if BinlogStreamer exists

BinlogSyncer.wg will be Add(1) when creating BinlogStreamer. And BinlogSyncer.wg only will be decrease when an error comes to BinlogSyncer.onStream.
BinlogSyncer.Close() was waiting on wg.
So if I call BinlogSyncer.Close() when there is no error in BinlogSyncer.onStream, process will be blocked.

add ping routine cause panic

I add a new routine to check connection like this:

image

panic info:

2016/11/28 20:19:02 binlogsyncer.go:514: [error] invalid sequence 1 != 2
panic: runtime error: slice bounds out of range

goroutine 54 [running]:
panic(0x3ce180, 0xc42000c130)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
bufio.(*Reader).Read(0xc4211fe7e0, 0xc4204bc394, 0x4, 0x4, 0x4, 0x0, 0x0)
/usr/local/go/src/bufio/bufio.go:216 +0x2a8
io.ReadAtLeast(0x611c40, 0xc4211fe7e0, 0xc4204bc394, 0x4, 0x4, 0x4, 0x3b4200, 0x1, 0xc4204bc394)
/usr/local/go/src/io/io.go:307 +0xa4
io.ReadFull(0x611c40, 0xc4211fe7e0, 0xc4204bc394, 0x4, 0x4, 0xc4201be800, 0x715000, 0x0)
/usr/local/go/src/io/io.go:325 +0x58
canal/libs/github.com/siddontang/go-mysql/packet.(*Conn).ReadPacketTo(0xc42278d0c0, 0x611d00, 0xc42171fc00, 0x5, 0x0)
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/packet/conn.go:81 +0x89
canal/libs/github.com/siddontang/go-mysql/packet.(*Conn).ReadPacket(0xc42278d0c0, 0x0, 0x0, 0xc42003bee0, 0x2c60e4, 0xc4201d0020)
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/packet/conn.go:35 +0x7b
canal/libs/github.com/siddontang/go-mysql/client.(*Conn).readOK(0xc42285c070, 0xc42003bf0e, 0x0, 0x0)
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/client/resp.go:85 +0x5b
canal/libs/github.com/siddontang/go-mysql/client.(*Conn).Ping(0xc42285c070, 0x14, 0xc42003bf88)
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/client/conn.go:97 +0x7d
canal/libs/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).ping(0xc4201d4880)
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/replication/binlogsyncer.go:250 +0x4e
created by canal/libs/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).startDumpStream
/Users/liangkai/Code/gopath/src/canal/libs/github.com/siddontang/go-mysql/replication/binlogsyncer.go:242 +0x11c

Is there something wrong?

Replication RowsEvent support

Hello. I have a use case where I want to read and process RowsEvents as a slave to a master MySQL DB. I had a project going that does this by tailing the binlog on the DB server itself, however, I would like to do it via the replication protocol instead. I noticed, in playing around with the replication package in the repository, that RowsEvents are just deserialized as GenericEvents. It only works with one version of MySQL currently, but I do have this library https://github.com/Granicus/mysql-binlog-go, which is capable of deserializing RowsEvents.

I want to fork this repository and add support for RowsEvents deserialization. My question to you is this: is it preferred that I create a more generic interface for my deserialization library and integrate it as a dependency here, or would it be better to attempt to fold the deserialization logic from the library into this library?

reading the binlog, is the gtid on the record available?

I can read from the binlog starting at a given point. I could count forward from there, but I think that gaps are allowed. So I think the records from the binlog must themselves be stamped with a GTID. But when I print out these records, I only see the old offset from non-gtid replication.

 ev.Header = &replication.EventHeader{Timestamp:0x58abc314, EventType:0x1e, ServerID:0x98352c, EventSize:0x673, LogPos:0x10081, Flags:0x0}

 ev = '=== WriteRowsEventV2 ===
Date: 2017-02-20 22:33:24
Log position: 65665
Event size: 1651
TableID: 72
Flags: 1
Column count: 58
Values:
--
...

Is the GTID hiding somewhere in the binary data, just not yet decoded?

'invalid ok packet' error

Received when connecting using user with 'replication slave' privilege. The user was already being used in master -> slave1 replication. This lib was being used for slave1 -> other datastore replication. Creating a different user with replication slave privilege resolved the issue. Unclear why, but resolved.

Selects with 0 rows result in a crash

Hi,

When I run a select that doesn't return any rows, I get a panic:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x693de]

goroutine 12 [running]:
github.com/siddontang/go-mysql/mysql.(*Field).Dump(0x0, 0x0, 0x0, 0x0)
    /gocode/src/github.com/siddontang/go-mysql/mysql/field.go:121 +0x4e

Authentication handler

Authentication should be exposed as a handler that way more than a single username/password combination could be supported.

Getting unsigned values for INT column

Set up to use row-format replication from MySQL 5.6.5, I'm getting large positive values in place of small negative ones for a column defined as INT which should be 32-bit signed. Here's a part of the debug log:

2016/01/07 20:04:27 [DEBUG] === UpdateRowsEventV2 ===
Date: 2016-01-07 15:48:58
Log position: 1007
Event size: 72
TableID: 74
Flags: 1
Column count: 4
Values:
--
0:566
1:2379
2:4294967295
3:"2016-01-07 15:44:32"
--
0:566
1:2379
2:4294967294
3:"2016-01-07 15:44:32"

The column '2' value was changed from -1 (received as 4294967295) to -2 (received as 4294967294).
I looked at the TableMapEvent for this table and didn't see anywhere that an unsigned 'meta' bit was set.

I even changed the schema of column '1' to be unsigned and I still didn't see any unsigned 'meta' bit in the debug output. There's a lot of binary data and it's possible I missed it, but the first case of an INT field -1 => -2 being reported as 4294967295 => 4294967294 stands.

Dump fails if field value contains INSERT INTO statement

Dump fails if field value contains INSERT INTO statement, like INSERT INTO `table` VALUES ('');

2016/11/18 11:23:50 dump.go:32: [error] get schema.task` VALUES ('2QhUaRNzRUBP6yUH','TRaScZha',1474954092309183,3,'2QhUaRNz','2QhUaRNz','','','2QhUaRNznpZYD3jt',0,1,'','INSERT INTO `table information err: ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'table' at line 1

valuesExp in dump/parser.go should use non greedy capture

// origin
valuesExp = regexp.MustCompile("^INSERT INTO `(.+)` VALUES \\((.+)\\);$")

// fixed
valuesExp = regexp.MustCompile("^INSERT INTO `(.+?)` VALUES \\((.+)\\);$")

StreamEvents encountered unexpected error: Err: runtime error: index out of range

Issue description

I try to migrate table using the tool gh-ost that uses go-sql-driver/mysql but each time I get the same error unexpected error: Err: runtime error: index out of range. Do you have any idea how to fix the issue?

Thank you

There is ticket in gh-ost

Error log

2016-10-24 00:43:18 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 16 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc82000bf60, 0xc8200d80c0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x798ea0, 0xc82000c080)
        /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc82042385e, 0x3, 0x5a2, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc82007dcc0, 0xc82042385e, 0x3, 0x5a2, 0xa00f6, 0x0, 
2016-10-23 20:31:10 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 13 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc82000b720, 0xc820112480)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x798ea0, 0xc82000c080)
        /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc82022a05e, 0x3, 0x5a2, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc8201c6d20, 0xc82022a05e, 0x3, 0x5a2, 0xa00f6, 0x0,
2016-10-14 22:36:32 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 20 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc820134700, 0xc820112480)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x798ea0, 0xc82000c090)
  /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc82037d85e, 0x3, 0x5a2, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc8201b6aa0, 0xc82037d85e, 0x3, 0x5a2, 0xa00f6, 0x0,
2016-10-20 04:30:17 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 16 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc820152100, 0xc8200d60c0)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x798ea0, 0xc82000c080)
  /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc82030cc5e, 0x3, 0x5a2, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
  /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc8201a59a0, 0xc82030cc5e, 0x3, 0x5a2, 0xa00f6, 0x0,
2016-10-13 20:13:24 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 20 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc8200fd420, 0xc82013a000)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x798ea0, 0xc82000c090)
        /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc8203d78c7, 0xaa, 0x539, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc82022b180, 0xc8203d78c7, 0xaa, 0x539, 0xa00f6, 0x0
2016-10-13 08:36:37 INFO StreamEvents encountered unexpected error: Err: runtime error: index out of range
 Stack: goroutine 137735 [running]:
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql.Pstack(0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/mysql/util.go:18 +0x7b
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*BinlogSyncer).onStream.func1(0xc820195d80, 0xc820230840)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/binlogsyncer.go:488 +0x66
panic(0x797b60, 0xc82000c090)
        /usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:443 +0x4e9
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.decodeDecimal(0xc82019e05e, 0x3, 0x5a2, 0x0, 0xa, 0x13, 0x5, 0x0, 0x0)
        /Users/shlomi-noach/dev/go/src/github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication/row_event.go:513 +0xcc7
github.com/github/gh-ost/vendor/github.com/siddontang/go-mysql/replication.(*RowsEvent).decodeValue(0xc8201cd2c0, 0xc82019e05e, 0x3, 0x5a2, 0xa00f6, 0

Configuration

MySQL 5.7.11 on AWS RDS
Ubuntu 14.04

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.