A MySQL binlog listener running on Node.js.
ZongJi (踪迹) is pronounced as
This package is a "pure JS" implementation based on
This package has been tested to work in MySQL 5.5, 5.6, and 5.7.
For a complete implementation see
```bash $ npm install zongji ```
``` # Must be unique integer from 1-2^32 server-id = 1 # Row format required for ZongJi binlogformat = row # Directory must exist. This path works for Linux. Other OS may require # different path. logbin = /var/log/mysql/mysql-bin.log
binlogdodb = employees # Optional, limit which databases to log expirelogsdays = 10 # Optional, purge old logs maxbinlogsize = 100M # Optional, limit log size ``
```sql GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON . TO 'zongji'@'localhost' ```
If a
If there is a
Each instance includes the following methods:
Method Name | Arguments | Description ------------|-----------|------------------------
Options available:
Option Name | Type | Description ------------|------|-------------------------------
Default:
Default:
Example:
Example:
Example: ``
Supported Binlog Events:
Event name | Description ------------|---------------
Event Methods
Neither method requires any arguments.
Name | Description -------|---------------------------
ZongJi (踪迹) is pronounced as
zōng jì
in Chinese.This package is a "pure JS" implementation based on
node-mysql
. Since v0.2.0, The native part (which was written in C++) has been dropped.This package has been tested to work in MySQL 5.5, 5.6, and 5.7.
Quick Start
var zongji = new ZongJi({ /* ... MySQL Connection Settings ... */ });
// Each change to the replication log results in an event
zongji.on('binlog', function(evt) {
evt.dump();
});
// Binlog must be started, optionally pass in filters
zongji.start({
includeEvents: ['tablemap', 'writerows', 'updaterows', 'deleterows']
});
For a complete implementation see
example.js
...Installation
- Requires Node.js v4+
```bash $ npm install zongji ```
- Enable MySQL binlog in
my.cnf
, restart MySQL server after making the changes.
``` # Must be unique integer from 1-2^32 server-id = 1 # Row format required for ZongJi binlogformat = row # Directory must exist. This path works for Linux. Other OS may require # different path. logbin = /var/log/mysql/mysql-bin.log
binlogdodb = employees # Optional, limit which databases to log expirelogsdays = 10 # Optional, purge old logs maxbinlogsize = 100M # Optional, limit log size ``
* Create an account with replication privileges, e.g. given privileges to account
zongji` (or any account that you use to read binary logs)```sql GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON . TO 'zongji'@'localhost' ```
ZongJi Class
TheZongJi
constructor accepts one argument of either:- An object containing MySQL connection details in the same format as used by
node-mysql
- Or, a
node-mysql
Connection
orPool
object that will be used for querying column information.
If a
Connection
or Pool
object is passed to the constructor, it will not be destroyed/ended by Zongji's stop()
method.If there is a
dateStrings
node-mysql
configuration option in the connection details or connection, ZongJi
will follow it.Each instance includes the following methods:
Method Name | Arguments | Description ------------|-----------|------------------------
start
| options
| Start receiving replication events, see options listed below
stop
| None | Disconnect from MySQL server, stop receiving events
set
| options
| Change options after start()
on
| eventName
, handler
| Add a listener to the binlog
or error
event. Each handler function accepts one argument.Options available:
Option Name | Type | Description ------------|------|-------------------------------
serverId
| integer
| Unique number (1 - 232) to identify this replication slave instance. Must be specified if running more than one instance of ZongJi. Must be used in start()
method for effect.Default:
1
startAtEnd
| boolean
| Pass true
to only emit binlog events that occur after ZongJi's instantiation. Must be used in start()
method for effect.Default:
false
binlogName
| string
| Begin reading events from this binlog file. If specified together with binlogNextPos
, will take precedence over startAtEnd
.
binlogNextPos
| integer
| Begin reading events from this position. Must be included with binlogName
.
includeEvents
| [string]
| Array of event names to includeExample:
['writerows', 'updaterows', 'deleterows']
excludeEvents
| [string]
| Array of event names to excludeExample:
['rotate', 'tablemap']
includeSchema
| object
| Object describing which databases and tables to include (Only for row events). Use database names as the key and pass an array of table names or true
(for the entire database).Example: ``
{ 'my_database': ['allow_table', 'another_table'], 'another_db': true }
`
excludeSchema |
object | Object describing which databases and tables to exclude (Same format as
includeSchema)<br>**Example:**
`{ 'other_db': ['disallowed_table'], 'ex_db': true }
``- By default, all events and schema are emitted.
excludeSchema
andexcludeEvents
take precedence overincludeSchema
andincludeEvents
, respectively.
Supported Binlog Events:
Event name | Description ------------|---------------
unknown
| Catch any other events
query
| Insert/Update/Delete Query
intvar
| Autoincrement and LASTINSERTID
rotate
| New Binlog file Not required to be included to rotate to new files, but it is required to be included in order to keep the binlogName
and binlogNextPos
properties updated with current values for graceful restarting on errors.
format
| Format Description
xid
| Transaction ID
tablemap
| Before any row event (must be included for any other row events)
writerows
| Rows inserted, row data array available as rows
property on event object
updaterows
| Rows changed, row data array available as rows
property on event object
deleterows
| Rows deleted, row data array available as rows
property on event objectEvent Methods
Neither method requires any arguments.
Name | Description -------|---------------------------
dump
| Log a description of the event to the console
getEventName
| Return the name of the eventImportant Notes
- :star2: All types allowed by
node-mysql
are supported by this package. - :speaknoevil: While 64-bit integers in MySQL (
BIGINT
type) allow values in the range of 264 (± ½ × 264 for signed values), Javascript's internal storage of numbers limits values to 253, making the allowed range ofBIGINT
fields only-9007199254740992
to9007199254740992
. Unsigned 64-bit integers must also not exceed9007199254740992
. - :pointright:
TRUNCATE
statement does not cause correspondingDeleteRows
event. Use unqualifiedDELETE FROM
for same effect. - When using fractional seconds with
DATETIME
andTIMESTAMP
data types in MySQL > 5.6.4, only millisecond precision is available due to the limit of Javascript'sDate
object.
Run Tests
- install Docker
- run
docker-compose up
and then./docker-test.sh
Reference
I learnt many things from following resources while making ZongJi.- https://github.com/felixge/node-mysql
- https://github.com/felixge/faster-than-c/
- http://intuitive-search.blogspot.co.uk/2011/07/binary-log-api-and-replication-listener.html
- https://github.com/Sannis/node-mysql-libmysqlclient
- https://kkaefer.com/node-cpp-modules/
- http://dev.mysql.com/doc/internals/en/replication-protocol.html
- http://www.cs.wichita.edu/~chang/lecture/cs742/program/how-mysql-c-api.html
- https://github.com/jeremycole/mysqlbinlog (Ruby implemenation of MySQL binlog parser)
- http://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html