<?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='\
А кто-нибудь исследовал чем отличается инструкция (взятая с сайта Гилева):
USE [master]
GO
ALTER DATABASE [Моя База] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE [Моя База]
SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE [Моя База]
SET READ_COMMITTED_SNAPSHOT ON
ALTER DATABASE [Моя База] SET MULTI_USER WITH ROLLBACK IMMEDIATE
GO
От того, что есть по умолчанию в 1С в режиме совмести 8.3.6 и выше?
Пробовал, когда нужно было принудительно включить RCSI, но конфигурация была совместима только с 8.2. Работает.
Несколько вопросов по статье:
•
— разве без БлокировкаДанных это будет не READ UNCOMMITTED?
•
и ниже
— то есть при repeatable read получили dirty read?
• Не увидел ссылку на обработку.
•
— книга хорошая, написано верно, ведь Postgre чистый версионник, а ms sql — блокировочник.
(3) CSiER,
Поддержу вопрос коллеги.
Разве грязное чтение не исчезает на уровне изоляции READ COMMITED и выше?
В принципе то же самое рассказывают на курсах подготовки к эксперту/профессионалу по тех.вопросам. Единственное, что после курсов вопросы из комментов не возникают. ))
(3) CSiER,
Надо разделять менеджер блокировок MSQL и менеджер блокировок 1С.
Когда у вас включен автоматический режим блокировок, то работает только менеджер блокировок MSQL, при этом используется уровень изоляции транзакций repeatable read и serializable.
Причем это не сам MSQL решает какой уровень изоляции использовать при получении данных, а это сервер 1С при передаче запроса на выполнение MSQL «говорит» какой уровень изоляции для какой таблицы необходимо установить. Т.е. тут за блокировку полностью отвечает MSQL.
Когда вы включаете управляемый режим блокировок, то начинает работать менеджер блокировок 1С. И соответственно сервер 1С решает что для MSQL будет достаточным уровень изоляции транзакций read commited т.к. за блокировку данных будет отвечать сам сервер 1С. В этом случае MSQL фактически ничего не блокирует.
А «БлокировкаДанных » — это фактически команда серверу 1С, что необходимо наложить блокировку на определенные данные.
Т.е. не взирая на то используем мы или нет «БлокировкаДанных «, на уровне MSQL всегда будет использоваться read commited.
(3) CSiER,
В статье же написано про 2 сеанса.
В первом сеансе у нас устанавливается блокировка с уровнем изоляции repeatable read.
А вот ВО ВТОРОМ сеансе у нас будет видно dirty read.
Т.к. в приведенном примере стоит уровень совместимости с 8.2, то read commited snaphot не используется. Соответственно когда пользователь во втором сеансе открывает форму списка, то фактически сервер 1С передает запрос MSQL с хинтом «with no lock». Что фактически означает что будут прочитаны все данные в т.ч. данные не зафиксированных транзакций. Поэтому именно ВО ВТОРОМ сеансе будет наблюдаться грязное чтение, невзирая на то что в первом сеансе на этих записях стоит блокировка с уровнем узоляции repeatable read.
(6) headMade, а вот г-нФилиппов на курсах, помнится, говорит о том, что блокировки MS SQL все-таки устанавливает. В режиме 8.2 — реад комиттед, в режиме 8.3 — реад комиттед снапшот. В профайлере при этом нет инструкции WITH (NOLOCK), но даже наличие WITH (NOLOCK) не гарантирует их отсутствие.
(1) Сурикат, ничем не отличается, просто 8.3 это делает сама
(8) Вы путаете блокировки с уровнями изоляции транзакций. И блокировки у MSSQL бывают разные, есть много вспомогательных. С практической точки зрения важно то, что в режиме изоляции «реад комиттед снапшот» читающие транзакции не «держат» пишущие транзакции и наоборот. И при этом прочитанные данные всегда согласованы, как при repeatable read.
Ну и да — включение режима «реад комиттед снапшот» по сути меняет поведение MSSQL с «блокировочника» на «версионник». MSSQL начинает фигачить версии изменяемых строк в tempdb и при чтении брать данные подходящих версий оттуда, а не из родных таблиц.
В отличие от старых уровней изоляции — это механизм совершенно другого качества. Поэтому его еще надо явно активировать в свойствах конкретной БД.
(7) headMade, спасибо за ответ, вроде все понятно, но, чувствую, только повторение шагов автора с профайлером окончательно расставят все точки на «и» в моей голове )
(8) starik-2005,
Конечно же блокировки всегда устанавливаются. Важное значение имеет с каким уровнем изоляции они устанавливаются и когда они снимаются.
В некоторых случаях блокировка держится до конца транзакции (при repeatable read), а в некоторых снимается сразу после выполнения запроса (read commited).
— естественно можно еще рассматривать блокировки стабильности схемы или блокировки намерений, но они на параллельность работы пользователей в 1С никак не влияют.
(13) лично я вот конкретно на это отвечал:
А есть такая еще штука, как эскалация блокировок. Может внезапно оказаться, что блокируется вся таблица в SQL, при том 1С вроде как заблокировала только часть данных (до 100к).
(14)
Ну, эти страшилки остались в прошлом, слава богу. Такое было не редкость в режиме автоматических блокировок, где на MSSQL при проведении использовался serializable — самый строгий режим изоляции, беспощадный по блокировкам. В postgresql вообще были табличные блокировки.
А сейчас на версионниках с управляемыми блокировками одинэсник в самом деле фактически самолично управляет блокировками. Я не представляю, что нужно сделать, чтобы спровоцировать экскалацию блокировок СУБД в этой ситуации. Перезаписывать значительную часть большой таблицы в одной транзакции, разве что. Так тогда так и так разница невелика. И то помешает эта эскалация только другим транзакциям на запись.
(9) Sergey.Noskov,
https://msdn.microsoft.com/ru-ru/library/tcbchxcb(v=vs.110).aspx):
1С ставит только SET READ_COMMITTED_SNAPSHOT ON
Хотя на MSDN написано (
Перед использованием в транзакциях изоляция моментального снимка должна быть включена путем установки параметра базы данных ALLOW_SNAPSHOT_ISOLATION в значение ON. Это приводит к активизации механизма сохранения версий строк во временной базе данных (tempdb).
Собственно вопрос был:
Как работает READ_COMMITTED_SNAPSHOT без ALLOW_SNAPSHOT_ISOLATION?
(16) Сурикат,
ссылка нерабочая
(17) headMade, там последние 2 символа зацепило.Вот верная
(15) herfis,
обмен 500 новых контрагентов с 10 дополнительными значениями. Сущий пустяк правда?)
А, ещё один пересказ общедоступных источников…
(20) Yashazz,
Ну не вредничайте.
Статья полезная, а общедоступные источники еще нужно найти и вычитать там именно то что нужно.
Статья хорошая
(19)
Скорее белиберда какая-то.
(19)мильёнами грузим ежедневно. Так что ЭТО пустяк.