MySQL5.6データベースとmysql
クライアントを使用して接続するnode.jsExpressプロジェクトがあります。プロジェクトにはORMがなく、生のクエリがDBに対して実行されます。ここで、SELECT
(トランザクション内にない)クエリがMySQL読み取りレプリカにルーティングされるようにコードを変更する必要があります。私はこれまで他のプロジェクトで同様のことをしたことがないので、(node.jsで)それを行うためのベストプラクティスは何であるか疑問に思いました。
私がいることを発見したsequelize
ライブラリは読み取りおよび書き込みが個別にレプリカし、別のクエリが異なるデータベースにルーティングされるだろうが、私はそれをやってのいずれかのオプション発見していない指定することを可能にする設定オプションがあるmysql
クライアントライブラリを。を使用してみましたsequelize
が、RAWクエリではこの機能がサポートされていないようです。
それとは別に、アーキテクチャの観点から最善の解決策は何でしょうか?現在、私が見ている唯一のオプションは、query
メソッドを持つデータベースラッパーサービスmysql
connection.query
を使用することです。これは、をカプセル化し、提供されたSQLに基づいて、使用するデータベース接続を決定します(読み取りまたは書き込み(トランザクションでない場合))。すべて同じDBで実行する必要があると思います)。これはかなり馬鹿げた解決策ですが、今のところ私の唯一のアイデアです。
誰かがこれに関するいくつかの経験を共有できますか?node.jsプロジェクトだけでなく、アーキテクチャのアイデアも歓迎します。おそらく、ホストに到達する前にリクエストをプロキシする方法はありますか?よろしくお願いします。
したがって、最終的には、かなり簡単な方法で解決しました。読み取りと書き込みのDBレプリカ用に個別の接続プールを作成し、必要な場所でそれぞれを直接使用しました。
const writePool = mysql.createPool(writeConnectionString);
const readPool = mysql.createPool(readConnectionString);
function getWriteConnection() {
return writePool.getConnection();
};
async function getReadConnection() {
const connection = await readPool.getConnection();
connection.isRead = true;
const originalQuery = connection.query;
connection.query = function (...args) {
if(!isSelectQuery(args[0])) {
throw new Error('Read connection cannot be used for the commands other than SELECT.');
}
return originalQuery.apply(this, args);
};
return connection;
};
// checking if query is SELECT
function isSelectQuery(query) {
return query.replace(/\s+/mi, '').toLowerCase().startsWith('select');
}
// release function
function release(connection) {
if(connection.isRead) {
readPool.releaseConnection(connection)
} else {
writePool.releaseConnection(connection);
}
};
次にコードで:
const connection = await database.getReadConnection();
await connection.query('SELECT * FROM ...');
....
database.release(connection);
これはそれを解決するための最も洗練された方法ではありませんが、最小限の変更とその後のバグで私の問題を比較的迅速に解決しました。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加