从PHP端处理MySQL事务:策略和最佳实践

Let's say I have following dummy code that actually copy-pastes company (client) information with all related objects:

class Company extends BaseModel{
    public function companyCopyPaste($existingCompanyId)
    {

        $this->db->transaction->start();

        try{
            $newCompanyId = $this->createNewCompany($existingCompanyId);
            $this->copyPasteClientObjects($companyId, $newCompanyId)
            $this->db->transaction->commit();
        } catch(Exception $e){
            this->db->transaction->rollback();
        }

    }
    ...
}

Method copyPasteClientObjects contains a lot of logic inside, like selecting/updating existing data, aggregating it and saving it. Also whole process may take up to 10 seconds to complete (due to loads of information to process) Easiest way is to start transaction in the begging of the method and commit it when its done. But I guess this is not the right way to do it, but still I want to keep everything integral, also to avoid deadlocks as well. So if one of the steps fail, I want previous steps to be rolled back.

Any good advice how to handle such situations properly?

This is not an answer but some opinion.

If I get you right, you want to implement create-new-from-existing kind operation.

There is nothing really dangerous yet happen while you create new records.

I would suggest you to transform code this way:

     try{
        $newCompanyId = $this->createNewCompany($existingCompanyId);
        $this->copyPasteClientObjects($companyId, $newCompanyId)
    } catch(Exception $e){
        this->deleteNewCompany($newCompanyId);
    }

This way you don't need any transaction, but your deleteNewCompany should revert everything that was done but not finished. Yes it is more work to create that functionality, but to me it makes more sense then to block DB for 10 sec.

And } catch(Exception $e){ imho is not the best practice, you need to define some custom case specific Exception type. Like CopyPasteException or whatever.