MySQLデータベースの非個人化。 興味深いテクニック

画像



私が働いている会社では、Production-aで非個人化されたベースを使用しています。 現時点での総容量は約30 GBです。 難読化Rubyスクリプトは約6時間かかりました。 これをすべてストアドプロシージャに書き換えることで、処理を高速化できます。 しかし、私たちのプロジェクトでは、彼らは禁止されています...ああ、ああ。



それから私は疑問に思った:1つの更新ステートメントのみを使用して、プロセスを最大まで高速化し、データベース全体(または少なくとも1つのテーブル)を非個人化することは可能ですか? 問題は、いくつかのフィールドが リストの一意の値といくつかのランダムな値。





それができたことがわかった。 少し考えて、ソリューションはカスタム変数、擬似乱数ジェネレーター、およびcaseステートメントを思い付きました。



以下にコードと説明を示します。



フィールドを持つユーザーテーブルがあるとします。



性別

last_name

address_1

address_2

home_phone

生年月日

ssn

パスワード



難読化後:

first_name女性パトリシア、テイラー、スーザン、リサ、リンダ、サンドラ、キャロル、デブラ、テレサ、レベッカ、ダイアナ、ヴェロニカ、ヘレン、アレクサンドラ、スヴェトラーナ、エロナ、マリーナ、ミラ、オルガ、ヴァシリサ、マルタ

男性-デビッド、ジョン、ロバート、スティーブン、ウィリアム、マーク、トーマス、マイケル、リチャード、ケビン、ドナルド、アンドリュー、ラスラン、ユージン、セルゲイ、アレクサンダー、ユラ、イワン、ダニエル

性別:変更なし

last_name:ジョンソン、アンダーソン、リード、エリクソン、フランク、ルーカス、ジェンキンス、ワトソン、モーガン、キム、コヴァリネン、コノバロフ、テレシコ、ウルチク、クレショフ、キスリアコフ、アレシュニク、ペカール、マトロスキン、ギャラガー

address_1: 123 Main Street

address_2:オリジナルに何もない場合、難読化後はNULLでなければなりません。そうでない場合、住所は123 Main Streetです

home_phone:オリジナルに何もない場合、難読化後にNULLになります。それ以外の場合は、電話111-111-2222

生年月日:生年月日をそのままにして、日付と月を変更します

ssn: 「30」で始まる各行に固有のランダムな9文字の値

パスワード: NULL



解決策:

SET @rand = 276821; UPDATE users SET first_name= CASE WHEN gender='F' || gender='f' THEN ELT(FLOOR(1+RAND() * 21), 'Patricia', 'Taylor', 'Susan', 'Lisa', 'Linda', 'Sandra', 'Carol', 'Debra', 'Teresa', 'Rebecca', 'Diana', 'Veronika', 'Helen', 'Alexandra', 'Svetlana', 'Elona', 'Marina', 'Mila', 'Olga', 'Vasilisa', 'Marta') ELSE ELT(FLOOR(1+RAND() * 19), 'David', 'John', 'Robert', 'Steven', 'William', 'Mark', 'Thomas', 'Michael', 'Richard', 'Kevin', 'Donald', 'Andrew', 'Ruslan', 'Eugene', 'Sergey', 'Alexandr', 'Yura', 'Ivan', 'Daniel') END, last_name = ELT(FLOOR(1+RAND() * 20), 'Johnson', 'Anderson', 'Reed', 'Erickson', 'Frank', 'Lucas', 'Jenkins', 'Watson', 'Morgan', 'Kim', 'Kovalinen', 'Konovalov', 'Tereshko', 'Urchik', 'Kuleshov', 'Kisliakov', 'Areshnik', 'Pekar', 'Matroskin', 'Gallagher'), address_1 = '123 Main Street', address_2 = CASE WHEN address_2 is not null THEN 'Apt. 14' ELSE null END, home_phone = CASE WHEN home_phone is not null THEN '111-111-2222' ELSE null END, birthdate = CASE WHEN birthdate is not null THEN MAKEDATE(YEAR(birthdate),FLOOR(RAND()*365)) ELSE null END, ssn = CASE WHEN ((@rand + 609673) % 1048576 <> 0) && ((@rand + 609673) % 1048576 <> 1000000) THEN CONCAT('30',LPAD(@rand:=(@rand + 609673) % 1048576,7,'0')) ELSE CONCAT('30',LPAD(@rand:=(@rand + 609673*2) % 1048576,7,'0')) END, password = null;
      
      







コードからわかるように、ELT(FLOOR(1 + RAND()* 21)、...)を使用してリストからランダムな値を選択できます。ここで、FLOOR(1 + RAND()* 21)は1〜 21. ELT-指定されたインデックスを持つ適切なドレインを選択します。



CASEは、性別ごとに男性と女性の名前を別々に選択するのに役立ちます。 4つのCASE、IF、IFNULL()、NULLIF()など、進行状況を制御する関数があり、個別のステートメントで使用できます。



まだ言及する価値があるものから、それは一意の値のランダムな値ジェネレータです。 素数(276821)がジェネレーターの初期値として選択され、ユーザー変数randに書き込まれました。 次の値は、CASEステートメントで直接設定されます。rand:=( rand + 609673 * 2)%1048576。式CONCAT( '30'、LPAD( rand 、7、 '0'))は、 rand値の最終形式を形成します。



結論:

このようにして、基地の非個人化によって何を達成しましたか?

1)実行速度が6時間から4分に減少しました。

2)ストアドプロシージャは使用されません。

3)作業の明確な(複雑ではない)ロジックとすべてのコードが1か所に収集されます。



All Articles