Пересечение запросов mysql

lexey2006.90

Новичок
Добрый день. Вопрос по поводу mysql. У меня есть много скриптов, на INSERT, DELETE и SELECT которые идет одновременно, и некоторые скрипты идут некорректно, например парсится файл xml и INSERT вставляет не все. Может ли это быть из-за одновременного запроса DELETE в базу? как можно поступить, если процессов очень много и по времени их невозможно разделить, может быть что-то связанное в wiew (только база большая - 15 млн. записей)?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Ну ты маловато данных дал пока что, что за движок на таблицах, MyISAM или InnoDB? Какие запросы? Используется ли INSERT DELAYED? Что вообще ты удаляешь и т.д.
 

lexey2006.90

Новичок
Inno db. Делаю Insert и Delete в одну и ту же таблицу. Притом запросы могут совпадать по времени.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
lexey2006.90
То, что они совпадают по времени мало влияет в случае innodb.
Опиши задачу чуть более подробно, то есть у тебя есть таблица, которая несет в себе довольно большой набор данных, вопрос в том, надо ли все хранить именно в одной таблице, надо ли делать одновременно кучу селект-делит-инсерт запросов. То есть опиши сам процесс, который ты там наваял, авось народ и посоветует чего.
 

lexey2006.90

Новичок
У меня таблица, в которой хранятся туры в египет. Раз 15 мин идет докачка новых данных (из xml) - от разных тур операторов. Полюбому все должно храниться в одной таблице. Одновременно идет уделение туров тоже по выпускаемым СТОПам по разным параметрам. Все должно идти в режиме онлайн.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
lexey2006.90
ты понимаешь, что 15 миллионов записей не наберется у всех операторов даже в россии, для одного египта, ты как-то не полностью описал проблему.

Теперь так,
и некоторые скрипты идут некорректно, например парсится файл xml и INSERT вставляет не все
вот тут поподробнее, что значит "некорректно" и "не все"?
 

lexey2006.90

Новичок
Поверь мне - у одного оператора teztour 25 млн записей - я работаю в тех поддержке турагенства. Некорректно и не все: парсится один xml - автоматически - по крону. Вставляются не все записи. Проверил всевозможные проблемы - сам скрипт, файл, доступность сервера оператора в это время и т.д. Потом запускаю скрипт вручную - и записываются все записи.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Кхм, 25 миллионов записей я себе слабо представляю, видимо что-то там не так лежит. Это слишком много, даже если учесть все "вариации" туров.

ты понимаешь, что тут надо установить из-за чего у тебя валится запись. Надо смотреть сколько у тебя запросов висит в queue мускуля, какая нагрузка при этом на базу, и т.д. Вообще было бы неплохо добавить какой-то кусок кода, который бы писал в случае неудачи вставки строки нечто в какой-то лог. В самом логе php / мускуля есть что?
 

lexey2006.90

Новичок
могу добавить весь скрипт.
PHP:
foreach ($prices[0] as $item2) {
		$all_price_sumnar++;
		preg_match_all("'DATE=\"(.*?)\"'si", $item2, $date);
		$price_date=$date[1][0];
		$price_date=$price_date[0].$price_date[1].$price_date[2].$price_date[3]."-".$price_date[4].$price_date[5]."-".$price_date[6].$price_date[7];
		preg_match_all("'N=\"(.*?)\"'si", $item2, $nights);
		$price_nights=$nights[1][0];
		preg_match_all("'VAL=\"(.*?)\"'si", $item2, $val);
		$price_val=$val[1][0];
		
		$elemdat  = explode("-",$price_date);
		$price_date_sec = mktime (0,0,0,$elemdat[1],$elemdat[2],$elemdat[0]);
		
		if ($min_date_sec>$price_date_sec) {$min_date=$price_date;}
		if ($max_date_sec<$price_date_sec) {$max_date=$price_date;}
		
		// $SQL = "INSERT IGNORE INTO anextour_hotels (name) VALUES ('$price_hotelname');";
		// $result = $DB->Query($SQL) or die(mysql_error());
		
		$enabledprice=0;
		if ($now_date_sec<=$price_date_sec) {
			for ($ii=0;$ii<count($hotels_mas);$ii++) { // если найден такой символьный код в массиве инфоблоков, то записываем, если нет - то на нет и суда нет
			//if ($hotels_mas[$ii][0]==$price_hotelname) {$enabledprice=1; break;} // нужно переделать сравнение с id в инфоблоке
			//////////////////////////////////////////////////////////////////////
			// var_dump($hotels_mas[$ii][1]);
			if ($hotels_mas[$ii][1]==$price_id_anex){$enabledprice=1; break;}
			// var_dump($hotels_mas[$ii][1]);
			//////////////////////////////////////////////////////////////////////
			}
			// $SQL = "SELECT id from anextour_hotels where id_anex = '$price_id_anex'";
			// $res = mysql_query($SQL);
			// if(mysql_num_rows($res)) {$enabledprice=1;}
		}

		//if ($price_hotelname=='DOMINA PRESTIGE SEA') {$price_hotelname='DOMINA PRESTIGE POOL';}
		//if ($price_hotelname=='DOMINA SULTAN POOL') {$price_hotelname='DOMINA SULTAN BEACH';}
		// echo $enabledprice." ".$price_transportfrom." ".$price_chd." ".$price_inf."________";
		if ($enabledprice==1 and $price_transportfrom=='Moscow' and $price_chd==0 and $price_inf==0) {
			$elements_true_param++;
			$SQL="SELECT id FROM anextour_spo_price WHERE spoid='$price_spo' and country='$price_country' and city='$price_city' and adl='$price_adl' and chd='$price_chd' and inf='$price_inf' and currency='$price_currency' and hotelname='$price_id_anex' and star='$price_star' and room='$price_room' and meal='$price_meal' and depature_from='$price_transportfrom' and depature_to='$price_transportto' and depature_date='$price_date' and days='$price_nights' and price='$price_val' and datecreate='$price_datecreate' LIMIT 1";
			// hotelname = '$price_id_anex'
						
			$res = mysql_query($SQL);
			if(mysql_num_rows($res)) {$price_in_base=1; $elements_true_no_add++;}
			else {$price_in_base=0;}
			
				$true_replace=0;
				$true_add=0;
				$replace_id=0;
				$SQL="SELECT id FROM anextour_spo_price WHERE hotelname='$price_id_anex' and depature_date='$price_date' and adl='$price_adl' and room='$price_room' and meal='$price_meal' and days='$price_nights' and datecreate<'$price_datecreate'";
				// hotelname = '$price_id_anex'
				
				$res = mysql_query($SQL);
				if(mysql_num_rows($res))  {
				while ($line = mysql_fetch_row($res)) {
					$replace_id=$line[0];
					$true_replace=1;
				}}
				
				if ($true_replace==0) {
					$SQL="SELECT id FROM anextour_spo_price WHERE hotelname='$price_id_anex' and depature_date='$price_date' and adl='$price_adl' and room='$price_room' and meal='$price_meal' and days='$price_nights' and datecreate>='$price_datecreate'";
						// hotelname = '$price_id_anex'
						$res = mysql_query($SQL);
						if(mysql_num_rows($res)) {$true_add=0; $elements_true_no_add++;}
						else {$true_add=1;}
				}

				if (($true_replace==1 or $true_add==1) and ($price_in_base==0)) {
					$elements_true_add_replace++;
					$numprice++;
					$all_price++;
					$an++;
					$anex_id = $an*100 + 1;
					// var_dump($anex_id);
					if ($sqfix=='') {
					$sqfix=$sqfix." ('$anex_id','$price_spo','$price_country','$price_city','$price_adl','$price_chd','$price_inf','$price_currency','$price_id_anex','$price_star','$price_room','$price_meal','$price_transportfrom','$price_transportto','$price_date','$price_nights','$price_val','$price_datecreate','0')";
					// '$price_id_anex'
					}
					else {
					$sqfix=$sqfix.",('$anex_id','$price_spo','$price_country','$price_city','$price_adl','$price_chd','$price_inf','$price_currency','$price_id_anex','$price_star','$price_room','$price_meal','$price_transportfrom','$price_transportto','$price_date','$price_nights','$price_val','$price_datecreate','0')";
					// '$price_id_anex'
					}
				}
				
				if ($true_replace==1) {
					$SQL = "DELETE FROM anextour_spo_price WHERE id='$replace_id'";
					$result = $DB->Query($SQL);
					$SQL = "DELETE FROM gate_spo_price_turkish WHERE id='$replace_id'";
					$result = $DB->Query($SQL);
					$SQL = "DELETE FROM gate_spo_price_egipt WHERE id='$replace_id'";
					$result = $DB->Query($SQL);
				}
			
		}else{
			$elements_false_param++;
		}
		
		if ($numprice>=$numstep*$step and $sqfix!='') {
		$numstep++;
		$SQL = "INSERT IGNORE INTO anextour_spo_price (id,spoid,country,city,adl,chd,inf,currency,hotelname,star,room,meal,depature_from,depature_to,depature_date,days,price,datecreate,download) VALUES $sqfix;";
		$result = $DB->Query($SQL) or die(mysql_error());
		// var_dump($SQL);
		// var_dump($result);
		$sqfix="";
		}
Запись в таблицу - anextour_spo_price. 25 млн записей - это нормально. Турция - 800 отелей, на 6 мес. вперед, возможные вариации кол-ва человек, питания, кол-ва дней, размещения и т.д.
 

lexey2006.90

Новичок
что происходит, если у меня больше, чем 100 запросов - они не ставятся в очередь, а просто не выполняются?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Записываться они должны. Я у себя делал таким образом вставку 50-56к значений в innodb таблицу, простым циклом, правда у меня был драйвер PDO_MYSQL и не было удалений.

Почему ты юзаешь то mysql_query, а то $DB->Query($SQL)?
 

prolis

Новичок
Это не случай необходимости применения транзакционной модели, так как из одного процесса все выполняется.
1.Каким образом и с какой целью организована одновременная работа нескольких скриптов?
2.Зачем логика импорта вынесена в php? В приведенном скрипте нет групповых операций:(.
3.Про какое количество затрагиваемых записей мы говорим при 15-минутном апдейте?

Вообще-то проблем быть не должно при тривиальном подходе:
1. Импортировать новые данные во временную таблицу.
2.Далее два запроса на вставку-апдейт и удаление.
 

lexey2006.90

Новичок
Вообще-то проблем быть не должно при тривиальном подходе:
Хорошая идея. Только прежде чем это реализовывать необходимо понять, что проблема именно в блокировке таблицы при INSERS/UPDATE/DELETE
Каким образом и с какой целью организована одновременная работа нескольких скриптов?
Постоянно выпускаются новые xml - для импорта и удаления по ним
Зачем логика импорта вынесена в php? В приведенном скрипте нет групповых операций
Нет прямого доступа к серверам бд туроператоров. Есть возможность получить файлы и отпарсить их.
Про какое количество затрагиваемых записей мы говорим при 15-минутном апдейте?
До 100 тыс записей - чаще 5 тыс.
 

prolis

Новичок
Хорошо, давай сначала с тем что есть разберемся:
PHP:
 $SQL = "INSERT IGNORE INTO anextour_spo_price (id,spoid,country,city,adl,chd,inf,currency,hotelname,star,room,meal,depature_from,depature_to,depature_date,days,price,datecreate,download) VALUES $sqfix;";
        $result = $DB->Query($SQL) or die(mysql_error());
1. с какой целью в SQL стоит IGNORE? Убрать бы на время тестирования
2. die(mysql_error()) - очень неинформативно, лучше записать в лог и потом разбираться
 

lexey2006.90

Новичок
с какой целью в SQL стоит IGNORE? Убрать бы на время тестирования
В случае, если баг у оператора, и он 2 раза использует 1 и тот же id
die(mysql_error()) - очень неинформативно, лучше записать в лог и потом разбираться
что именно записать в лог? result = $DB->Query("SQL"); result в лог записать?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Ошибку записать в лог, и смотреть где у тебя завалился запрос. Я тебе уже советовал это делать выше.
 
Сверху