簡體   English   中英

MySQL中的語句回滾與事務回滾

[英]Statement rollback vs transaction rollback in MySQL

MySQL 文檔我得到以下(關於錯誤代碼):

  • 1205 (ER_LOCK_WAIT_TIMEOUT)

    鎖定等待超時已過期。 等待太久的語句被回滾(不是整個事務)。 如果 SQL 語句應該等待更長的時間來等待其他事務完成,您可以增加 innodb_lock_wait_timeout 配置選項的值,或者如果過多長時間運行的事務導致鎖定問題並降低繁忙系統上的並發性,則可以減少它。

在這個語句中,明確區分了語句回滾和事務回滾。 我的問題是如何回滾一個語句,而在其中運行的事務不回滾? 更重要的是,我在一個事務中遇到了這樣的鎖超時,並且整個事務被回滾了。 有人可以啟發我嗎?

與事務類似,語句也是原子的。 一旦語句開始執行數據更改,原始狀態將被保存(實際上更改已被記錄)。 如果語句因任何原因(超時、與剛剛提交的事務沖突)失敗,則更改必須恢復到原始狀態。 該語句將報告失敗,但該事務仍處於打開狀態,您可以繼續該事務,就像該語句從未執行過一樣。

這其實和savepoint類似——你可以想象在記錄每個語句savepoint之前和語句完成之后,提交savepoint。 但是,這對外部事務或保存點沒有影響。

接受的答案是完全正確和好的,但我最終在同一個文檔頁面上進行了快速測試設置,並且由於評論太短,如果您願意自己測試並查看行為,請使用以下設置:

1) 初始化表

CREATE TABLE `x` (
    `id` INT(10) UNSIGNED NOT NULL,
    `xx` INT(11) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
INSERT INTO X (id, xx) VALUES (1,NULL),(2,NULL),(3,NULL);

2) 打開一個客戶端連接,啟動一個事務,觸發一個INSERT來鎖定新創建的表中的一行

START TRANSACTION;
INSERT INTO X (id, xx) VALUES (1, 5) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

不要提交事務

3) 打開第二個客戶端連接,啟動一個事務,然后在非鎖定行上觸發另一個INSERT

START TRANSACTION;
INSERT INTO X (id, xx) VALUES (2, 7) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

再次,不要承諾。

到目前為止,如果發出SELECT * FROM x然后客戶端 1 看到“1,5; 2,NULL, 3;NULL”,客戶端 2 看到“1,NULL; 2,7; 3,NULL”

4) 在客戶端 2 上觸發一個鎖定的INSERT並等待它用 SQL 1025 終止:

INSERT INTO X (id, xx) VALUES (1, 6) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

現在,如果在客戶端 2 上發出SELECT * FROM x ,我們仍然會看到“1,NULL; 2,7; 3,NULL”,所以語句被回滾了。 如果我們在客戶端 1 上發出它,我們仍然會看到“1,5; 2,NULL; 3,NULL”,因此客戶端 2 事務仍在運行(假設您的客戶端未配置為在每個 SQL 錯誤時自動回滾)。

5) 現在,如果您在兩個客戶端上都發出ROLLBACK ,則該表將“恢復”為所有 NULL 值。 如果你COMMIT它,那么你會得到“1,5; 2,7, 3,NULL”(“1,6”在回滾時無處可尋,但客戶端 2 事務已提交)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM