我有兩個MySQL表:如何避免鎖定從SELECT中的所有表MySQL的INNER JOIN ... FOR UPDATE
tbl_jobs (
id INTEGER PRIMARY KEY,
status ENUM("runnable", "running", "finished"),
server_id INTEGER
)
tbl_servers (
is INTEGER PRIMARY KEY,
name VARCHAR(50)
)
我有很多連接的客戶端,需要一個工作了特定的服務器是runnable
並將其設置爲running
。
這是我目前如何做到這一點(在存儲過程):
DELIMITER $$
CREATE PROCEDURE GET_JOB(serverName VARCHAR(50))
BEGIN
DECLARE jobId INTEGER DEFAULT NULL;
SELECT id FROM tbl_jobs j INNER JOIN tbl_servers s on j.server_id=s.id
WHERE j.state='runnable' AND s.server_name=serverName
ORDER BY job_id ASC LIMIT 1
INTO jobId FOR UPDATE;
IF IFNULL(jobId, 0) = 0 THEN
SELECT 0;
END IF;
UPDATE tbl_jobs SET state='running' WHERE job_id=jobId;
SELECT jobId;
END $$
這工作得很好,但當併發用戶的數量變大(數百個),我看到有一個大鎖擁擠進行tbl_servers
表。我知道FOR UPDATE
語句會鎖定所有的表,但我實際上使用tbl_servers
作爲只讀表。
問題:如何在tbl_servers
上避免鎖擁塞(即鎖定)?
我能想到的一件事是將我的查詢分成兩個 - 首先將服務器名稱轉換爲id,然後查詢tbl_jobs
,但在我的真實應用程序中,一個服務器名稱可以有許多ID(我知道這聽起來很奇怪,但我只是簡單介紹了我的應用程序)。因此,tbl_jobs
上的第二個查詢將需要準備好的語句。
我確定有一個更優雅的解決方案。
系統:在亞馬遜RDS
- MySQL的67年5月1日
- 所有的表的InnoDB
- 我做對
tbl_jobs.server_id
你爲什麼需要'INNER JOIN'?在你的代碼中沒有真正的需要。 「servername」呢?你沒有在你的代碼中使用它,你爲什麼要通過這個?我不認爲,這是你的真實代碼 –
固定使用'serverName' - 這是明顯的錯誤類型。謝謝!附:當然它不是一個真正的代碼。它是來自真實應用程序的一個摘錄,可以說明問題。 –