2010-04-29 60 views
1

這一直在困擾着我整天,沒有盡頭。 當我的php應用程序的用戶添加一個新的更新並出錯時,我需要能夠撤消一批覆雜的混合命令。他們可以是MySQL更新和插入查詢,文件刪除和文件夾重命名和創作。回滾文件移動,文件夾刪除和mysql查詢

我可以跟蹤所有插入命令的狀態,並在拋出錯誤時將其撤消。 但是,如何使用update語句來執行此操作? 是否有一種智能的方式(某些設計模式?)跟蹤文件結構和數據庫中的這些變化?

我的數據庫表是MyISAM。將所有東西都轉換成InnoDB很容易,這樣我就可以使用事務。這樣我就只需要處理文件和文件夾操作。 不幸的是,我不能認爲所有的客戶端都支持InnoDB。這還需要我將我數據庫中的很多表轉換爲InnoDB,我很猶豫。

+1

你所描述的正是交易的目的。我不明白「客戶支持」是什麼意思? – 2010-04-29 19:10:04

+0

我的意思是我不知道我的軟件的用戶是否在他們的服務器上啓用了InnoDB。我需要假設它已關閉。 – Workoholic 2010-04-29 19:23:47

回答

0

PDO的rowcount()返回更新中的eftected行。 mysqli的afftected_rows也一樣

我是客戶,你的意思是客戶的服務器,你將放置這個應用程序。如果你不需要在服務器上使用innoDB,你需要做更多的編碼來回滾MyISAM表上的變化。

最好的辦法是模塊化一切都變成函數(或類方法)

僞代碼:

function updateThisThing() { 

    if (!updateTable()) { 
     rollbackUpdateTable(); 
     return false; 
    } 

    if (!updateFiles()) { 
     rollbackUpdateFiles(); 
     return false; 
    } 

    // more update statements 

    return true 

} 
0

如果你是絕對套牢的MyISAM,你應該看到,如果代碼可以安排,以便更新是最後一件事情。如果在此之前發生錯誤,則不會進行更新。

如果這樣做不可行,則必須鎖定相關表格,抓取當前記錄並更新它們。如果出錯,則用抓取的記錄進行恢復。解鎖表格。

不是很實際,這就是爲什麼有InnoDB(如你所知)。

我覺得這是這個模塊,你可以檢查出的基礎:

http://www.deepbluesky.com/blog/-/myisam-transactions_20/

+0

是的,我發現之前的鏈接。不過,它不支持別名。 一些查詢依賴於以前查詢中的mysql插入id。所以我在移動他們時受到限制。 – Workoholic 2010-04-29 20:05:01

+0

我明白了。那麼,同樣的鎖定,保持,更新,恢復方法將適用。鎖定是必須的,所以其他人在此期間不會閱讀。它會減慢速度,但如果用戶寫入很少,您可能會擺脫困境。 – webbiedave 2010-04-29 20:09:32

0

你調查過Unit of Work模式?

下面是您如何開始的一個非常粗暴的例子。

基本的UnitOfWork容器。

class UnitOfWork 
{ 
    protected $entities = array(); 
    protected $completed = array(); 

    final public function addEntity(IWorkUnitEntity $entity) 
    { 
    $this->entities[] = $entity; 
    } 

    final public function execute() 
    { 
    try { 
     foreach ($this->entities as $entity) 
     { 
     $entity->execute(); 
     $completed[] = $entity; 
     } 
    } 
    catch (UnitOfWorkRollbackException $e) 
    { 
     $this->rollbackCompleted(); 
    } 

    return $this->commitAll(); 
    } 

    protected function rollbackCompleted() 
    { 
    while ($entity = array_pop($this->completed)) 
    { 
     $entity->rollback(); 
    } 
    } 

    protected function commitAll() 
    { 
    try { 
     foreach ($this->entities as $entity) 
     { 
     $entity->commit(); 
     } 
    } 
    catch (UnitOfWorkRollbackException $e) 
    { 
     $this->rollbackCompleted(); 
     return false; 
    } 
    return true; 
    } 
} 

幾個演員來幫助它一起

class UnitOfWorkRollbackException extends Exception {}; 

interface IWorkUnitEntity 
{ 
    public function execute(); 
    public function rollback(); 
} 

現在,一個工作實體

class FileMoverEntity implements IWorkUnitEntity 
{ 
    protected 
     $source 
    , $destination 
    , $newName 
    ; 

    public function __construct($source, $destination, $newName = null) 
    { 
    $this->source = $source; 
    $this->destination = dirname($destination); 
    $this->newName = $newName; 
    } 

    public function execute() 
    { 
    if (is_readable($this->source) && is_writable($this->destination)) 
    { 
     return true; 
    } 
    throw new UnitOfWorkRollbackException('File cannot be moved'); 
    } 

    public function commit() 
    { 
    $filename = (null === $this->newName) 
     ? basename($this->source) 
     : $this->newName 
    ; 
    if (!rename($this->source, $this->destination . DIRECTORY_SEPARATOR . $filename)) 
    { 
     throw new UnitOfWorkRollbackException('File move failed'); 
    } 
    } 

    public function rollback() 
    { 
    // Nothing to do here since the file doesn't actually move until commit() 
    } 
} 

的例子全部放在一起。

$UoW = new UnitOfWork(); 

$UoW->addEntity(new FileMoverEntity('/tmp/foo', '/home/me', 'profile.jpg')); 
$UoW->addEntity(new FileMoverEntity('/tmp/bar', '/root', 'profile.jpg')); 

if ($UoW->execute()) 
{ 
    // all operations successful 
} 

現在,我沒有這樣做,你會想在這裏有些東西 - 像跟蹤這些異常被拋出,這樣客戶端腳本可以訪問這些信息 - 但我認爲你的想法。當然,您可以繼續爲各種操作創建工作實體 - 數據庫更新,API調用,無論如何。

就連接到沒有事務安全表的數據庫而言 - 我沒有任何見解。

+0

謝謝,這看起來很有趣,我將不得不考慮它。 問題雖然:有些查詢使用先前查詢生成的插入標識。不確定這種模式是否可行。 – Workoholic 2010-04-29 20:01:17

+0

任何你可以想出如何處理execute()','commit()','rollback()''結構的方法都可以工作。問題在於解決如何針對不支持本地事務的RDBMS執行連接安全回滾 - 這再次是我沒有任何洞察力的。 – 2010-04-29 20:05:23

相關問題