MySQL で二重引用符の位置が誤っていたために起きた殺人事件の詳細な分析

MySQL で二重引用符の位置が誤っていたために起きた殺人事件の詳細な分析

1. はじめに

最近、開発者が誤ってデータを削除したり更新したりするケースがよくあります。今回もまた問題になりました。全体のプロセスを見てみましょう。

2. プロセス

開発では本番フェーズでデータを修復する必要があるため、120のSQL文を実行してデータを更新する必要がある。

そこで開発者は本番データベースに接続し、最初のSQLを実行した。

テーブル名を更新し、ソース名を「bj1062-北京市朝陽区長営北辰富地」に設定します。
ここで、source_name は "-北京市朝陽区長営北辰富地" です。

この SQL を詳しく調べたところ、確かに問題がないことがわかりました。 where 条件も正常です。基本的な考え方は、アドレスの前に文字列 bj1062 を追加することです。本当にエラーはないのでしょうか?はい、エラーはありません。開発が完了した後、結果は確かに期待通りでした。

次に、開発者は上記の SQL と同じ残りの SQL を実行して、アドレスを更新しました。実行が完了した後、開発者は混乱し、source_name が 0 になっていることに気づきました。開発者はすぐに私に電話をかけ、こう言いました。

Harveyさん、更新を実行しました。WHERE条件は正しく、設定された値も正しいのですが、設定後のフィールドがすべて0になってしまいました。データを復元できるかどうか確認するのを手伝ってもらえますか?

この期間中にサーバーにすぐにログインして binlog を確認しました。update update tablename set source_name=0ステートメントが多数見つかりました。binlog2sql を使用して解析しました。プロジェクト アドレス: binlog2sql

開発者と連携して迅速に操作時間を特定し、フラッシュバック SQL を生成してデータを復旧し、現場の証拠を保存しました。

次に、開発によって実行された SQL をチェックしたところ、非常に奇妙な SQL がいくつか見つかりました。

これらの SQL ステートメント内の引用符は、where フィールド名の後に配置されます。簡略化された SQL ステートメントは次のようになります。

tbl_name を更新し、str_col="xxx" = "yyy" を設定します。

では、この SQL は MySQL でどのようにセマンティック変換を実行するのでしょうか?

こんな感じでしょうか?

tbl_name を更新し、(str_col="xxx" ) = "yyy" に設定します。

これは文法上の誤りであり、次の形式のみになります。

tbl_name を更新し、str_col=("xxx" = "yyy") を設定します。

そして

「xxx」=「yyy」を選択

の値は0なので、

tbl_name を更新し、str_col="xxx" = "yyy" を設定します。

同等

tbl_name を更新し、str_col=0 を設定します

したがって、すべての source_name フィールドは 0 に更新されます。

この種のステートメントが選択された形式で何が起こるかを調べてみましょう。

mysql [localhost] {msandbox} (テスト) > tbl_name から id、str_col を選択します。ここで、str_col="xxx" = "yyy" です。
+----+---------+
| id | 文字列 |
| 1 | ああ |
+----+----------+ | 2 | aaa |
+----+---------+
| 3 | ああ |
| 4 | ああ |

この SQL ではstr_col='aaa'のレコードも見つかったことがわかりました。なぜでしょうか?

mysql [localhost] {msandbox} (テスト) > 警告
警告の表示が有効になりました。
mysql [localhost] {msandbox} (テスト) > tbl_name から id、str_col を拡張して選択し、str_col="xxx" = "yyy"\G を実行する方法について説明します。
************************** 1. 行 ****************************
id: 1 select_type: SIMPLE テーブル: tbl_name タイプ: インデックス
セットに 1 行、警告 1 件 (0.00 秒)
可能なキー: NULL
キー: idx_str
参照: NULL
key_len: 33 行: 4
追加: where の使用; index の使用
フィルター: 100.00
注 (コード 1003): /* select#1 */ select `test`.`tbl_name`.`id` AS `id`,`test`.`tbl_name`.`str_col` AS `str_col` from `test`.`tbl_name` where ((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy')

ここで彼はwhere条件を次のように変換します。

((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy')

この条件は、まず str_col と 'xxx' が等しいかどうかを判断します。等しい場合、括弧内の値は 1 になります。等しくない場合は 0 になります。
次に、0 または 1 が 'yyy' と比較されます。

等号の片側は int で、もう一方は文字列なので、比較のために両側が float に変換されます。

MySQL の暗黙的な変換によって発生するクエリ結果エラーのケース分析

'yyy' は浮動小数点型に変換され、0 に等しくなります。0 と比較すると、0 は常に 1 に等しくなります。

mysql [localhost] {msandbox} (テスト) > 'yyy'+0.0 を選択します。
+-----------+
| 'yyy'+0.0 |
| 0 |
+-----------+
mysql [localhost] {msandbox} (テスト) > 0=0 を選択します。
+-----------+
セットに 1 行、警告 1 件 (0.00 秒)
+-----+
セット内の 1 行 (0.00 秒)
| 0=0 |
+-----+
+-----+
| 1 |

これにより、結果は常に真になります。つまり、選択ステートメントは次のSQLと同等です。

tbl_name から id、str_col を選択します (1=1)。

すべてのレコードが照会されます。

3. まとめ

SQL を書くときは、引用符が正しい位置にあるかどうかに注意する必要があります。引用符の位置が間違っていると、SQL は正常でも、実行結果がすべて間違ってしまうことがあります。実行する前に、テスト環境でテストを実行し、IDE の構文強調表示を使用して対応する問題を特定する必要があります。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • SQL 文で一重引用符と二重引用符を処理する方法
  • PostgreSQLにおけるシングルクォートとダブルクォートの説明
  • Mybatisは生成されたSQL文に自動的に一重引用符を追加します。
  • SQL で一重引用符「''''」を記述できないことの詳細な説明
  • SQL 文で一重引用符と二重引用符を使用する方法

<<:  CentOS 8が利用可能になりました

>>:  シンプルなスネークゲームを実現するネイティブjs

推薦する

Element-ui の組み込み 2 つのリモート検索 (ファジークエリ) の使用方法の説明

問題の説明フロントエンドリモート検索やファジークエリと呼ばれる種類のクエリがあります。 Ele.me...

mysqlは指定された期間内の統計データを取得します

mysqlは指定された期間内の統計データを取得します年別統計 選択 カウント(*)、 DATE_FO...

MySQL エラー コード 1064 の解決策

SQL ステートメント内の単語が mysql のキーワードと競合する場合は、`` (タブ キーの上)...

Zabbix 監視 Docker アプリケーション構成

コンテナの応用はますます一般的になっていますが、大量のコンテナをどのように管理すればよいのでしょうか...

ウェブページを最適化してメモリとCPUの使用率を削減

一部の Web ページは大きく見えなくても開くのに非常に時間がかかる場合があります。一方、他の We...

Linux で MySQL データベースのデータ ファイル パスを変更する手順

rpm インストール方法を使用して MySQL データベースをインストールした後、データ ファイルの...

Python Flask WeChat アプレットのログインプロセスとログイン API 実装コード

1. まずは効果を見てみましょうインターフェース要求によって返されるデータ: 2. 公式ログインフロ...

MySQLが中国語の文字を挿入する問題を永久に解決するコツを教えます

目次序文最初のステップ:ステップ2: このmy.iniを変更する要約する序文問題の説明:不正な文字列...

nginx パニック問題の解決方法の詳細な説明

nginx パニック問題に関しては、まず nginx の起動プロセス中に、マスター プロセスが構成フ...

Linux 上でプロジェクトをリリースするために Tomcat を展開するプロセスにおけるさまざまな問題と解決策

プロジェクトをプロジェクトサイトのテスト環境にデプロイするJDK1.8トムキャット8.5 Maven...

Dockerの急速な拡張の高度な方法

1. コマンド方式作成された Swarm クラスターで nginx サービスを実行し、--repli...

CSS3 引用のソースと出典をマークする方法

疫病のせいで家にこもりきりで、頭がおかしくなりそうなので、パソコンを起動して頭を働かせてみました。今...

ネイティブ JavaScript でショッピングカートを実装する

この記事では、ショッピングカートを実装するためのJavaScriptの具体的なコードを参考までに紹介...

Linux で rc.local ファイルがない場合の完璧なソリューション

新しい Linux ディストリビューションには rc.local ファイルがなくなりました。サービス...

WeChatアプレットは画像コントロールを選択します

この記事の例では、WeChatアプレットで画像コントロールを選択するための具体的なコードを参考までに...