次のようなテーブルスキームがあります。
CREATE TABLE IF NOT EXISTS `offers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`price` double NOT NULL,
`ip` varchar(15) NOT NULL,
`cdate` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id` (`campaign_id`,`price`)
) ENGINE=InnoDB DEFAULT CHARSET=latin5 AUTO_INCREMENT=190514 ;
ユーザーによる新しいオファーごとに、最後の注文が同じユーザーによって与えられたかどうかを確認します。
"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-log Percona サーバーを使用します。以下は、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