如何使選擇語句被阻止?
您好,出於學習的目的,我正在嘗試故意使 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 的死鎖可以通過多種方式完成。我寫過關於他們的文章
您可以讓 SELECT 因 UPDATE 和 DELETE 而死鎖
您可以讓 SELECT 阻止 UPDATE 和 DELETE
您可以在 SELECT 之前鎖定表並在之後解鎖它
LOCK TABLES table READ;
SELECT ... ;
UNLOCK TABLES;
您可以使用SERIALIZEABLE isoaltion level在事務中執行大型 UPDATE 。MySQL 文件上
SERIALIZEABLE isoaltion level
說:此級別類似於 REPEATABLE READ,但如果禁用自動送出,InnoDB 會將所有普通 SELECT 語句隱式轉換為 SELECT … LOCK IN SHARE MODE。如果啟用了自動送出,則 SELECT 是它自己的事務。因此,它是只讀的,並且如果作為一致(非鎖定)讀取執行並且不需要阻塞其他事務,則可以序列化。(如果其他事務修改了選定的行,要強制一個普通的 SELECT 阻塞,禁用自動送出。)
切入正題,你可以使用
- SELECT … FOR UPDATE,然後嘗試
SELECT
針對這些行- SELECT … LOCK IN SHARE MODE,然後嘗試
UPDATE
或DELETE
那些行- 請參閱 MySQL 文件
試一試 !!!