亚洲狠狠久久综合一区二区三区

<progress id="73rr5"></progress>
<tbody id="73rr5"><pre id="73rr5"></pre></tbody>

    <tbody id="73rr5"></tbody><dd id="73rr5"><track id="73rr5"></track></dd>
    MYSQL事務嵌套,PHP事務嵌套,THINKPHP事務嵌套

    成人自考/成人高考/教師資格證/會計從業資格證/建造師/造價師,一個小程序就夠啦。

    最近有在追蹤一個tp3的事務問題,正好看到事務嵌套的問題,于是整理了出來,本來想等待同事整理,白嫖他,結果等了個寂寞。

    (1).參考事務嵌套的錯誤SQL:

    ### 事務1開啟
    BEGIN;
    
     ## 事務1修改數據
     UPDATE hqjf_job_num  SET wx_uname='蔣琦1024' where id = 602;
     
     ### 事務2開啟
     BEGIN;
     
     ### 事務2提交
     COMMIT; 
     
    ### 事務1回滾
    ROLLBACK;

    我們期望的結果:update語句不會執行成功,實際執行成功了

    出現問題的原因:BEGIN語句會隱式的執行事務提交,相當于第二個BEGIN執行的時候提交了第一個事務.

    (2).哪些SQL語法會隱式事務提交事務呢?

    參考Mysql官方文檔:

    https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html

    (2.1).DDL 

    ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME, ALTER EVENT, ALTER PROCEDURE, ALTER SERVER, ALTER TABLE, ALTER TABLESPACE, ALTER VIEW, CREATE DATABASE, CREATE EVENT, CREATE INDEX, CREATE PROCEDURE, CREATE SERVER, CREATE TABLE, CREATE TABLESPACE, CREATE TRIGGER, CREATE VIEW, DROP DATABASE, DROP EVENT, DROP INDEX, DROP PROCEDURE, DROP SERVER, DROP TABLE, DROP TABLESPACE, DROP TRIGGER, DROP VIEW, INSTALL PLUGIN, RENAME TABLE, TRUNCATE TABLE, UNINSTALL PLUGIN.

    (2.2).USER|MODIFY TABLES

    ALTER USER, CREATE USER, DROP USER, GRANT, RENAME USER, REVOKE, SET PASSWORD.

    (2.3).TRANSACTION|LOCK TABLES

    BEGIN, LOCK TABLES, (if the value is not already 1), START TRANSACTION, UNLOCK TABLES. SET autocommit = 1,UNLOCK TABLES

    (2.4).DATA LOADING STATEMENTS

    LOAD DATA

    (2.5).ADMINISTRATIVE STATEMENTS

    ANALYZE TABLE, CACHE INDEX, CHECK TABLE, FLUSH, LOAD INDEX INTO CACHE, OPTIMIZE TABLE, REPAIR TABLE, RESET

    (2.6).REPLICATION CONTROL STATEMENTS

    START SLAVE, STOP SLAVE, RESET SLAVE, CHANGE MASTER TO

    好家伙原來這多SQL操作都會隱式提交事務

    同時上面的文檔中提到:

    Transactions cannot be nested. This is a consequence of the implicit commit performed for any current transaction when you issue a START TRANSACTION statement or one of its synonyms.

    事務不能嵌套。 這是當您發出 START TRANSACTION 語句或其同義詞之一時對任何當前事務執行的隱式提交的結果。

    (3).設置autocommit并不能解決上面的事務嵌套問題,好好了解下autocommit到底是啥

    首先要知道什么叫自動提交。就是自動提交事務啦。瓜娃子。

    (3.1).假設開啟事務自動提交的時候,你執行一個SQL如下:

    UPDATE hqjf_job_num  SET wx_uname='蔣琦104' where id = 6956;

    實際上已經等價于執行了如下SQL:

    BEGIN;
    UPDATE hqjf_job_num  SET wx_uname='蔣琦104' where id = 6956;
    COMMIT;

    只不過是MYSQL幫你的SQL自動加了事務并且提交了。

    如果你開啟了事務自動提交且自己使用了事務操作,MYSQL就會乖乖聽你的,不會亂自動提交,除非你自己隱式提交。

    (3.2).假設關閉事務自動提交的時候,你執行一個SQL如下:

    UPDATE hqjf_job_num  SET wx_uname='蔣琦104' where id = 6956;

    實際上根本不會執行成功,關閉事務自動提交后MYSQL要求你必須自己手動提交事務,否則SQL沒有提交也就不會更新咯

    老高你的內容我看不懂,給我推薦1個詳細的autocomit的文章,好的,給你。直達地址:https://blog.csdn.net/wx145/article/details/82740737

    上面我們得出的結論是MYSQL是不支持事務嵌套的,特別注意是不支持的,不支持的,不支持的!別看其他文章瞎說,看官方文檔。

    (4).MYSQL不支持事務嵌套,如果模擬事務嵌套的效果

    (4.1).例子SQL:

    ### 開啟事務
    BEGIN;
    
    ### 建立事務保存點a
    SAVEPOINT a;
    
    ### 更新數據名稱為1024
    UPDATE hqjf_job_num  SET wx_uname='1024'  WHERE id=7638;
    
    ### 建立事務保存點b
    SAVEPOINT b;
    
    ### 更新數據名稱為2048
    UPDATE hqjf_job_num  SET wx_uname='2048'  WHERE id=7638;
    
    ### 建立事務保存點d
    SAVEPOINT c;
    
    ### 回滾到事務保存點
    ROLLBACK TO SAVEPOINT a;
    
    ### 提交事務
    COMMIT;

    假設以上數據的原始wx_uname的原始值為空

    ROLLBACK TO SAVEPOINT a;則數據不會修改
    ROLLBACK TO SAVEPOINT b;則數據會被修改為1024
    ROLLBACK TO SAVEPOINT c;則數據會被修改為2048

    看看上面的SQL代碼的執行順序吧:

    上面的SQL在執行到ROLLBACK TO SAVEPOINT a的時候回跳到建立事務保存點a的位置,然后執行剩下的COMIT語句,因此示例的SQL不會修改任何數據

    (5).PHP框架中解決MYSQL事務嵌套的方案(TP6)

    開啟事務示例:

    /**
     * 啟動事務
     * @access public
     * @return void
     * @throws \PDOException
     * @throws \Exception
     */
    public function startTrans(): void
    {
        try {
            $this->initConnect(true);
            ++$this->transTimes;
            if (1 == $this->transTimes) {
                $this->linkID->beginTransaction();
            } elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
                $this->linkID->exec(
                    $this->parseSavepoint('trans' . $this->transTimes)
                );
            }
            $this->reConnectTimes = 0;
        } catch (\Throwable | \Exception $e) {
            if ($this->transTimes === 1 && $this->reConnectTimes < 4 && $this->isBreak($e)) {
                --$this->transTimes;
                ++$this->reConnectTimes;
                $this->close()->startTrans();
            } else {
                if ($this->isBreak($e)) {
                    // 嘗試對事務計數進行重置
                    $this->transTimes = 0;
                }
                throw $e;
            }
        }
    }

    開啟事務時統一遞增事務次數

    第一次開啟事務則真正調用MYSQL開啟事務

    第二次或以上開啟事務分情況:支持savepoint時調用MYSQL創建事務保存點,不支持時則相當于啥也不干,


    執行事務回滾示例:

    /**
     * 事務回滾
     * @access public
     * @return void
     * @throws \PDOException
     */
    public function rollback(): void
    {
        $this->initConnect(true);
        if (1 == $this->transTimes) {
            $this->linkID->rollBack();
        } elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
            $this->linkID->exec(
                $this->parseSavepointRollBack('trans' . $this->transTimes)
            );
        }
        $this->transTimes = max(0, $this->transTimes - 1);
    }

    執行事務回滾時事務次數統一減1

    如果事務次數為1則真正提交MYSQL讓事務回滾

    如果事務次數大于1并且支持savepoint則回滾事務到事務保存點


    執行事務提交的示例:

    /**
     * 用于非自動提交狀態下面的查詢提交
     * @access public
     * @return void
     * @throws \PDOException
     */
    public function commit(): void
    {
        $this->initConnect(true);
        if (1 == $this->transTimes) {
            $this->linkID->commit();
        }
        --$this->transTimes;
    }

    只有事務次數為1的時候才會真正提交MYSQL事務

    通過框架層的支持,你雖然包含了多層事務,但是本質上你只會真正開啟1次事務,提交1次事務,配合savepoint實現事務嵌套的效果。和上面我們模擬事務嵌套的效果一致。

    我看到很多PHP事務嵌套沒有使用savepoint的實現,嚴格來說不算是事務嵌套,比如下面的問題:

    // 開啟主事務
    Db::startTrans();
    // 開啟子事務
    Db::startTrans();
    // 執行UPDATE語句
    // 回滾子事務
    Db::rollback();
    // 提交主事務
    Db::rollback();

    最終結果導致主事務提交后子事務的SQL也執行了,因為子事務開啟和回滾是虛擬的,什么也沒做。當然部分實現中只要子事務回滾強制讓主事務也回滾,這樣失去的嵌套的意義。

    所以支持saveponit才能實現真正的框架層事務嵌套。

    訪客
    郵箱
    網址

    Top 亚洲狠狠久久综合一区二区三区
    <progress id="73rr5"></progress>
    <tbody id="73rr5"><pre id="73rr5"></pre></tbody>

      <tbody id="73rr5"></tbody><dd id="73rr5"><track id="73rr5"></track></dd>