ชุดสคลิ๊ป สำหรับทดสอบการยิงข้อมูลเข้าฐานข้อมูล แล้วเกินกว่าค่า limit ที่ตั้งไว้
ที่มา
.. ไปพบระบบฐานข้อมูลของโรงเรียนแห่งหนึ่ง ที่เปิดให้ลงวิชาเพิ่มเติมแบบออนไลน์ แล้วจำกัดจำนวนนักเรียนไว้ 60 คนต่อวิชา
กลุ่มเป้าหมายคือมีนักเรียน 700 คนเข้าใช้ระบบพร้อมกัน พบว่า นักเรียนคลิ๊กลงเรียนวิชาเพิ่มเติม
แล้วระบบรับนักเรียนเกินกว่าที่กำหนดไปถึง 10 คน ก็แสดงว่าระบบไม่ได้ป้องกันการเข้าถึงพร้อมกันจากหลายร้อยคน
ทำให้ข้อมูลที่เข้ามาพร้อม ๆ กันเกินกว่าที่กำหนดไว้ จึงนำโจทย์นี้มาทำให้เกิดขึ้นแบบที่เห็น แล้วก็เพิ่ม code ไป 2 บรรทัดเพื่อป้องกัน
กระบวนการทดสอบ
.. เริ่มจากสร้าง batch file ทั้งหมด 4 แฟ้ม เพื่อช่วยสร้าง .php บนเครื่องที่ติดตั้ง xampp web server จะได้สะดวกในการทดสอบ
ถ้าใช้ IE8 เวลาคลิ๊ป batch file จะเลือกประมวลผลได้ทันที แต่ถ้าเป็น firefox หรือ chrome ต้อง save ลงเครื่องแล้วประมวลผล
สำหรับแฟ้ม .php แต่ละแฟ้ม มีหน้าที่ดังนี้
1. สร้าง crt_db_tb.php เพื่อให้สร้างฐานข้อมูล และสร้างตาราง ไปพร้อมกับการทำหน้าที่ล้างข้อมูลในตาราง รองรับการทดสอบซ้ำหลาย ๆ รอบ
2. สร้าง insert_tb.php เพื่อใช้เพิ่มข้อมูลเข้าตารางเป้าหมาย ซึ่งคำสั่งชุดนี้จะทำงานเสร็จสิ้นอย่างรวดเร็ว ไม่ช้าอย่างที่อยากให้เกิดขึ้น หากถูกเรียกพร้อมกันจากหลายคน
3. สร้าง insert_tb10.php เพื่อใช้เพิ่มข้อมูลทีละระเบียน แบบตรวจสอบจำนวนระเบียนก่อนเพิ่มข้อมูล เป็นค่า limit ซึ่ง code ที่ใช้งานจริงมักมีขนาดใหญ่ และอาจหน่วงเวลา จึงเพิ่มคำสั่ง for สำหรับทำซ้ำ ให้โปรแกรมทดสอบนี้ โดยแยกกันระหว่างส่วนรับจำนวนระเบียน และส่วนเพิ่มระเบียน จะได้เห็นปัญหาได้ชัดเจน
4. สร้าง include_15.php เพื่อใช้เรียก insert_tb10.php โดยเรียกผ่าน iframe จำนวน 15 หน้าต่าง แต่ถ้าเรียกผ่าน browser หน้าเดียวจะไม่พบปัญหา เพราะมีการจัดลำดับการประมวลผล ทำให้การเข้าถึงฐานข้อมูลไม่มีการแซงกัน ต้องเรียกผ่าน browser คนละค่าย หรือเรียก browser ที่มี PID แยกกัน
ที่ไป
จากการทดสอบเรียก include_15.php ใน 2 browser พบว่าการตรวจสอบค่าในครั้งที่ 10 เกิดข้อผิดพลาด ทำให้บางครั้งข้อมูลเข้าในระบบจำนวน 11 ระเบียน ถ้าป้องกันการเข้าถึงพร้อมกันต้องเรียกใช้ lock tables mytable write และ unlock tables หลังการเรียกใช้ผลปรากฎว่า แต่ละ browser จะเข้าถึง include_15.php พร้อมกันไม่ได้ ต้องเข้าทีละ iframe ทำให้ผลที่ปรากฎคือ การประมวลผลจะเลื่อนไหลไปทีละช่อง และสลับ browser ในการประมวลผล แบบค่อยเป็นค่อยไป ไม่รวดเร็วแต่ถูกต้อง
|
1. Batch file : DOS> crt_db_tb.bat
หลังประมวลผลจะได้แฟ้มแบบ php file ใน C:\xampp\htdocs\ ชื่อ crt_db_tb.php
แล้วสั่งประมวลผลบน browser ชี้ address ไปที่ http://localhost/crt_db_tb.php |
| del C:\xampp\htdocs\crt_db_tb.php | echo y
echo ^<?php > C:\xampp\htdocs\crt_db_tb.php
echo $host = "127.0.0.1:3306"; >> C:\xampp\htdocs\crt_db_tb.php
echo $uname = "root"; >> C:\xampp\htdocs\crt_db_tb.php
echo $passwd = ""; >> C:\xampp\htdocs\crt_db_tb.php
echo $connect=mysql_connect($host,$uname,$passwd); >> C:\xampp\htdocs\crt_db_tb.php
echo $sql = "create database mydb"; >> C:\xampp\htdocs\crt_db_tb.php
echo mysql_query($sql,$connect); >> C:\xampp\htdocs\crt_db_tb.php
echo mysql_select_db("mydb",$connect); >> C:\xampp\htdocs\crt_db_tb.php
echo $sql="create table mytable (eid char(4),ename char(40),esalary int)"; >> C:\xampp\htdocs\crt_db_tb.php
echo if (!$result=mysql_query($sql,$connect)) { echo "it already had"; >> C:\xampp\htdocs\crt_db_tb.php
echo $sql="delete from mytable"; >> C:\xampp\htdocs\crt_db_tb.php
echo if (!$result=mysql_query($sql,$connect)) echo "error"; else echo "<br/>del all rec."; >> C:\xampp\htdocs\crt_db_tb.php
echo } else echo "db and table creating : ok" >> C:\xampp\htdocs\crt_db_tb.php
echo ?^> >> C:\xampp\htdocs\crt_db_tb.php
|
2. Batch file : DOS> insert_tb.bat
หลังประมวลผลจะได้แฟ้มแบบ php file ใน C:\xampp\htdocs\ ชื่อ insert_tb.php
แล้วสั่งประมวลผลบน browser ชี้ address ไปที่ http://localhost/insert_tb.php |
|
del C:\xampp\htdocs\insert_tb.php | echo y
echo ^<?php > C:\xampp\htdocs\insert_tb.php
echo $host = "127.0.0.1:3306"; >> C:\xampp\htdocs\insert_tb.php
echo $uname = "root"; >> C:\xampp\htdocs\insert_tb.php
echo $passwd = ""; >> C:\xampp\htdocs\insert_tb.php
echo $connect=mysql_connect($host,$uname,$passwd); >> C:\xampp\htdocs\insert_tb.php
echo mysql_select_db("mydb",$connect); >> C:\xampp\htdocs\insert_tb.php
echo $sql="insert into mytable (eid,ename,esalary) value ('1','tom',5)"; >> C:\xampp\htdocs\insert_tb.php
echo if (!$result=mysql_query($sql,$connect)) echo "error"; else echo "insert : ok" >> C:\xampp\htdocs\insert_tb.php
echo ?^> >> C:\xampp\htdocs\insert_tb.php
|
3. Batch file : DOS> insert_tb10.bat
หลังประมวลผลจะได้แฟ้มแบบ php file ใน C:\xampp\htdocs\ ชื่อ insert_tb10.php
แล้วสั่งประมวลผลบน browser ชี้ address ไปที่ http://localhost/insert_tb10.php |
| del C:\xampp\htdocs\insert_tb10.php | echo y
echo ^<?php > C:\xampp\htdocs\insert_tb10.php
echo $host = "127.0.0.1:3306"; >> C:\xampp\htdocs\insert_tb10.php
echo $uname = "root"; >> C:\xampp\htdocs\insert_tb10.php
echo $passwd = ""; >> C:\xampp\htdocs\insert_tb10.php
echo $connect=mysql_connect($host,$uname,$passwd); >> C:\xampp\htdocs\insert_tb10.php
echo mysql_select_db("mydb",$connect); >> C:\xampp\htdocs\insert_tb10.php
echo // mysql_query("lock tables mytable write",$connect); >> C:\xampp\htdocs\insert_tb10.php
echo $sql="select * from mytable"; >> C:\xampp\htdocs\insert_tb10.php
echo if (!$result=mysql_query($sql,$connect)) echo "error"; else { >> C:\xampp\htdocs\insert_tb10.php
echo if (mysql_num_rows($result) ^< 10) { >> C:\xampp\htdocs\insert_tb10.php
echo for($i=1;$i^<10000000;$i++) { $i += mysql_num_rows($result); } >> C:\xampp\htdocs\insert_tb10.php
echo $sql="insert into mytable (eid,ename,esalary) value ('1','tom',5)"; >> C:\xampp\htdocs\insert_tb10.php
echo if (!$result=mysql_query($sql,$connect)) echo "error"; else echo "insert : ok"; >> C:\xampp\htdocs\insert_tb10.php
echo } else { echo "over limit"; }// if >> C:\xampp\htdocs\insert_tb10.php
echo } // select >> C:\xampp\htdocs\insert_tb10.php
echo // mysql_query("unlock tables",$connect); >> C:\xampp\htdocs\insert_tb10.php
echo ?^> >> C:\xampp\htdocs\insert_tb10.php
|
4. Batch file : DOS> include_15.bat
หลังประมวลผลจะได้แฟ้มแบบ php file ใน C:\xampp\htdocs\ ชื่อ include_15.php
แล้วสั่งประมวลผลบน browser ชี้ address ไปที่ http://localhost/include_15.php
| | del C:\xampp\htdocs\include_15.php | echo y
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> > C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
echo ^<meta http-equiv="refresh" content="0;url=http://localhost/insert_tb10.php" /^> >> C:\xampp\htdocs\include_15.php
|
|