2

物語

最近、MySQL サーバーでレプリケーションをセットアップしました。マスター - マスター レプリケーションのルートをたどりました (ここで説明されているように、2 つのサーバー、それぞれがマスターであり、もう一方はスレーブです - http://brendanschwartz.com/post/12702901390/mysql-master-master-replication )。

WAMP で PhpMyAdmin を使用すると、一部のクエリが失敗したり、予期しない動作を表示したりすることに気付き始めました。たとえば、突然:

-- This fails
SELECT * FROM `tableName` WHERE `columnName` = 10;
-- This succeeds
SELECT * FROM tableName WHERE columnName = 10;
-- In some queries, specific columns seem to be the issue
-- So even this might work, but not always
SELECT * FROM `tableName` WHERE columnName = 10;
-- Sometimes it's even due to specific columns
-- So this might succeed
SELECT * FROM `tableName` WHERE `anotherColumnName` = 10;

MySQLシェルを介してそれを行うとうまくいったので、おそらくPhpMyAdminのせいだとすぐに気づきました。その後、Linux ベースの自分のマシンの PhpMyAdmin でも機能し、PhpMyAdmin のバージョンの方がはるかに新しいことに気付きました。

ただし、通常のシェルからいくつかのクエリを実行しようとすると、バッククォートの問題が発生します。たとえば、次のようになります。

# From my bash shell, this fails
mysql -s -uUser -pPassword -e "SELECT `columnName` FROM `dbName`.`tableName`;"
# This succeeds
mysql -s -uUser -pPassword -e "SELECT columnName FROM dbName.tableName;"

私は偶然を信じていないので、何が起こっているのかを確認したほうがよいと思いました。

私がこれまでに持っているもの

オンラインで検索したところ、ログに保存される方法が原因で、バックティックとレプリケーションに問題がある可能性があることがわかりました (私は思います)。しかし、レプリケーションがまだどのように機能しているかはまだ完全にはわかりませんが、一部のクエリはバッククォートで失敗しています。どちらかといえば、私のデータは、バックティックに問題がないことをサポートしています。

バックティックの目的を知っています- https://dba.stackexchange.com/questions/23129/benefits-of-using-backtick-in-mysql-queries

私のMySQLサーバーは実行されています:

  • Ubuntu 14.04.01 (64 ビット サーバー版)
  • MySQL バージョン 14.14 Distrib 5.5.41、readline 6.3 を使用する debian-linux-gnu (x86_64) 用

私の質問は次のとおりです。

  1. バックティックがレプリケーションに悪いのはなぜですか? バックティックで問題が発生する可能性はありますか、それとも難解なプラットフォーム固有の問題が原因でしたか?
  2. この問題に対処するための推奨される方法はありますか?
  3. 私の考えは、コード内のすべてのバッククォートを取り除くことです。私の列名はすべてプレーンな英語のアルファベットとキャメルケースであるため、バッククォートを使用する 必要はありません。
    1. に切り替えることができると思いましsql_mode = ANSI_QUOTESたが、値などのクエリの他の側面にどのように影響するかがわからないため、このような大きな変更にはシステム全体の徹底的なテストが必要になるのではないかと心配しています.
    2. また、バッククォートが名前の一部になっている可能性もあると思いましたが、動作に適合していないため、確認しました。

この問題に関して、どなたかのご意見をいただければ幸いです。

4

1 に答える 1

0

まず第一に、私の提案は、バッククォートを保持して使用することです。それらを使用しないと、MySQL の更新後にアプリケーションが壊れる危険性があります。MySQL 5.6 (またはそれ以前のバージョン) で新しく導入された予約語を見てください。大文字と小文字が区別されないため、キャメル ケースはここでは役に立ちません (maxValueまたはreSignal)。それらのいずれかをテーブルまたは列の名前として使用すると、アプリケーションが壊れます。それを危険にさらさないでください。

さて、あなたの質問に:

# From my bash shell, this fails
mysql -s -uUser -pPassword -e "SELECT `columnName` FROM `dbName`.`tableName`;"

たまたまエラーメッセージを見ましたか?シェル (bash) のバックティックは、実際にはコードの実行に使用されます。そのecho "host is `hostname`"ため、コマンドを実行し、hostnameそのプレースホルダーをそのコマンドの (端末) 出力に置き換えます。したがって、文字列は に変更されhost is computer0815、これは に供給されechoます。

commandd がcolumnName,dbNameまたはと呼ばれていない可能性が高いためtableName、シェルがそれらを空の文字列に置き換えた (そしてエラーを発行した) 可能性があるため、MySQL によって認識されるクエリSELECT FROM .;は明らかに無効であると読み取られ、失敗しました。

ヒント:シェルの拡張を避けるため'に、二重引用符の代わりに単一引用符を使用して再試行してください。"

  1. バックティックはレプリケーションにとって悪いことではありません。私はそれらをどこでも使用していますが、それらが原因でエラーが発生したことはありません-レプリケーションでも.
  2. クエリはどのように失敗しますか? それらは phpMyAdmin で失敗し、エラーが発生しますか? 彼らはアプリケーションに失敗しますか? エラーが出ますか?エラー メッセージを慎重に分析してください。問題の原因を突き止めることができます。
  3. ANSI 引用符はバッククォートとは関係ありませんが、二重引用符とは関係ありません"。したがって、列が文字列であること(ANSI 引用符なし)、または列が列と同じ値(ANSI 引用符) であるWHERE `login` = "name"ことを確認します。有効または無効の ANSI 引用符のように一重引用符を使用して文字列を引用すると、違いはありません。loginnameloginname'WHERE `login` = 'name'

さらに (詳細な) ヘルプが必要な場合は、クエリがどのように失敗するか、またはクエリが失敗すると思われる理由を詳しく説明してください。

于 2015-05-14T01:39:52.460 に答える