2017-01-13 19 views
0

我目前正在通過AWS RDS和node.js爲服務器使用MySQL 5.5。我們有幾個使用中央服務器的Web應用程序,auth是基於令牌的令牌,這種類似oauth。當你登錄時,你會得到一個授權碼,並將其交換爲訪問和刷新令牌。然後在一個時間間隔內,刷新令牌用於獲取新的訪問和刷新令牌。所有三個令牌都有一個到期日,並且當我們創建新的令牌時,我們有一個DELETE查詢來刪除過期的令牌。這裏是一個這樣的示例:什麼是更好的DELETE查詢經常運行?

DELETE FROM tokens WHERE expires <= NOW() LIMIT 50; 
INSERT INTO tokens (type, ...) VALUES ('access', ...); 
INSERT INTO tokens (type, ...) VALUES ('refresh', ...); 

這3個語句作爲單個事務發送到數據庫服務器,它們不會被單獨查詢。令牌表看起來像這樣:

CREATE TABLE `tokens` (
    `type` varchar(10) NOT NULL, 
    `system` varchar(45) NOT NULL, 
    `userid` int(10) NOT NULL, 
    `key` varchar(45) NOT NULL, 
    `token` varchar(45) NOT NULL, 
    `created` datetime NOT NULL, 
    `expires` datetime NOT NULL, 
    `scopes` longtext, 
    PRIMARY KEY (`token`,`expires`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

這已經工作了幾年,99%的時間工作很好。隨機地,服務器掛起,不會再有任何連接或查詢。看看進程列表,有一堆正在掛起的DELETE查詢。看起來行正在鎖定,因爲我有一個WHERE和一個INSERT試圖執行並且事情被弄亂。 DELETE只在最大刪除50行時刪除,所以我很好奇爲什麼這會隨機發行?

我們正試圖採取其他措施來解決此問題,如刪除較小的塊並降低頻率(擴展訪問令牌到期)。

有沒有更好的方式去清理過期的令牌?

回答

1

您應該在expires上添加索引。複合索引(token, expires)只能用於單獨搜索tokenexpirestoken(因爲它是組合索引的前綴)的查詢。

然後,DELETE查詢將能夠使用該索引,並且不會鎖定在查找過期令牌時掃描的表中的所有其他行。

根據您所做的其他查詢,它可能只是交換現有索引中列的順序,即將其更改爲PRIMARY KEY (expires, token)

+0

感謝您的回覆。刪除了主鍵,並嘗試添加過期回來,被重複的條目捕獲,這是有道理的。因此添加令牌作爲主要和索引到期。所以它現在是'PRIMARY KEY(token),KEY expires(expires)'。我真的不能確定它是否有效,直到它再次失敗。 –

+0

你確定主要是正確的嗎?舊模式將允許具有不同過期的重複令牌,現在您不再允許。是舊的行爲意圖還是錯誤? – Barmar

+0

有'PRIMARY KEY(令牌,過期)'只是添加過期,真相被告知我不知道它創建了一個複合,認爲它只會添加兩個。把它們分開只是我自己的無知,你說「可能」會把我放下。有'PRIMARY KEY(expires,token)'並不意味着perf命中或鎖定?分裂他們不會有幫助嗎?我真的沒有一個好的方法來測試這一切,這一切都在生產中,問題是隨機每隔幾周prod db就會鎖定一次。 –

相關問題