2013-05-03 76 views
3

我們有像下表計劃返回的最後一行與:的Mysql Innodb的不上選擇與遞減順序

"select user_id from offers where campaign_id='".$campaign['id']."' order by id desc limit 1" 

如果user_id相同,我們會阻止新的報價來保護用戶免於意外的雙擊。

如果沒有與報價,我們用插入任何報價問題:

"insert into offers(campaign_id,user_id,price,ip,cdate) values (".$campaign['id'].",".$user['id'].",'".$price."','".$_SERVER['REMOTE_ADDR']."',".time().")" 

但問題是選擇只有約1秒後返回最後插入的行。這意味着如果用戶點擊按鈕的速度過快,用戶可以插入多個優惠。

我們使用5.5.30-30.2日誌的Percona Server作爲我們的數據庫服務器。 以下是我們的my.cnf文件:

[mysqld] 
datadir       = /var/lib/mysql 
tmpdir       = /var/lib/mysqltmp 
socket       = /var/lib/mysql/mysql.sock 
skip-external-locking   = 1 
skip-name-resolve 
open-files-limit    = 40000 
max_heap_table_size    = 64M 
tmp_table_size     = 64M 
log-error      = /var/log/mysqld.log 
thread-cache-size    = 50 
table-cache      = 4096 
table-open-cache    = 4096 
table-definition-cache   = 512 
query-cache-size    = 0 
query-cache-limit    = 16M 
query-cache-type    = 0 
sort-buffer-size    = 1M 
read-buffer-size    = 1M 
read-rnd-buffer-size   = 8M 
join-buffer-size    = 1M 
tmp-table-size     = 64M 
max-heap-table-size    = 64M 
back-log      = 100 
max-connections     = 10000 
max-connect-errors    = 10000 
max-allowed-packet    = 256M 
interactive-timeout    = 360 
wait-timeout     = 360 
innodb       = FORCE 
key-buffer-size     = 32M 
myisam-sort-buffer-size   = 4M 
innodb-buffer-pool-size   = 60G 
innodb-log-file-size   = 256M 
innodb_log_files_in_group  = 2 
innodb-log-buffer-size   = 4M 
innodb-file-per-table   = 1 
innodb-thread-concurrency  = 8 
innodb-flush-log-at-trx-commit =2 
server-id      = 1 
slow-query-log     = 1 
slow-query-log-file    = /var/lib/mysqllogs/slow-log 

回答

0

我認爲這個問題是由多個連接插入之前選擇的同一行類似原因主要包括:

PHP連接1:選擇最後報價user_id說明

PHP連接2:選擇最後報價USER_ID(給出的相同)

PHP連接1:將報價

PHP連接2:插入報價

我通過之前選擇鎖定表並插入後解鎖它好像解決了這個問題:

鎖表提供寫

選擇最後報價的USER_ID

如果它不同於當前用戶插入報價

解鎖表格報價

0

MySQL查詢緩存。

MySQL將檢查第一次點擊,並返回一個空的結果,那麼它會插入記錄,然後以後每次點擊的MySQL返回空結果的緩存值,並允許其他插件。

我們有一個網站,我的工作與要求非常接近發生類似事情。

我們最後不得不運行這個第一

SET SESSION query_cache_type=0; 
+0

query_cache_type已經是0,因爲我從my.cnf複製了 – intacto 2013-05-03 13:42:36

+1

也更新了表中的query_cache – intacto 2013-05-03 13:43:11

+0

我的不好,抱歉。在我讀過cnf時錯過了。 – fullybaked 2013-05-03 13:43:19

1

你有沒有試過用在更新/插入事件的SQL觸發器來檢查,例如,如果

SELECT count(*) FROM `offers` 
WHERE campaign_id = [Your_value] AND user_id = [Your_value]; 

等於0,並採取行動根據它。 (如果已經存在的,沒有做任何修改[...])

編輯:順便說一下,似乎更在Ajax/PHP /無論你使用的問題,而不是一個不正確的使用MySQL數據庫。您應該防止用戶在很短的時間內發送很多請求。

0

您是否嘗試過明確包裝的插入操作的事務?做類似:

START TRANSACTION 
INSERT ... 
COMMIT 
SELECT ... 

這應該保證SELECT將返回最後插入的數據。

更多關於InnoDB的隔離級別:[1][2]