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