abstrak:數(shù)據(jù)庫的事務(wù)處理可以保證一組處理結(jié)果的正確性。mysql中只有INNODB和BDB引擎的數(shù)據(jù)表才支持事務(wù)處理,對于不支持事務(wù)的MyISAM引擎數(shù)據(jù)庫可以使用表鎖定的方法來實(shí)現(xiàn)相同的功能。 mysql的事務(wù)處理主要有兩種方法來實(shí)現(xiàn)?! ?、用begin,rollback,commit來實(shí)現(xiàn)。 begin 開始一個事務(wù) rollback 事務(wù)回滾 commit 事務(wù)確認(rèn) Php代碼$conn
數(shù)據(jù)庫的事務(wù)處理可以保證一組處理結(jié)果的正確性。mysql中只有INNODB和BDB引擎的數(shù)據(jù)表才支持事務(wù)處理,對于不支持事務(wù)的MyISAM引擎數(shù)據(jù)庫可以使用表鎖定的方法來實(shí)現(xiàn)相同的功能。
mysql的事務(wù)處理主要有兩種方法來實(shí)現(xiàn)。
1、用begin,rollback,commit來實(shí)現(xiàn)。
begin 開始一個事務(wù)
rollback 事務(wù)回滾
commit 事務(wù)確認(rèn)
Php代碼
$conn = mysql_connect('localhost','root','root') or die ("數(shù)據(jù)連接錯誤!!!"); mysql_select_db('test',$conn); mysql_query("set names 'utf8'"); //開始一個事務(wù) mysql_query("BEGIN"); //或者mysql_query("START TRANSACTION"); $sql = "INSERT INTO `t_user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $sql2 = "INSERT INTO `t_user` (`did`, `username`, `sex`) VALUES (NULL, 'test1', '0')";//這條是故意寫錯 $res = mysql_query($sql); $res1 = mysql_query($sql2); if($res && $res1){ mysql_query("COMMIT"); echo '提交成功。'; }else{ mysql_query("ROLLBACK"); echo '數(shù)據(jù)回滾。'; } mysql_query("END");
2、直接用set來改變mysql的自動提交模式
MYSQL默認(rèn)是自動提交的,也就是你提交一個QUERY,它就直接執(zhí)行!我們可以通過
set autocommit=0 禁止自動提交
set autocommit=1 開啟自動提交
Php代碼
$conn = mysql_connect('localhost','root','root') or die ("數(shù)據(jù)連接錯誤!!!"); mysql_select_db('test',$conn); mysql_query("set names 'utf8'"); mysql_query("SET AUTOCOMMIT=0"); //設(shè)置mysql不自動提交,需自行用commit語句提交 $sql = "INSERT INTO `t_user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $sql2 = "INSERT INTO `t_user` (`did`, `username`, `sex`) VALUES (NULL, 'test1', '0')";//這條故意寫錯 $res = mysql_query($sql); $res1 = mysql_query($sql2); if($res && $res1){ mysql_query("COMMIT"); echo '提交成功。'; }else{ mysql_query("ROLLBACK"); echo '數(shù)據(jù)回滾。'; } mysql_query("END"); //事務(wù)處理完時別忘記mysql_query("SET AUTOCOMMIT=1");自動提交
對于不支持事務(wù)的MyISAM引擎數(shù)據(jù)庫可以使用表鎖定的方法來實(shí)現(xiàn)
MyISAM & InnoDB 都支持,LOCK TABLES可以鎖定用于當(dāng)前線程的表。如果表被其它線程鎖定,則造成堵塞,直到可以獲取所有鎖定為止。UNLOCK TABLES可以釋放被當(dāng)前線程保持的任何鎖定。當(dāng)線程發(fā)布另一個LOCK TABLES時,或當(dāng)與服務(wù)器的連接被關(guān)閉時,所有由當(dāng)前線程鎖定的表被隱含地解鎖。
Php代碼
mysql_query("LOCK TABLES `t_user` WRITE");//鎖住`user`表 $sql = "INSERT INTO `t_user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $res = mysql_query($sql); if($res){ echo '提交成功。!'; }else{ echo '失敗!'; } mysql_query("UNLOCK TABLES");//解除鎖定
如果操作表比較多,采用斷點(diǎn)調(diào)試的時候,在事務(wù)處理完成之前(COMMIT)查看數(shù)據(jù)庫的相關(guān)表是看不到表中數(shù)據(jù)的變化的。
下面是在mysql存儲過程中使用事務(wù)處理的一個例子。
Java代碼
CREATE PROCEDURE TransTest(in p1 VARCHAR(20),in p2 VARCHAR(50)) BEGIN declare err int default 0; /*如果出現(xiàn)sql異常,則將err設(shè)置為1后繼續(xù)執(zhí)行后面的操作 */ declare continue handler for sqlexception set err=1; -- 出錯處理 set autocommit = 0; insert into sy_queryconfig(syq_id) values(p1); insert into sy_queryconfig(syq_id) values(p2); if err=1 then ROLLBACK; ELSE COMMIT; end if; END
PS:附加一個mysql數(shù)據(jù)庫在delete表數(shù)據(jù)的時候,不能用別名操作,例如:
delete from t_user where id in (1,2);//此寫法正確delete from t_user t where t.id in (1,2);//此寫法錯誤
mysql就是這么任性!