2011-08-25 25 views
3

我正在開發用PHP編寫的Web應用程序的更新系統。在更新過程中,我可能需要執行一堆MySQL腳本。使用mysqli_multi_query和事務運行多個查詢

的基本進程來運行這些腳本是:

  1. 搜索Mysql的腳本
  2. 開始事務
  3. 執行每個腳本mysqli_multi_query因爲腳本可以包含多個查詢
  4. 如果一切OK OK COMMORT事務,否則ROLLBACK。

我的代碼看起來是這樣的:

$link = mysqli_connect(...); 

mysqli_autocommit($link, false); 

// open dir and search for scripts in file. 
// $file is an array with all the scripts 
foreach ($scripts as $file) { 

    $script = trim(file_get_contents($scriptname)); 

    if (mysqli_multi_query($link, $script)) { 
     while (mysqli_next_result($link)) { 
      if ($resSet = mysqli_store_result($link)) { mysqli_free_result($resSet); } 

      if (mysqli_more_results($link)) { } 
     } 
    } 

    // check for errors in any query of any script 
    if (mysqli_error($link)) { 
     mysqli_rollback($link); 
     return; 
    } 
} 
mysqli_commit($link); 

下面是腳本的例子(用於演示目的):

script.1.5.0.0.sql: 
update `demo` set `alias` = 'test1' where `id` = 1; 
update `users` set `alias` = 'user1' where `id` = 1; 

script 1.5.1.0.sql: 
insert into `users`(id, key, username) values(3, '100', 'column key does not exist'); 
insert into `users`(id, key, username) values(3, '1', 'column key exists'); 

在這種情況下,腳本1.5.0.0將執行無錯誤和腳本1.5.1.0會產生錯誤(爲了演示目的,假設列key是唯一的,並且已經有一行key = 1)。

在這種情況下,我想回滾執行的每個查詢。但是會發生什麼情況是1.5.1.0的第一次插入不在數據庫中(正確),但1.5.0.0的更新已成功執行。

備註:

  1. 我的第一選擇是分拆從每個腳本每次查詢「」並獨立執行查詢。這是不是一種選擇,因爲我必須要能夠插入HTML代碼的數據庫(例如:如果我想要插入像「& NBSP;」)
  2. 我已經StackOverflow的搜索和谷歌遇到像解決方案來this one但我寧願使用像mysqli_multi_query這樣的解決方案,而不是使用函數來分割每個查詢。它更容易理解和調試
  3. 我還沒有測試過它,但我相信我可以合併所有腳本並執行一個查詢。但是,一次執行一個腳本是非常有用的,這樣我就可以找出哪個腳本有錯誤。
  4. 表引擎是InnoDB。

欣賞如果你能指出某種方式來完成這項工作。

回答

0

好的,花了一天的時間調試後,我發現了這個問題。

其實,它無關的代碼本身或與mysqli的功能。我習慣於支持DDL語句的MS SQL事務。 MySQL不支持DDL語句並隱式提交數據(Implicit commit)。我在其中一個自動提交數據的腳本中有一個DROP表。

2

編輯:mysqli_multi_query()只返回false如果第一查詢失敗。如果第一個查詢沒有失敗,那麼你的代碼將運行mysql_store_result(),如果成功將會使mysqli_error()爲空。你需要檢查之後的錯誤,每 mysqli函數可以成功或失敗。

+1

我已經在使用InnoDB了。對不起,沒有提到它的問題,我現在添加了這些信息。 –

+0

@milz我已經更新了一個基於已經使用InnoDB的解決方案 – regality