Server: PROTOCOL_CONNECTION_LOST when connecting with mysqli
See original GitHub issueWe are using mysql2
proxy example and see a fatal PROTOCOL_CONNECTION_LOST
exception after several sql queries have successfully executed. MySQL version is 5.7.
My guess is that we are not handling the sequenceId
correctly somewhere as we also see Warning: got packets out of order. Expected 2 but received 0
.
For testing, the proxy code is as per the vanilla example with the exception that we set the sequencId
to 0 in the authCallback
and to 1 on query
. Here is the full code:
"use strict";
const mysql = require("mysql2");
const ClientFlags = require("mysql2/lib/constants/client.js");
const server = mysql.createServer();
server.listen(3300);
server.on("connection", (conn) => {
console.log("connection");
conn.serverHandshake({
protocolVersion: 10,
serverVersion: "node.js rocks",
connectionId: 1234,
statusFlags: 2,
characterSet: 8,
capabilityFlags: 0xffffff,
authCallback: () => {
conn.writeOk();
conn.sequenceId = 0;
},
});
conn.on("field_list", (table, fields) => {
console.log("field list:", table, fields);
conn.writeEof();
});
const remote = mysql.createConnection({
user: "root",
database: "wordpress",
host: "127.0.0.1",
password: "supersecret",
port: 3310,
});
conn.on("query", (sql) => {
console.log(`${sql}\n`);
conn.sequenceId = 1;
remote.query(sql, function (err) {
// overloaded args, either (err, result :object)
// or (err, rows :array, columns :array)
if (Array.isArray(arguments[1])) {
// response to a 'select', 'show' or similar
const rows = arguments[1],
columns = arguments[2];
conn.writeTextResult(rows, columns);
} else {
// response to an 'insert', 'update' or 'delete'
const result = arguments[1];
conn.writeOk(result);
}
});
});
conn.on("end", remote.end.bind(remote));
});
Connecting a wordpress site, when loading, it fires a few sql queries and I see:
connection
SELECT @@SESSION.sql_mode
Warning: got packets out of order. Expected 6 but received 0
SET SESSION sql_mode='IGNORE_SPACE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
Warning: got packets out of order. Expected 2 but received 0
events.js:291
throw er; // Unhandled 'error' event
^
Error: Connection lost: The server closed the connection.
at Socket.<anonymous> (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:91:31)
at Socket.emit (events.js:314:20)
at TCP.<anonymous> (net.js:673:12)
Emitted 'error' event on Connection instance at:
at Connection._notifyError (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:221:12)
at Socket.<anonymous> (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:97:12)
at Socket.emit (events.js:314:20)
at TCP.<anonymous> (net.js:673:12) {
fatal: true,
Now, if i reset the sequence id at the end of the remote.query
, it gets s lot further (successfully completes multiple sql statements and then fails with the same error. Here is the code with the addition:
conn.on("query", (sql) => {
console.log(`${sql}\n`);
conn.sequenceId = 1;
remote.query(sql, function (err) {
// overloaded args, either (err, result :object)
// or (err, rows :array, columns :array)
if (Array.isArray(arguments[1])) {
// response to a 'select', 'show' or similar
const rows = arguments[1],
columns = arguments[2];
conn.writeTextResult(rows, columns);
} else {
// response to an 'insert', 'update' or 'delete'
const result = arguments[1];
conn.writeOk(result);
}
conn.sequenceId = 0;
});
});
Here is the output when executing with the additional conn.sequenceId = 0;
:
connection
SELECT @@SESSION.sql_mode
SET SESSION sql_mode='IGNORE_SPACE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
Warning: got packets out of order. Expected 2 but received 0
SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'
SELECT option_value FROM wp_options WHERE option_name = 'WPLANG' LIMIT 1
SELECT * FROM wp_users WHERE user_login = 'ben' LIMIT 1
SELECT user_id, meta_key, meta_value FROM wp_usermeta WHERE user_id IN (1) ORDER BY umeta_id ASC
SELECT option_value FROM wp_options WHERE option_name = 'can_compress_scripts' LIMIT 1
SELECT option_value FROM wp_options WHERE option_name = 'theme_switched' LIMIT 1
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10
SELECT FOUND_ROWS()
SELECT wp_posts.* FROM wp_posts WHERE ID IN (1)
SELECT t.*, tt.*, tr.object_id FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category', 'post_tag', 'post_format') AND tr.object_id IN (1) ORDER BY t.name ASC
SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (1) ORDER BY meta_id ASC
SELECT option_value FROM wp_options WHERE option_name = '_site_transient_update_plugins' LIMIT 1
SELECT option_value FROM wp_options WHERE option_name = '_site_transient_update_themes' LIMIT 1
SELECT option_value FROM wp_options WHERE option_name = '_site_transient_update_core' LIMIT 1
SELECT comment_approved, COUNT( * ) AS total
FROM wp_comments
GROUP BY comment_approved
SELECT * FROM wp_posts WHERE (post_type = 'page' AND post_status = 'publish') ORDER BY menu_order,wp_posts.post_title ASC
SELECT wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND ((wp_posts.post_status = 'publish')) ORDER BY wp_posts.post_date DESC LIMIT 0, 5
SELECT wp_comments.comment_ID FROM wp_comments JOIN wp_posts ON wp_posts.ID = wp_comments.comment_post_ID WHERE ( comment_approved = '1' ) AND wp_posts.post_status IN ('publish') ORDER BY wp_comments.comment_date_gmt DESC LIMIT 0,5
SELECT wp_comments.* FROM wp_comments WHERE comment_ID IN (1)
SELECT comment_id, meta_key, meta_value FROM wp_commentmeta WHERE comment_id IN (1) ORDER BY meta_id ASC
SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM wp_posts WHERE post_type = 'post' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC
SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ('category') AND tt.count > 0 ORDER BY t.name ASC
SELECT term_id, meta_key, meta_value FROM wp_termmeta WHERE term_id IN (1) ORDER BY meta_id ASC
events.js:291
throw er; // Unhandled 'error' event
^
Error: Connection lost: The server closed the connection.
at Socket.<anonymous> (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:91:31)
at Socket.emit (events.js:314:20)
at TCP.<anonymous> (net.js:673:12)
Emitted 'error' event on Connection instance at:
at Connection._notifyError (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:221:12)
at Socket.<anonymous> (/Users/VisualStudio/node_modules/mysql2/lib/connection.js:97:12)
at Socket.emit (events.js:314:20)
at TCP.<anonymous> (net.js:673:12) {
fatal: true,
code: 'PROTOCOL_CONNECTION_LOST'
}
So it looks like we are not handling the sequenceId’s correctly. We would be very grateful for some advice 👍
Issue Analytics
- State:
- Created 3 years ago
- Comments:17 (4 by maintainers)
1 is for
COM_QUIT
- php client might be closing connection ( and 3 isCOM_QUERY
)thanks for more debug examples, investigating right now
Hi @haganbt , thanks for more debug info
simple php mysqli “select 1+1” script worked for me with a server from https://github.com/sidorares/node-mysql2/tree/passthrough-auth-token branch. I’m currently attempting to provide example that would work with master