PHP Generate ID for MySQL อย่างไรไม่ให้ คีย์ซ้ำกัน โดยไม่ใช้ AUTO_INCREMENT ของ MySQL #1
สวัสดีเพื่อนๆชาว Developer นะครับ วันนี้ผมมาแนะนำวิธีการ
Generate ID โดย PHP อย่างไรไม่ให้ Key ซ้ำกัน โดยที่เราไม่ใช้ความสามารถของ MySQL (AUTO_INCREMENT)
เหตุที่ผมไม่ใช้ AUTO_INCREMENT ก็เพราะว่า ผมต้องการที่จะได้ ID สวยๆ เช่น1702-0000001, 1702-0000002, 1702-0000003 และจะ Reset ID กลับไปเป็น 1 ใหม่ทุกๆ เดือน แบบนี้รับรองว่า ใช้ Application ที่เราเขียนเป็นชาติ ก็ไม่มีคีย์ซ้ำครับ
วิธีการทำผมขอยกมานำเสนอ 2 วิธีได้แก่
1.) ใช้ semaphore ของ PHP ซึ่งจะมีตั้งแต่ PHP เวอร์ชั่น 4 ขึ้นไปครับ
2.) ใช้การเขียนไฟล์แบบ Exclusive คือ LOCK ไฟล์ให้เขียนเฉพาะ Thread ปัจจุบันให้เสร็จก่อนแล้วค่อยให้ Thread อื่นๆทำงาน โดยการจัด Queue (คิว) ลำดับก่อนหลัง (First in first out)
สำหรับ Post นี้ผมจะเสนอวิธีที่ 1 ให้ก่อน
Code (PHP)
$semaphoreId= sem_get('100200300', 1, 0666, 0); // or die('Cannot create semaphore');
if(!$semaphoreId){
echo "Cannot create semaphore";exit;
}
//----- Set Exclusive process ต้องการให้ทำงานได้ทีล่ะ Thread และจัด Queue ในการเข้ามาทำงาน หรือ First In First Out (FIFO)
sem_acquire($semaphoreId);
//----- ส่วนด้านล่างนี้คือโค้ดที่เราต้องการเขียน Blabla ว่าไป ยกตัวอย่างเช่น
//----- ผมสร้างตารางไว้ชื่อ tb_genkey
$resource = mysql_connect('localhost', 'DB_USER', DB_PASSWORD) or die('Not connect ...');
mysql_select_db('test', $resource);
$rs = mysql_query("select keyValue FROM tb_genkey WHERE keyId = 'tb_transaction.tranId';");
$keyId = 1;
if(mysql_num_rows($rs) === 0){
mysql_query("INSERT INTO tb_genkey VALUES('tb_transaction.tranId', 1);");
}else{
$row = mysql_fetch_assoc($rs);
$keyId = intval($row['keyValue']);
$keyId++;
mysql_query("UPDATE tb_genkey SET keyValue={$keyId} WHERE keyId = 'tb_transaction.tranId';");
}
$keyResult = sprintf("TRAN-%07d", $keyId);
$handle = fopen(dirname(__FILE__) . '/genId.txt', 'a');
fwrite($handle, "{$keyResult}\n");
fclose($handle);
echo $keyResult;
//----- เสร็จแล้วสั่ง Release thread ที่ทำงานอยู่เพื่อให้ Thread ต่อไปที่เข้าคิว มาทำงานต่อ
sem_release($semaphoreId);
Tag : PHP
Date :
2017-02-27 12:47:56
By :
takky12345
View :
7013
Reply :
9
จัดไปครับ
Date :
2017-02-27 15:49:15
By :
mr.win
ยอดเยี่ยมครับ
Date :
2017-02-28 09:10:09
By :
itloei
ลืม SQL สำหรับสร้างตารางด้วยครับ
Date :
2017-02-28 09:23:34
By :
mr.win
หลักการเดียวกับทำ auto increment ใน oracle หรือเปล่า??
Date :
2017-02-28 10:09:32
By :
ห้ามตอบเกินวันละ 2 กระทู้
สำหรับคำสั่งในการสร้าง ตารางนะครับ
Code (SQL)
CREATE TABLE `tb_genkey` (
`keyId` varchar(100) NOT NULL,
`keyValue` bigint(20) DEFAULT '1',
UNIQUE KEY `keyId` (`keyId`)
) ENGINE=InnoDB collate utf8-bin DEFAULT CHARSET=utf8;
ขอเพิ่มเติมสำหรับการใช้ DB ENGINE ของแต่ละตารางครับ
1.) InnoDB DB ENGINE ตัวนี้เราสามารถเปิด Transaction ในการทำ INSERT/UPDATE/DELETE ได้และจะมีการ Validate พวกความยาวตัวอักษรให้เรา (หากเกินจะเกิด SQL Exception)
Code (SQL)
START TRANSACTION;
-- Bla bla
COMMIT;
2.) MyISAM DB ENGINE ตัวนี้เราเปิด Transaction ไม่ได้ และจะไม่ Validate ความยาวตัวอักษรให้เรา โดยมันจะตัดทิ้งส่วนที่เกินขนาดของ Field ที่เรา Defined เอาไว้
เด่วในกระทู้หน้าผมจะ เอาอีกวิธีการทำ Lock Thread ในวิธีที่สอง มาโพสให้ครับ ผมหาเวลาว่างๆก่อน ตอนนี้ผมเขียน Script ไว้แล้ว และจะมาบอกวิธีการทดสอบโดยใช้ AB (Apache Benchmark) ในการยิงทดสอบว่า Script เรา Lock Thread จริงไหม
Date :
2017-02-28 12:33:26
By :
takky12345
ว่างๆ เดียวจะแชร์ให้ครับ (ตามคิวครับ)
Date :
2017-02-28 13:11:58
By :
mr.win
เยี่ยมเลยครับ
Date :
2017-04-11 16:11:00
By :
tkaj_krit
Date :
2017-04-11 20:45:38
By :
คนมีเสน่ห์
Load balance : Server 05