我有一个简单的表格,它是一个电子邮件队列。
CREATE TABLE `emails_queue_batch` (
`eq_log_id` int(11) NOT NULL DEFAULT '0',
`eq_to` varchar(120) CHARACTER SET utf8 DEFAULT NULL,
`eq_bcc` varchar(80) CHARACTER SET utf8 DEFAULT '',
`eq_from` varchar(80) CHARACTER SET utf8 DEFAULT NULL,
`eq_title` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`eq_headers` varchar(80) CHARACTER SET utf8 DEFAULT NULL,
`eq_content` longtext CHARACTER SET utf8,
`eq_sid` int(11) DEFAULT '0',
`eq_type` int(11) DEFAULT '0' COMMENT 'email type',
`eq_esp` int(11) DEFAULT '0',
PRIMARY KEY (`eq_log_id`),
KEY `email` (`eq_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
多个线程一次重复读取 50 行并删除这些行。
为了避免重复阅读我使用的同一行:
$db->query(" LOCK TABLE $table WRITE ");
$query= "SELECT * FROM $table LIMIT ".CHUNK_SIZE. " " ;
$emails2send=$db->get_results ($query);
if (!empty ($emails2send)){
// DELETE EMAIL
$eq_log_ids = array();
foreach ($emails2send as $email) $eq_log_ids[]= $email->eq_log_id ;
$query= "DELETE FROM $table WHERE eq_log_id IN ( ".implode(',', $eq_log_ids)." ) ";
$db->query ($query);
$db->query (" UNLOCK TABLES "); // unlock the table so other sessions can read next rows
........ code processing the read rows here .............
} else { // if !empty emails2send
// $emails2send is empty
$db->query (" UNLOCK TABLES; ");
$stop_running=true; // stop running
}
另一个线程同时写入表。出于某种原因,我不明白这个配置在读取和写入时都被锁定的表死锁了。
我的问题是:这是锁定正确的解决方案,以确保我读取每一行一次且仅一次(并删除它)。
还是将其作为交易更好地处理,如果是,是哪种?我没有交易经验。