Mysql

如何使選擇語句被阻止?

  • August 9, 2017

您好,出於學習的目的,我正在嘗試故意使 SQL 選擇語句被另一個簡單的 SQL 刪除或更新語句阻塞。我只喜歡 InnoDB 表。

為了準備測試,我創建了一個表

CREATE TABLE `test`.`client` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB;

並在表中插入 1,000,000 行。


現在我將開始測試。

在 MySQL 客戶端 #1 中,我刪除了所有行:

mysql #1> delete from client;

雖然刪除仍在執行,但在另一個 MySQL 客戶端 #2 中,我嘗試選擇一行。

mysql #2> select * from client where id=1;
+---------+------+
| id      | name |
+---------+------+
| 1       | joe  |
+---------+------+
1 row in set (0.00 sec)

結果立即顯示,選擇未被阻止。


接下來我將嘗試另一個測試。我在表中插入 1,000,000 行。

在 MySQL 客戶端 #1 中,我更新了所有行:

mysql #1> update client set name='Bill';

當更新仍在執行時,在另一個 MySQL 客戶端 #2 中,我嘗試選擇一行。

mysql #2> select * from client where id=100;
+-----+------+
| id  | name |
+-----+------+
| 100 | joe  |
+-----+------+
1 row in set (0.00 sec)

mysql #2> select * from client where id=1000;
+------+------+
| id   | name |
+------+------+
| 1000 | joe  |
+------+------+
1 row in set (0.00 sec)

結果立即顯示,選擇未被阻止。

所以現在我的問題是,如何使用 InnoDB 表展示 SQL 選擇語句被另一個簡單的 SQL 刪除或更新語句阻塞?或者 MySQL 從來沒有任何阻塞問題?

PS我不是想模擬兩個相互死鎖的程序,只是一個大的更新或插入阻塞一個選擇。

SELECT 的死鎖可以通過多種方式完成。我寫過關於他們的文章

此級別類似於 REPEATABLE READ,但如果禁用自動送出,InnoDB 會將所有普通 SELECT 語句隱式轉換為 SELECT … LOCK IN SHARE MODE。如果啟用了自動送出,則 SELECT 是它自己的事務。因此,它是只讀的,並且如果作為一致(非鎖定)讀取執行並且不需要阻塞其他事務,則可以序列化。(如果其他事務修改了選定的行,要強制一個普通的 SELECT 阻塞,禁用自動送出。)

切入正題,你可以使用

  • SELECT … FOR UPDATE,然後嘗試SELECT針對這些行
  • SELECT … LOCK IN SHARE MODE,然後嘗試UPDATEDELETE那些行
  • 請參閱 MySQL 文件

試一試 !!!

引用自:https://dba.stackexchange.com/questions/41865