Просмотр блокировок 1С 7.7 SQL




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

33 Comments

  1. Aleco

    Не хватает в kill.ert имя пользователя 1с

    Reply
  2. Правильно, в kill имени пользователя 1С нет! Чтобы его добыть — имя пользователя 1С — следуйте инструкциям и используйте «Блокировки.ert».

    Впрочем, поскольку Вы дали такой комментарий, читать инструкции Вы не привыкли :-((.

    Reply
  3. infossa

    автор развей мои сомнения

    обработка kill.ert не показывает заблокированных , т.к. пытается анализировать только таблицу master..sysprocesses , а по полю blocked этой таблице вряд ли это можно сделать.

    а вот «блокировки.ert» другое дело

    Reply
  4. infossa

    а ну нашел на проклабе комментарий автора

    >>> Кроме того, у kill.ert нет возможности смотреть заблокированных пользователей и комфортно отслеживать степень загруженности работой MS SQL.

    вопрос снят

    просто не понятно тогда, для чего она нужна 🙂

    Reply
  5. o-mel

    Отличная обработка, пользовался на SQL 2000 долгое время..

    Поставили SQL 2005 и с ней траблы..

    Переделывать обработку под sql 2005 не собираешся???

    Reply
  6. Sure

    Пока не собираюсь: SQL 2005 в обозримом окружении нет. Собственно, работа с 1С 7.7 в нашей организации более не ведётся :-(. Потому возможностей для сколь-либо полезных доработок этой обработки у меня больше нет. В 1С 8.0 всё стало много хуже: сервер приложений изолирует нас и от соединения с SQL-сервером, а кроме того, попытка принудительно «прибить» злоумышленника, запустившего «тяжёлую» операцию в 1С ведёт к обрушению сервера приложений. В 1С 7.7 всё было много проще и приятнее.

    Reply
  7. Gilev.Vyacheslav
  8. MadDAD

    Возможно для SQL 2005 Решение вот http://www.sql.ru/forum/actualthread.aspx?bid=40&tid=575224

    Reply
  9. boks

    Отличная обработка, пользуюсь, нравится.

    Автору респект.

    Reply
  10. Pierre

    А почему она может не показывать имена пользователей? т.е. пустые строки

    Reply
  11. Sure

    Во-первых, может показывать пустые строчки, если в ходе работы чистился справочник «Ативные пользователи». Во-вторых, если используются прямые запросы к SQL-базе, то они создаются «в обход регистрации пользователя», такие соединения с SQL не получают имени в таблице «АктивныеПользователи». Их Вы и видите.

    На моём нынешнем месте работы база оптимизирована прямыми запросами достаточно сильно. И на одно соединение пользователя приходится ещё три соединения с SQL для запросов через ADO. Ну, благо, что здесь хоть терминальный сервер не используется 🙂

    Reply
  12. Sure

    Пришло сообщение.

    Доброе время суток !

    Александр, подскажите пожалуйста маленький вопрос по вашей обработке «Просмотр блокировок 1С 7.7 SQL»

    Вопрос в следующем.

    У нас на рабочем сервере крутятся две базы SQL разных конфигураций. Я добавил в одну базу константы и справочник и запустил обработку КонфигурироватьБлоки ровки. Далее когда запускаю обработку по просмотру блокировок то вижу в колонке пользователей имена активных пользователей из первой базы (в которой создан справочник АктивныеПользователи ) а так же подключения на SQL сервер которые происходят из второй базы (в которой этого справочника нет)

    Возможно ли видеть при одновременно активных двух базах SQL сервера с помощью этой обработки пользователей из двух баз идентифицированных по именам ?



    Отвечаю. Извините, что не могу отправить приватно: новая система начисления баллов на infostart загнала меня в минус.

    Возможно. Но не стандартной версией, а настроенной под себя.

    Нужно знать имена баз, в обеих завести механизм учёта болокировок, знать имена таблиц в основной базе и во второй (Пусть будут SC8888 и anorherdb..SC9999).

    Тогда процедура a_lock_sp будет примерно выглядеть так

    create proc a_lock_sp as

    set nocount on

    create table #locks (spid int,dbid int,ObjId int,IndId int, Type varchar(8),Resource varchar(30),Mode varchar(8),Status varchar(8))

    insert #locks exec sp_lock

    create table #who(spid int, ecid int, status varchar(20),loginame varchar(256), hostname varchar(256) ,blk char(5) null,dbname varchar(80)null, cmd varchar(256) null)

    insert #who exec sp_who

    select s.ROW_ID spid, left(d.name,15) as dbid,

    case d.name

    when ‘onedb’ then s.DESCR

    when ‘anotherdb’ then s1.DESCR

    else »

    end as name

    , count(*) as QtyLock,convert(char(20),loginame) login,l.Status, convert(char(40),cmd) Command,convert(char(20),hostname) Host

    from #locks l, #who w, SC8888 s, anorherdb..SC9999 s1, master..sysdatabases d

    where d.dbid=l.dbid and l.Mode<>’S’ and l.spid=w.spid and s.ROW_ID=l.spid group by s.ROW_ID, left(d.name,15),

    case d.name

    when ‘onedb’ then s.DESCR

    when ‘anotherdb’ then s1.DESCR

    else »

    end,

    convert(char(20),loginame),l.Status, convert(char(40),cmd),convert(char(20),hostname) having s.ROW_ID<>@@SPID

    drop table #locks, #who

    set nocount off

    return

    grant exec on a_lock_sp to public



    Она будет подхватывать имена пользователей из обеих баз.

    Обращаю внимание: отличие процедуры от стандартной — вместо DESCR as name будет «простыня»

    case d.name

    when ‘onedb’ then s.DESCR

    when ‘anotherdb’ then s1.DESCR

    else »

    end as name

    Reply
  13. Sure

    Отвечаю. Извините, что не могу отправить приватно: новая система начисления баллов на infostart загнала меня в минус.

    Подскажите пожалуйста один момент.

    В процедуре ПриНачалеРаботыСистемы() вы вставляете конструкцию

    Процесс=СоздатьОбъект(«Справочник.АктивныеПользователи»);

    Процесс.Новый();

    Если 0=Процесс.НайтиЭлемент(Процесс) Тогда

    не понятно вот что. В чем смысл конструкции

    Если 0=Процесс.НайтиЭлемент(Процесс) Тогда

    ? Идея выполнять запрос при каждом входе пользователя в базу 1С ? Ведь и так понятно что если элемент справочника только создан то он не будет найден.



    Это трюк. При конфигурации блокировок подменяется процедура поска элемента. Вместо этого в таблицу АктивныеПользователи запрос SQL вписывает имя текущего пользователя и номер его сессии. Таким образом, при просмотре блокировок мы может выяснить, кто из пользователей вызывает блокировки (SQL-сервер штатной процедурой sp_lock даёт не имя пользователя в 1С, а номер сессии и имя компьютера)

    Reply
  14. vovaapril

    Параметры подключения к БД SQL можно брать из файла 1CV7.DBA, а не заставлять пользователя вносить их руками

    пример кода тут

    Reply
  15. Sure

    (14) vovaapril,

    Да-да! Плавали-знаем. Я знаю способ получения пароля из параметров подключения. К сожалению, в моей жизни был пример, когда пароль, расшифрованный из параметров подключения не совпадал с паролем SQL. Потому что пароль был в русской раскладке. Так что пароль из констант оказался более надёжной штукой.

    🙁

    Reply
  16. shiro93

    Добрый день.такая вот проблема при пробе подключиться к кто блокирует выскакивает ошибка SQL ERROR a_lock_sp :<<Microsoft OLE DB Provider for ODBC Drivers: [Microsoft][ODBC SQL Server Driver][SQL Server]Имя столбца или число предоставленных значений не соответствует определению таблицы.>>

    кто что подскажет?

    и еще время не хочет выводить ошибка: ГлавнаяТаблица.Время=СокрЛП(rs.Fields(«wait»).Value);

    {C:USERSSHYROBOKOV.ADESKTOPLOCKБЛОКИРОВКИ.ERT(97)}: Тип переменой не поддерживается

    Reply
  17. MadDAD

    (16) Версия SQL сервера какая?

    Reply
  18. shiro93

    (17) MadDAD, 2008 R2

    Reply
  19. shiro93

    со второй ошибкой времени разобрался. первая осталась еще

    Reply
  20. MadDAD

    (18) Обработка «КонфигурированиеБлокировок» отработала нормально? В глобальник все что нужно добавлено? Константы установлены?

    Reply
  21. shiro93

    (20) MadDAD, с этим все верно отработало. к другим подключается. к этой не хочет процедуре

    Reply
  22. shiro93

    (20) MadDAD, проблема где-то в этом участке:

    «set nocount on cre ate   table #locks (spid int,dbid int,ObjId int,IndId int, Type varchar(8),Resource varchar(30),Mode varchar(8),Status varchar(8)) ins ert #locks exec sp_lock cre ate   table #who(spid int,»+
    » ecid int, status varchar(20),loginame varchar(256), hostname varchar(256) ,blk char(5) null,dbname varchar(80)null, cmd  varchar(256) null) insert #who exec sp_who sel ect s.ROW_ID spid, left(d.name,15) as dbid, DESCR as name,»+
    » count(*) as QtyLock,convert(char(20),loginame) login,l.Status, convert(char(40),cmd) Command,convert(char(20),hostname) Host fr om #locks l, #who w, «+_txtTbl+» s, master..sysdatabases d where d.dbid=l.dbid and l.Mode<>’S’ and l.spid=w.spid and»+
    » s.ROW_ID=l.spid group by s.ROW_ID, left(d.name,15),DESCR, convert(char(20),loginame),l.Status, convert(char(40),cmd),convert(char(20),hostname) having s.ROW_ID<>@@SPID dr op   table #locks, #who se t nocount off return»;
    Reply
  23. MadDAD

    (22) _txtTbl в Вашем случае чему равно?

    Reply
  24. shiro93

    (23) MadDAD, это имя таблицы справочника

    Reply
  25. shiro93

    (23) MadDAD, разобрался в табл #who не хватало колонки для выполнения процедуры sp_who

    Reply
  26. mai13

    (25) shiro93, А можете дать точную информацию, чего не хватало и как решить проблему «wait» ?

    Reply
  27. Sure

    (26) mai13,

    Позвольте автору высказаться.

    В старой версии MS SQL процедура sp_who выдавала на одну колонку меньше.

    Лечение:

    cmd varchar(256) null)

    меняется на

    cmd varchar(256) null, request_id int)

    По поводу wait. По-видимому, 1С-у не нравится возвращаемое значение. Попробуйте заменить

    max(waittime) wait

    на

    str(max(waittime),18,0) as wait

    Reply
  28. putinpe

    ГлавнаяТаблица.Время=Время-тблЗагруженность.Время;

    {C:USERSPOLGIN.DDESKTOPНОВАЯ ПАПКА (4)БЛОКИРОВКИ.ERT(214)}: Операция вычитания не определена для строковых величин

    как править?

    Reply
  29. putinpe

    Почему та таблица в которой данные по Активным пользователям не очищается?

    Почему в той таблице показываются все БД которые на сервере?

    Reply
  30. putinpe
    Если Вы используете терминальный сервер (Citrix), а подключение к с серверу SQL идёт через один логин и пароль, то стандартные средства MS SQL не дают возможность различать пользователей и определять «виновника».

    Предлагаемая обработка решает эту проблему.

    У меня путает Базы . Я зашел в базу «TEST BLOсK» в показывает что в «TORG»

    Конфа такая

    1с 7.7

    sql 2005

    Терминальный доступ

    100 человек все в 1с

    Как мне сделать что бы все это заработало?

    Reply
  31. Sure

    (28) putinpe, По-видимому, нужно преобразование:

    ГлавнаяТаблица.Время=Число(Время)-Число(тблЗагруженность.Время);
    Reply
  32. Sure

    (30) putinpe,

    Для того, чтобы можно было видеть пользователей во всех базах, нужно во всех базах произвести доработки и воспользоваться предложенным в (12) ответом.

    А иначе — смотрите на пустых пользователей

    Reply
  33. Sure

    Когда пользователь заходит в базу, то в процедуре ПриНачалеРаботыСистемы() в таблицу «АктивныеПользователи» записывается его имя. Если пользователь выходит из системы регламетным способом, то в процедура ПриЗавершенииРаботыСистемы() имя очищается.

    Если же пользователь выходит из системы «нерегламентно», то есть при снятии задачи, при kill в SQL, при ошибке и т.п., то процедура ПриЗавершенииРаботыСистемы() не запускается, имя не очищается.

    Если в других базах (не обязательно 1С-ных) на SQL работает пользователи, то в таблице «АктивныеПользователи» они не регистрируются.

    Более того, если пользователь запускает обработку, применяющую SQL запросы через ODBC, ADO, то такие запросы имеют дополнительные входы на SQL сервер. Которые также не регистрируются в таблице «АктивныеПользователи». Да, это недостаток предлагаемого решения.

    Feci quod potui, faciant meuora potentes.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *