1

Тема: 500 Error після виклику процедури на SQL Server

Суть функціоналу: користувач вибирає деякі дані на сторінці і тицяє кнопку. На кліку висить функція, що препарує дані і надсилає запит на сервер:

function getOperations()
{
var terms = "";
var df = "";
var dt = "";
var tf = "00:00";
var tt = "23:59";
/*десь тут усі змінні задаються: проблем немає, тому опускаю.*/
    $.ajax(
        {
            type:    "POST",
            url:    "/operations/getOperations",
            data:    "df="+df+"&dt="+dt+"&tf="+tf+"&tt="+tt+"&terms="+terms
        }
        ).done( receiveOperations );
}

Нижче - код метода моделі на сервері, який має витягти необхідні дані (викликається з однойменного методу контроллера). Фреймворк - CodeIgniter.

function getOperations($terminals, $dtFrom, $dtTo)
    {
        $termInfo = array();
        $this->dbase = $this->load->database('mydb', TRUE);
        foreach( explode(';', $terminals) as $term)
        {
            $req = sprintf('SELECT * FROM Table1 WHERE TId=%s AND DTF=\'%s\' AND DTT=\'%s\'', $term, $dtFrom, $dtTo);

            $result = $this->dbase->query( $req ); /*перевіряємо наявність рядка у базі*/
            if($result->num_rows() == 0) #рядок відсутній
            {
                $reqSub = sprintf('exec myCoolProcedure @dtFrom=\'%s\', @dtTo=\'%s\', @TId=%s',
                        $dtFrom,$dtTo,$term);
                $this->dbase->query( $reqSub );
            }
            $result = $this->dbase->query( $req ); /*повтор запиту*/
/*І тут далі вже підготовка даних*/
    }

Суть методу: робимо запит до таблиці. Якщо відповідних рядків немає, викликаємо процедуру (яка їх туди вставляє) і знову витягаємо дані з таблиці. Однак коли я запускаю процедуру, за кілька секунд випадає 500 Error. Цікаво, що процедура при цьому таки відпрацьовує і вставляє дані до таблиці, бо повторний клік на кнопці повертає очікуваний результат.

У чому тут проблема? Може, якісь таймаути?

I belong to the Dead Generation.

2

Re: 500 Error після виклику процедури на SQL Server

ini_set('display_errors', 1);
error_reporting(E_ALL);

А так що показує?

Подякували: koala, Bartash2

3

Re: 500 Error після виклику процедури на SQL Server

А який max_execution_time (в php.ini)? Який у вас SQL-сервер?
Якщо операція дійсно довга, може, варто було б відображати це в браузері (типу, "зараз іде обробка даних, зачекайте 10с") і надсилати новий запит  після того?
І, перепрошую, що то за довга операція - може, її можна (і варто) якось оптимізувати?

Подякували: Bartash1

4

Re: 500 Error після виклику процедури на SQL Server

max_execution_time:
Local value: 300
Master value: 30

Про помилку 500 бачу у консолі JS у Хромі. Більше ніяк воно себе не проявляє.

koala написав:

І, перепрошую, що то за довга операція - може, її можна (і варто) якось оптимізувати?

Процедура важка (містить курсори, юніони, групування, тимчасові таблиці - повний фарш), написана не мною. У випадку виконання для великих діапазонів, заданих dtFrom, dtTo, може затягтися секунд і на 20-30, думаю. Вставка даних, які процедура будує, - це спроба розвантажити сервер, кешуючи, таким чином, попередні запити.
SQL Server 2000.

I belong to the Dead Generation.

5

Re: 500 Error після виклику процедури на SQL Server

І ще момент: використовую вже sqlsrv, а не mssql.

I belong to the Dead Generation.

6 Востаннє редагувалося koala (13.06.2013 15:56:39)

Re: 500 Error після виклику процедури на SQL Server

Bartash написав:

max_execution_time:
Local value: 300
Master value: 30

Про помилку 500 бачу у консолі JS у Хромі. Більше ніяк воно себе не проявляє.

koala написав:

І, перепрошую, що то за довга операція - може, її можна (і варто) якось оптимізувати?

Процедура важка (містить курсори, юніони, групування, тимчасові таблиці - повний фарш), написана не мною. У випадку виконання для великих діапазонів, заданих dtFrom, dtTo, може затягтися секунд і на 20-30, думаю. Вставка даних, які процедура будує, - це спроба розвантажити сервер, кешуючи, таким чином, попередні запити.
SQL Server 2000.

Якщо Local більший за Master , то Local ігнорується. Скрипт примусово прибивається за 30 секунд. Ну і про користувача подумайте - йому 30 секунд чекати? Краще робіть так: іде запит, користувачеві показується гіфка з простою анімацією. Якщо запит "короткий", то дані повертаються швидко, все. Якщо довгий, то запускається окремий процес, а користувач отримує замість гіфки повідомлення, що все надовго, і потім або автоматичний запит за 30 секунд, або йому доведеться самому тиснути, як вже правильніше - дивіться самі.
Ну і перевіряти повним запитом - це неправильно, робіть щось типу
select top 1 NULL from ...
Нащо два рази запит робити, навіть якщо він кешується?

7

Re: 500 Error після виклику процедури на SQL Server

А в логах нічого не пишеться?

8

Re: 500 Error після виклику процедури на SQL Server

koala написав:

Нащо два рази запит робити, навіть якщо він кешується?

Таблиця містить результати звітів, що генеруються тією процедурою. Суть у тому, що якщо перший SELECT з таблиці верне порожнину, то треба дані згенерувати, а тоді витягти. А якщо дані є, то все ок: беремо з першого запиту дані й обробляємо собі. По факту, там не так і багато даних у таблиці. Зате процедура суттєва.
Сайт призначений для людей, яким і 5 хвилин можна почекати - не принципово.

Гіфка ще буде: руки не дійшли поки. :)

Replace написав:

А в логах нічого не пишеться?

access.log написав:

***.***.***.*** - - [13/Jun/2013:16:10:33 +0300] "POST /operations/getOperations HTTP/1.1" 500 1454

I belong to the Dead Generation.

9

Re: 500 Error після виклику процедури на SQL Server

Bartash написав:
koala написав:

Нащо два рази запит робити, навіть якщо він кешується?

Таблиця містить результати звітів, що генеруються тією процедурою. Суть у тому, що якщо перший SELECT з таблиці верне порожнину, то треба дані згенерувати, а тоді витягти. А якщо дані є, то все ок: беремо з першого запиту дані й обробляємо собі. По факту, там не так і багато даних у таблиці. Зате процедура суттєва.
Сайт призначений для людей, яким і 5 хвилин можна почекати - не принципово.

Гіфка ще буде: руки не дійшли поки. :)

Replace написав:

А в логах нічого не пишеться?

access.log написав:

***.***.***.*** - - [13/Jun/2013:16:10:33 +0300] "POST /operations/getOperations HTTP/1.1" 500 1454

БД, власне кажучи, призначені не для процедур, а для зберігання даних. Якщо основна робота винесена в процедуру, а не час від часу її треба смикати - може, варто взагалі переглянути модель? Кешувати дані в БД - це те саме, що тягати в кишені замість гаманця банківський сейф. Можете хоч трохи описати, що процедура робить?
Про гіфку - це я умовно, суттєво там про розрізнення короткого і довгого запиту.
І де ви таких людей знайшли? :)

10

Re: 500 Error після виклику процедури на SQL Server

Я би спробував якось віддебажити. GET передавати та дивитись, що там за помилка.

11

Re: 500 Error після виклику процедури на SQL Server

koala написав:

БД, власне кажучи, призначені не для процедур, а для зберігання даних. Якщо основна робота винесена в процедуру, а не час від часу її треба смикати - може, варто взагалі переглянути модель? Кешувати дані в БД - це те саме, що тягати в кишені замість гаманця банківський сейф. Можете хоч трохи описати, що процедура робить?
Про гіфку - це я умовно, суттєво там про розрізнення короткого і довгого запиту.
І де ви таких людей знайшли?

Суть така. У базі є дані за операціями. Кожна операція має окремий тип, дату та значення (число). Процедура вибирає статистичну інфу про ці операції (суму, кількість), але.. за окремими типами. У результаті роботи процедури формується запит з єдиним рядком, кожна колонка якого відповідає певному показнику (наприклад: сума операцій типу А, кількість операцій типу Б, абощо).

Попередня версія сайту, написана на голому РНР, загалом працювала з цією процедурою (там ще був набір mssql-функцій). Зараз сайт переписаний мною на СІ з модулем sqlsrv. Часу переписувати процедуру з нуля наразі немає, а сайт бажано допиляти щошвидше.
Тут особлива ситуація з людьми: проект - некомерційний, а технічний, я з нього хіба що власний досвід отримую. :)

Replace написав:

Я би спробував якось віддебажити. GET передавати та дивитись, що там за помилка.

Зневаджував, тестував запити до бази, які формувалися у моделі. Все проходить коректно, просто після виклику процедури на сервері БД мій сервер вертає 500. Цікаво, що інфа про 500 засвітилася у Хромі (JavaScript console) секунд за 3-5 після старту...

I belong to the Dead Generation.

12

Re: 500 Error після виклику процедури на SQL Server

Bartash написав:

Суть така. У базі є дані за операціями. Кожна операція має окремий тип, дату та значення (число). Процедура вибирає статистичну інфу про ці операції (суму, кількість), але.. за окремими типами. У результаті роботи процедури формується запит з єдиним рядком, кожна колонка якого відповідає певному показнику (наприклад: сума операцій типу А, кількість операцій типу Б, абощо).

А що, sqlsrv не вміє робити запити на SUM і COUNT? О Боже, що тільки люди не використовують...

13

Re: 500 Error після виклику процедури на SQL Server

koala, розробники, вочевидь, тому і наваяли процедуру, щоб не зашивати порядка 20 запитів у код. Там не все так просто, і процедура у реальності - не просто десяток селектів з юніонами.

Однак проблема не в тому. Єдине, що треба, це exec proc_ThisHardcoreProcedure і подальше отримання даних без усяких там помилок сервера.

З.І: sqlsrv - це той же mssql, тільки зі штампом "зроблено у Мілкософтії", існує для РНР>5.3, здс. Свої граблі, звісно, теж має, але то дрібниці... :)

I belong to the Dead Generation.

14

Re: 500 Error після виклику процедури на SQL Server

Bartash, а не пробував ці дані відправляти не використовуючи ajax, а беспосередньо відправлячи форму? Я думаю потрібно відловити помилку. Ще раз передивився код - ніби все правильно. Щось з процедурою скоріше за все.

15

Re: 500 Error після виклику процедури на SQL Server

Replace написав:

Bartash, а не пробував ці дані відправляти не використовуючи ajax, а беспосередньо відправлячи форму? Я думаю потрібно відловити помилку. Ще раз передивився код - ніби все правильно. Щось з процедурою скоріше за все.

Імовірно, таки доведеться тестувать окремо...

Взагалі, попередники користували mssql_query(), і у них процедура наприкінці просто робила SELECT з темпової таблиці, і цей селект опинявся у результатах даної функції. Однак sqlsrv_query(), по ходу, не така дотошна калька, бо запит Exec anyProcedure нічого у ній не вертає незалежно від структури процедури. Відповідно до цього я змінив процедуру, прописавши у ній Insert отого селекту. Одним словом, підтримка старого ПЗ. :D

Процедура коректна. Я запускав її у Query Analyzer, потім перевіряв дані у таблиці. Все працює.

I belong to the Dead Generation.

16

Re: 500 Error після виклику процедури на SQL Server

[Microsoft][SQL Server Native Client 10.0][SQL Server]Executing SQL directly; no cursor.

Цікаво, як цей сайт існував раніше... Доведеться перепаювати процедуру.%_%

I belong to the Dead Generation.

17

Re: 500 Error після виклику процедури на SQL Server

РАПТОВО все вирішилося просто:

Замінити текст запиту для процедури з

"exec myCoolProcedure"

на просто

"myCoolProcedure"

Отакі пироги... "get rid of EXEC..."
:)

I belong to the Dead Generation.
Подякували: Replace, koala2