There is a code that theoretically does not allow duplication in the database over the $slon_code и $service_id fields (I did not make the composite unique key, I think for the time being to figure it out without it, and to understand the duplication as a whole).
The essence of the class is parsing and caching information.
The main method of the class get_response() : there is an elephant isset_slon() - we check the time, issue it from the database as a cache or parsim, no elephant - add add_slon() to the database, then the parsim and write the information to the elephant, issue it to the user.
Problem : for some reason, there are duplicates in the $slon_code и $service_id fields in the database. I see no reason to add the isset_slon() check inside add_slon() , because the addition now passes the check inside get_response() and falls into the else branch, that is, isset_slon() == false .
So here's the thing: when isset_post () works incorrectly, the work of further code is meaningless (and this is not about this method, but for anyone working with sql queries). What to do, what to do?
Questions:
- Why is the duplication of records in the database? (25 duplicates appeared on 5,000 elephants)
- How to solve a problem?
- How do CMS work where hundreds of sql queries are used to generate a web page?
Updated 12/08/2016
Started a small log, the second line is microtime (true). It can be seen that the record was found, and after that it is still being added.
Date: 08.12.2016 13:51:28 1481194288.9353 slon_code: 125125125 service_id: 1 slon_code в базе есть, проверяем таймаут Date: 08.12.2016 13:51:29 1481194289.5376 slon_code: 125125125 service_id: 1 slon_codeа в базе нет, придется парсить с нуля slon_code добавлен в базу Date: 08.12.2016 13:51:29 1481194289.5627 slon_code: 125125125 service_id: 1 slon_codeа в базе нет, придется парсить с нуля slon_code добавлен в базу Date: 08.12.2016 13:51:29 1481194289.5887 slon_code: 125125125 service_id: 1 slon_codeа в базе нет, придется парсить с нуля slon_code добавлен в базу Request class
class Resp { private $slon_code; private $service_id; public function __construct($slon_code = '', $service_id = 0) { $this->slon_code = $slon_code; $this->service_id = $service_id; } public function get_response() { if ($this->isset_slon()) { //СЛОН ЕСТЬ //Прошло ли достаточно времени с последнего парсинга if ($this->can_parse()) { //парсим $this->parse_slon(); return $this->get_slon_info(); } else { //выдаем из бд (кеш) return $this->get_slon_info(); } } else { //СЛОНА НЕТ! //добавим в базу слона/пустышку //по пустышке ограничиваю запросы пользователей $this->add_slon(); $this->parse_slon(); return $this->get_slon_info(); } } private function isset_slon() { $sql = 'SELECT COUNT(*) AS count FROM slon WHERE slon_code = :slon_code AND service_id = :service_id'; $data = $this->db->select($sql, $this->slon_params()); if ($data[0]['count'] > 0) { return true; } else { return false; } } private function add_slon() { //(появились одинаковые слоны в базе) $sql = 'INSERT INTO slon (slon_code, service_id) VALUES (:slon_code, :service_id)'; $params = [':slon_code' => $this->slon_code, ':service_id' => $this->service_id]; $inserted = $this->db->insert($sql, $params); if ($inserted) { return true; } else { return false; } } } Class code for query in DB:
class Database { public function insert(){ //практически копия метода select() ниже } public function select($sql = '', $params = array()){ $sth = $this->dbh->prepare($sql); if (!empty($params)) { $s = $sth->execute($params); } else { $s = $sth->execute(); } if (!$s) { //логируем ошибку, ни одной ошибки в логах пока нет Log::create_mysql_log($sql, $params, $sth->errorInfo()); return false; } return $sth->fetchAll(PDO::FETCH_ASSOC); } }
insert ... select ... where not exists(select ...)but again insert-check must be an atomic operation for the database - Mike