web-dev-qa-db-ja.com

これにより、パフォーマンスが大幅に低下しますか?

ブルートフォースログインを防ぐために(最善を尽くして)このトリガーがあります。次の2つの機能があります。

  1. 失敗したログインが過去3分間に同じIPアドレスから4回を超えて(つまり、正確に5回読んだ場合)試行された場合、そのIP_addressがblacklisted_ipsテーブルに追加されます。その場合、IPアドレスには、表の列で指定された「クールダウン」期間があります。

  2. 失敗したログインが同じユーザー名から過去2分間(IPアドレスに依存しないため)に3回以上試行された場合(正確に4回読み取った場合)、ユーザー名はblacklisted_usernamesテーブルに追加されます。ユーザー名には、表の列で指定された「クールダウン」期間があります。

私の質問は、このトリガーを見ると、パフォーマンスが非効率的に見えることです。それは正しいと思いますか、それともパフォーマンスへの影響は無視できますか?

CREATE TRIGGER prevent_brute_force 
AFTER INSERT ON login_att 
FOR EACH ROW 
BEGIN 
    SELECT ip_add, was_success INTO @ip, @result 
    FROM login_att 
    ORDER BY login_att_id DESC LIMIT 1;

    SELECT ip_add INTO @check_ip 
    FROM login_att 
    WHERE login_att_time > DATE_SUB(NOW(), INTERVAL 3 MINUTE) 
      AND ip_add = @ip 
    HAVING COUNT(ip_add) > 4;

    IF @check_ip IS NOT NULL 
    THEN 
        IF @result = 0
        THEN
            INSERT INTO blacklisted_ips (ip_add) VALUES (@ip); 
        END IF;
    END IF;

    SELECT username_att into @username_att 
    FROM login_att 
    WHERE login_att_time > DATE_SUB(NOW(), INTERVAL 2 MINUTE) 
      AND was_success=0 HAVING COUNT(username_att) > 3;

    IF @username_att IS NOT NULL
    THEN
        INSERT INTO blacklisted_users (username) VALUES (@username_att);
    END IF;
END$$
4
Adam McGurk

パフォーマンスを評価する最良の方法は、それを測定することです。実際のアプリケーションで、またはさらに優れた方法として、トラフィックのコピーまたはそのエミュレーションを備えたステージング環境でそれを評価できるのはあなただけです。

ハードウェア、実行中の他のコード、スループット、これらの新しいクエリの速度、所有しているデータの量などから、知りたいことがわかります。つまり、同じコードがさまざまな状況で成功したり壊れたりする可能性があるということです。

とは言っても、システムについてあまり知らなくても、アイデアの高水準の意見が機能する場合は、通常、外部ログ(またはlogin_attテーブル)に基づいてこの種の分析を非同期で行います発生頻度が十分でない場合、通常のユーザーを罰したくない。また、トリガーは、アプリケーションロジックを処理するための私のお気に入りの方法ではありません。ただし、ソースコードを変更できない場合は、レイテンシの合計に大きな影響はありません。テストして問題がないように見えますが、何千回も並行して試行してもアプリケーションが壊れないかどうかテストしてください。余分な書き込みのため、毎秒。

3
jynus

それは問題ではありません。

有効なログインとは、ユーザーがシステムで行った作業全体のごく一部です。したがって、その「小さな」割合が増加しても、それはまだ「小さな」影響です。

その間、誰がハッカーで何が起こるか気にしています。

オーバーヘッドに関しては、マイナーになります。

3
Rick James

@RickJamesは良い点だと思いますが、とにかくトリガーを少しでも最適化したい場合は、いくつか注意点があります。

  1. MySQLトリガー(および保存されたルーチンとイベント)は、実行されるたびに解析されます。つまり、コンパイルされたコードよりも遅くなるか、少なくとも遅くなる可能性があります。 (ただし、データベース内ですべてのコードを実行すると、データベース内でデータを送受信するのに時間がかかるため、アプリケーションで制御フローを実行し、データベースでSQLを実行するよりも高速になる場合があります。)同じセッション)トリガーまたはストアドルーチン内で保存され、後で再利用されます。IFステートメントは毎回完全に再解析されるため、回避することをお勧めしますが、もちろん必要な場合もあります。あなたの場合、IFsなしでコードを機能させる方法がよくわかりません。
  2. 最初のSELECTは不要です。 AFTER INSERTトリガー列名に接頭辞NEWを使用して、挿入された行の値にアクセスできるため、次のようになります。NEW.ip_addNEW.was_successは、ここで必要な値を提供します。
  3. ネストされたIFステートメント(IF @check_ip ... THEN IF @result = 0 THEN)、あなたは単にIF @check_ip IS NOT NULL AND NEW.was_success = 0 THEN
2
dbdemon