Skip to content

Instantly share code, notes, and snippets.

@numtel
Created December 18, 2014 09:13
Show Gist options
  • Select an option

  • Save numtel/2e9771a16b3470be7101 to your computer and use it in GitHub Desktop.

Select an option

Save numtel/2e9771a16b3470be7101 to your computer and use it in GitHub Desktop.
Tail mysqlbinlog in row mode with Node JS
#!/usr/bin/env node
var determineDb = function(lines, startIndex){
// Look backward from statement at startIndex to find database name used
var result;
for(var i = startIndex; i >= 0; i--){
result = lines[i].match(/^use (`([^\.]+)`|[^\.\/]+)?/i);
if(result === null) continue;
if(result[2] === undefined){
return result[1];
}else{
return result[2];
}
}
};
var tableModEvents = [
{
type: 'alterTable',
match: /^ALTER TABLE/i
},
{
type: 'dropTable',
match: /^DROP TABLE/i
},
{
type: 'createTable',
match: /^CREATE TABLE( IF NOT EXISTS)?/i
},
{
type: 'truncateTable',
match: /^TRUNCATE/i
},
{
type: 'insert',
match: /^### INSERT INTO/
},
{
type: 'update',
match: /^### UPDATE/
},
{
type: 'delete',
match: /^### DELETE FROM/
}
];
var checkTableMod = function(lines, index){
for(var m = 0; m < tableModEvents.length; m++){
var result = lines[index].match(tableModEvents[m].match);
var table, db;
if(!result) continue;
var target = lines[index].substr(result[0].length)
.match(/^ (`([^\.]+)`|[^\.]+)?(\.`(.+)`|\..+)?/);
// Map possible regex results to data
// x: value must not be undefined but discard
// t: table name
// d: database name
// -: undefined
var checkRes = ['xt---', 'xxt--', 'xd-xt', 'xd-t-', 'xxdt-', 'xxdxt' ];
var expect;
for(var p = 0; p < checkRes.length; p++){
table = undefined;
db = undefined;
for(var i = 0; i < checkRes[p].length; i++){
expect = checkRes[p][i];
if((expect === '-' && target[i] !== undefined) ||
((expect === 'x' || expect === 't') && target[i] === undefined)){
break;
}
if(expect === 't') table = target[i];
else if(expect === 'd') db = target[i];
}
if(i === checkRes[p].length) break;
}
if(!db) db = determineDb(lines, index);
if(table.substr(0, 1) === '.') table = table.substr(1);
return {
type: tableModEvents[m].type,
table: table,
db: db
};
}
};
// include db in cmd params
var binlog = '/usr/bin/mysqlbinlog -v --base64-output=DECODE-ROWS --start-position=%d %s',
exec = require('child_process').exec,
fs = require('fs'),
output = function (e, out, err) {
console.log(out);
// event emitters
var lines = out.split("\n");
for (var i=0; i < lines.length; i++) {
var tableMod = checkTableMod(lines, i);
tableMod && console.log(tableMod);
}
},
util = require('util'),
tail = function (e, out, err) {
var logfile = out.replace(/(\n|\r)+$/, '');
var prev = fs.statSync(logfile);
console.log('tailing ' + logfile + '...');
fs.watch(logfile , function (evt, filename) {
console.log(arguments, prev);
var cmd = util.format(binlog, prev.size, logfile);
console.log(cmd);
exec(cmd, output);
prev = fs.statSync(logfile);
});
};
exec('ls -t /var/log/mysql/mysql-bin* | head -n1', tail );
@numtel

numtel commented Dec 18, 2014

Copy link
Copy Markdown
Author

I began working on this as an update to https://gist.github.com/petethomas/1572119 but am not going to use this approach. Instead, the zongji NPM module seems like a better way to accomplish this task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment