<?php
$conn
=mysql_connect(
"localhost"
,
"big"
,
"123456"
);
if
(!
$conn
){
echo
"connect failed"
;
exit
;
}
mysql_select_db(
"big"
,
$conn
);
mysql_query(
"set names utf8"
);
$price
=10;
$user_id
=1;
$goods_id
=1;
$sku_id
=11;
$number
=1;
//生成唯一訂單
function
build_order_no(){
return
date
(
'ymd'
).
substr
(implode(NULL,
array_map
(
'ord'
,
str_split
(
substr
(uniqid(), 7, 13), 1))), 0, 8);
}
//記錄日志
function
insertLog(
$event
,
$type
=0){
global
$conn
;
$sql
="insert into ih_log(event,type)
values(
'$event'
,
'$type'
)";
mysql_query(
$sql
,
$conn
);
}
//模擬下單操作
//庫存是否大於0
$sql
=
"select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'"
;
//解鎖 此時ih_store數據中goods_id='$goods_id' and sku_id='$sku_id' 的數據被鎖住(注3),其它事務必須等待此次事務 提交后才能執行
$rs
=mysql_query(
$sql
,
$conn
);
$row
=mysql_fetch_assoc(
$rs
);
if
(
$row
[
'number'
]>0){
//高並發下會導致超賣
$order_sn
=build_order_no();
//生成訂單
$sql
="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(
'$order_sn'
,
'$user_id'
,
'$goods_id'
,
'$sku_id'
,
'$price'
)";
$order_rs
=mysql_query(
$sql
,
$conn
);
//庫存減少
$sql
=
"update ih_store set number=number-{$number} where sku_id='$sku_id'"
;
$store_rs
=mysql_query(
$sql
,
$conn
);
if
(mysql_affected_rows()){
insertLog(
'庫存減少成功'
);
}
else
{
insertLog(
'庫存減少失敗'
);
}
}
else
{
insertLog(
'庫存不夠'
);
}
?>.
<?php
$conn
=mysql_connect(
"localhost"
,
"big"
,
"123456"
);
if
(!
$conn
){
echo
"connect failed"
;
exit
;
}
mysql_select_db(
"big"
,
$conn
);
mysql_query(
"set names utf8"
);
$price
=10;
$user_id
=1;
$goods_id
=1;
$sku_id
=11;
$number
=1;
//生成唯一訂單號
function
build_order_no(){
return
date
(
'ymd'
).
substr
(implode(NULL,
array_map
(
'ord'
,
str_split
(
substr
(uniqid(), 7, 13), 1))), 0, 8);
}
//記錄日志
function
insertLog(
$event
,
$type
=0){
global
$conn
;
$sql
="insert into ih_log(event,type)
values(
'$event'
,
'$type'
)";
mysql_query(
$sql
,
$conn
);
}
//模擬下單操作
//庫存是否大於0
mysql_query(
"BEGIN"
);
//開始事務
$sql
=
"select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id' FOR UPDATE"
;
//此時這條記錄被鎖住,其它事務必須等待此次事務提交后才能執行
$rs
=mysql_query(
$sql
,
$conn
);
$row
=mysql_fetch_assoc(
$rs
);
if
(
$row
[
'number'
]>0){
//生成訂單
$order_sn
=build_order_no();
$sql
="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values(
'$order_sn'
,
'$user_id'
,
'$goods_id'
,
'$sku_id'
,
'$price'
)";
$order_rs
=mysql_query(
$sql
,
$conn
);
//庫存減少
$sql
=
"update ih_store set number=number-{$number} where sku_id='$sku_id'"
;
$store_rs
=mysql_query(
$sql
,
$conn
);
if
(mysql_affected_rows()){
insertLog(
'庫存減少成功'
);
mysql_query(
"COMMIT"
);
//事務提交即解鎖
}
else
{
insertLog(
'庫存減少失敗'
);
}
}
else
{
insertLog(
'庫存不夠'
);
mysql_query(
"ROLLBACK"
);
}
?>
<?php
$conn=mysql_connect("localhost","root","123456");
if(!$conn){
echo "connect failed";
exit;
}
mysql_select_db("big-bak",$conn);
mysql_query("set names utf8");
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
//生成唯一訂單號
function build_order_no(){
return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//記錄日志
function insertLog($event,$type=0){
global $conn;
$sql="insert into ih_log(event,type)
values('$event','$type')";
mysql_query($sql,$conn);
}
$fp = fopen("lock.txt", "w+");
if(!flock($fp,LOCK_EX | LOCK_NB)){
echo "系統繁忙,請稍后再試";
return;
}
//下單
$sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
if($row['number']>0){//庫存是否大於0
//模擬下單操作
$order_sn=build_order_no();
$sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values('$order_sn','$user_id','$goods_id','$sku_id','$price')";
$order_rs=mysql_query($sql,$conn);
//庫存減少
$sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
$store_rs=mysql_query($sql,$conn);
if(mysql_affected_rows()){
insertLog('庫存減少成功');
flock($fp,LOCK_UN);//釋放鎖
}else{
insertLog('庫存減少失敗');
}
}else{
insertLog('庫存不夠');
}
fclose($fp);
第四種,使用redis隊列
<?php
$store
=1000;
$redis
=
new
Redis();
$result
=
$redis
->connect(
'127.0.0.1'
,6379);
$res
=
$redis
->llen(
'goods_store'
);
echo
$res
;
$count
=
$store
-
$res
;
for
(
$i
=0;
$i
<
$count
;
$i
++){
$redis
->lpush(
'goods_store'
,1);
}
echo
$redis
->llen(
'goods_store'
);
?>
