我們知道事務(wù)是維護(hù)數(shù)據(jù)庫完整性的一個非常好的方法,但卻因為它的獨占性,有時會影響數(shù)據(jù)庫的性能,尤其是在很大的應(yīng)用系統(tǒng)中。由于在事務(wù)執(zhí)行的過程中,數(shù)據(jù)庫將會被鎖定,因此其它的用戶請求只能暫時等待直到該事務(wù)結(jié)束。如果一個數(shù)據(jù)庫系統(tǒng)只有少數(shù)幾個用戶來使用,事務(wù)造成的影響不會成為一個太大的問題;但假設(shè)有成千上萬的用戶同時訪問一個數(shù)據(jù)庫系統(tǒng),例如訪問一個電子商務(wù)網(wǎng)站,就會產(chǎn)生比較嚴(yán)重的響應(yīng)延遲。
其實,有些情況下我們可以通過鎖定表的方法來獲得更好的性能。下面的例子就用鎖定表的方法來完成
LOCK TABLE inventory WRITE SELECT Quantity FROM inventory WHERE Item='book';
...
UPDATE inventory SET Quantity=11 WHERE Item='book'; UNLOCKTABLES
這里,我們用一個select語句取出初始數(shù)據(jù),通過一些計算,用update語句將新值更新到表中。包含有WRITE關(guān)鍵字的LOCKTABLE語句可以保證在UNLOCKTABLES命令被執(zhí)行之前,不會有其它的訪問來對inventory進(jìn)行插入、更新或者刪除的操作。
PHP操作PDO實現(xiàn)縮機(jī)制
$pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456'); $pdo->beginTransaction();//開啟事務(wù) $sql="select `number` from storage where id=1 for UPDATE ";//利用for update 開啟行鎖 $res = $pdo->query($sql)->fetch(); $number = $res['number']; if($number>0) { $sql ="insert into `order` VALUES (null,$number)"; $order_id = $pdo->query($sql); if($order_id) { $sql="update storage set `number`=`number`-1 WHERE id=1"; if($pdo->query($sql)) { $pdo->commit();//提交事務(wù) } else { $pdo->rollBack();//回滾 } } else { $pdo->rollBack();//回滾 } }