пятница, 23 октября 2015 г.

1С: Эксперт. Решение билета №4

Вопрос 4.1.  Обработчик проведения содержит следующий фрагмент. Укажите на неоптимальности.

// Запрос к остаткам
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|     Товары.Номенклатура КАК Номенклатура,
|     Товары.Количество КАК Количество,
|     Остатки.КоличествоОстаток КАК Остаток
|ИЗ
|     (ВЫБРАТЬ
|          Товары.Номенклатура КАК Номенклатура,
|          СУММА(Товары.Количество) КАК Количество
|     ИЗ
|          Документ.Реализация.Товары КАК Товары
|     ГДЕ
|          Товары.Ссылка = &ДокументСсылка
|     СГРУППИРОВАТЬ ПО
|          Товары.Номенклатура) КАК Товары
|ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(,) КАК Остатки
|     ПО Остатки.Номенклатура = Товары.Номенклатура
|ГДЕ
|     Остатки.Склад = &Склад";

Запрос.УстановитьПараметр("ДокументСсылка", ТекущийДокумент);
Запрос.УстановитьПараметр("Склад", СпрСклады.НайтиПоНаименованию("Основной"));
ВыборкаОстатков = Запрос.Выполнить().Выбрать();

Пока (ВыборкаОстатков.Следующий()) Цикл    
     // Запрос к лимитам
     Запрос.Текст = "ВЫБРАТЬ Лимиты.Лимит КАК Лимит
     |ИЗ РегистрСведений.Лимиты КАК Лимиты
     |ГДЕ Лимиты.Номенклатура = &Номенклатура";
   
     Запрос.УстановитьПараметр("Номенклатура", ВыборкаОстатков.Номенклатура);
     ВыборкаЛимитов = Запрос.Выполнить().Выбрать();
     ВыборкаЛимитов.Следующий();
   
     // Остаток по товару после списания, должен быть больше установленного лимита
     Если (ВыборкаОстатков.Остаток - ВыборкаОстатков.Количество < ВыборкаЛимитов.Лимит) Тогда
          Сообщить ("Документ не проведен, превышен лимит!");
          Отказ = Истина;
     КонецЕсли;    

КонецЦикла;

Ответ:
1) Условие по складу перенести в  параметры вирт. таблицы
2) Запрос в цикле. Лимиты нужно получать в самом запросе.
3) Соединение с вирт. таблицей. Оптимальнее вирт. таблицу предварительно поместить во ВТ.

Вопрос 4.2. Имеется информационная система работающая в клиент-серверном варианте с использованием MSSQL. В системе работает большое количество пользователей, которые не получают сообщений об ошибках.
Как получить ответы на следующие вопросы:
Происходят ли ожидания на блокировках при работе пользователей?
Какое общее время система проводит в режиме ожиданий на блокировках?
Ответ:
Ответы на эти вопросы можно получить с помощью ЦУП 
Происходят ли ожидания на блокировках при работе пользователей - по оперативному показателю "Среднее время ожидания на блокировках СУБД и 1С". Если значения >0 значит ожидания на блокировках есть.
Какое общее время система проводит в режиме ожиданий на блокировках? - По значению в колонке "Сумма" показателя "Суммарное время ожидания на блокировках СУБД и 1С".
Вопрос 4.3. Назовите известные Вам типичные ошибки в коде конфигурации и структуре метаданных, которые могут привести к неоптимальной работе запроса.
Дайте рекомендации по устранению ошибок 
Ответ:
  1. Соединения с подзапросами.
  2. Соединения с виртуальными таблицами.
  3. Подзапрос в условии соединения.
  4. Фильтрация не в параметрах виртуальной таблицы, а на закладке условия.
  5. Несоответствие индекса заданным условиям.
  6. Ошибки при работе с полями составного типа.
  7. Разыменование полей.
  8. Запросы в цикле, кореллированные запросы.
Для п1-3 одна рекомендация - использовать временные таблицы и соединять с ВТ по проиндексированным полям.
Для п.4 требуется фильтры накладывать в параметрах виртуальных  таблиц.
По п.5. существует несколько причин по которым индекс не может быть использован
1) Чтобы поиск по индексу был использован поля на которые накладываются условия должны быть в индексе без зазоров и начинаться с самого первого поля.
2) Использование логического "ИЛИ" в запросе. Следует заменить на объединения нескольких таблиц с помощью "ОБЪЕДИНИТЬ ВСЕ"
3) Арифметические выражения в условиях, функции месяц.
4) Использование операторов (Не, не В, Не подобно). Следует заменить на "ЕСТЬ NULL" в условии соединения
По п6. Есть несколько ошибок при работе с полями составного типа
1) Обращение через точку к реквизитам полей составного типа. Следует ограничить количество полей с помощью ВЫРАЗИТЬ.
2) Использование  примитивных полей вместе с ссылочными в субконто.
3) Регистратор, Субконто,Последовательность -это как правило поля составного типа. Желательно например избегать таких  вытягиваний как Регистратор.Дата.
4) Обращение через .Cсылка через полю ссылочного типа.
5) Использование ссылочных полей в конструкции ВЫБОР КОГДА
6) Соединения таблиц по полю составного типа.
По п7. Лучше в явном виде добавить таблицу и соединить 2 таблицы.
По п 8. Избегать неявных запросов в цикле. 

четверг, 22 октября 2015 г.

В данной транзакции уже происходили ошибки или попытка не пытка.


Рано или поздно каждому программисту 1с придется познакомится с сообщением об ошибке "В данной транзакции уже происходили ошибки".
В этой статье разберем природу этой ошибки.
Данная ошибка появляется при использовании конструкции Попытка... Исключение внутри транзакции. Дело в том, что если  исключительную ситуацию отрабатывать с помощью скобок Попытка...Исключение...КонецПопытки, расположенных внутри транзакции, то транзакция не завершится в момент возникновения исключительной ситуации, она дойдет до следующего обращения к данным — чтения или записи, продолжая при этом блокировать ресурсы, и откатится с сообщением: «В данной транзакции уже происходили ошибки!». 

НачатьТранзакцию();
//первая попытка
Попытка
Исключение
КонецПопытки;

//вторая попытка
Попытка
Исключение
КонецПопытки;

РезультатЗапроса = Запрос.Выполнить();
ЗафиксироватьТранзакцию();

В  схеме описанной выше ошибка возникнет в строке РезультатЗапроса = Запрос.Выполнить();
Первая неприятность заключается в том, что совершенно не понятно в какой из попыток выше приключилась ошибка, что затрудняет ее поиск и исправление ведь зачастую ОписаниеОшибки()  ничего не сообщает. Вторая неприятность заключается в том, что эти сообщения не могут вызывать положительных эмоций у пользователей, которые часто спешат поделится ими с руководством, а дальше Вы сами знаете).
Таким образом использование Попытка...Исключение... КонецПопытки в транзакции никоим образом не решает наших проблем. 
Поэтому следует по возможности хорошенько подумать как избежать вообще использования попыток в транзакции. 
В моей практике был подобный случай. Фоновые задания загружали в систему заказы от контрагентов. Поначалу мы легкомысленно использовали конструкцию Попытка...Исключение... КонецПопытки. В итоге загрузка спотыкалась, заказы не загружались, все нервничали. Изменить ситуацию удалось очень тщательным предварительным разбором файла перед загрузкой и в случае проблем отправление письма клиенту и на саппорт.
Если же без попытки ни как то следует отработав исключительную ситуацию, вызывать оператор ВызватьИсключение 
Описанное поведение системы позволяет говорить о том, что если возникает ситуация, когда внутри транзакций нужно использовать скобки
Попытка...Исключение... КонецПопытки, необходимо, отработав исключительную ситуацию, вызывать оператор ВызватьИсключение. В таком случае выполнение кода завершится в конце попытки и дальше не пойдет, таким образом пользователи не увидят ошибку «В данной транзакции уже происходили ошибки!». 
Однако не всегда ошибочная ситуация приведет к появлению такой ошибки, это зависит от того восстановимая ошибка случилась или нет. Например:
Попытка
а =6/0;
Исключение
КонецПопытки;
Не приведет к появлению ошибки «В данной транзакции уже происходили ошибки!».
а вот следующий код системе не сможет "прожевать" и ошибка появится.

СпрНом = Справочники.Товары.СоздатьЭлемент();
СпрНом.Код ="000001" // товар с таким кодом уже был создан ранее
Попытка
СпрНом.Записать();
Исключение
КонецПопытки;

Также не упущу возможность развеять один миф в плену которого я и сам находился.
Миф звучит так "Попытка Исключение организует неявную транзакцию". Причем это сообщение от одного весьма известного методиста на форуме.
На самом деле это не так. Никакой неявной транзакции Попытка Исключение не организует.
Подведем итоги:
1) Крайне нежелательно использовать конструкцию Попытка...Исключение... КонецПопытки в транзакции.
2) Если уж без этого не обойтись то использование оператора ВызватьИсключение уберет появление ошибки "В данной транзакции уже происходили ошибки".




Обработка "Настройка технологического журнала"

Продолжая ранее начатую тему работы с технологическим журналом решил что было несправедливо не упомянуть обработку "Настройка технологического журнала. Главное что может эта  обработка -это сэкономить ваше драгоценное время. Скачать обработку можно с сайта 1с или взять с диска ИТС. Обработка имеет интуитивно понятный интерфейс, может быть поэтому на странице скачивания и нет никакой инструкции и прочего.
Обработка также очень удобно что установив курсор на ячейке сразу можем увидеть описание текущих события и свойства.

Также обработку удобно использовать в справочных целях, хотя бы просто для того чтобы увидеть какие свойства доступны конкретному событию.
Теперь немного о грустном.
1) Не все задачи возможно решить с помощью этой обработки. Например нужно хранить логи разных событий в разных каталогах (Например действия администраторов admin в своей папке и таймауты в другой). Хотя возможно я не понял как это сделать.
2) При формировании конфигурационного файла записываются строки несколько раз. Например:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
 <dump create="false"/>
 <log location="C:\\" history="168">
  <event>
   <eq property="name" value="tdeadlock"/>
  </event>
  <property name="all">
   <event>
    <eq property="name" value="tdeadlock"/>
   </event>
  </property>
 </log>
</config>

Но идея в любом случае хорошая, будем следить за развитием)

1С: Эксперт. Решение билета №3

Вопрос 3.1.

Имеется регистр бухгалтерии «Хозрасчетный», с измерением «Организация» и субконто «Контрагенты». Будут ли перечисленные пары операций выполняться параллельно из разных сессий? Возможные блокировки на границах диапазона индекса не учитываются. Что изменится если включить разделитель итогов? (остатки не контролируются).


Параллельность      Операция 1 Операция 2

Запись набора записей: Счет = 41.01  
Организация = «Рога и Копыта»
Контрагент «Ромашка»

Запись набора записей: Счет = 41.01
Организация = «Рога и Копыта»
Контрагент «Ромашка»

Запись набора записей: Счет = 41.01
Организация = «Рога и Копыта»
Контрагент = «ОАО МосИнвест»

Чтение остатков с условием: Счет = 41.01
Организация «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»

Чтение остатков с условием
Счет = 41.01
Организация = «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
Чтение остатков с условием
Счет = 41.01
Организация - «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»




Ответ:

1) Без разделителя
Параллельность      Операция 1 Операция 2
НЕТ
Запись набора записей: Счет = 41.01  
Организация = «Рога и Копыта»
Контрагент «Ромашка»

Запись набора записей: Счет = 41.01
Организация = «Рога и Копыта»
Контрагент «Ромашка»
ДА
Запись набора записей: Счет = 41.01
Организация = «Рога и Копыта»
Контрагент = «ОАО МосИнвест»

Чтение остатков с условием: Счет = 41.01
Организация «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
ДА
Чтение остатков с условием
Счет = 41.01
Организация = «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
Чтение остатков с условием
Счет = 41.01
Организация - «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
2) С разделителем

ДА
Запись набора записей: Счет = 41.01  
Организация = «Рога и Копыта»
Контрагент «Ромашка»
Запись набора записей: Счет = 41.01
Организация = «Рога и Копыта»
Контрагент «Ромашка»
ДА
Запись набора записей: Счет = 41.01Организация = «Рога и Копыта»
Контрагент = «ОАО МосИнвест»
Чтение остатков с условием: Счет = 41.01
Организация «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
ДА
Чтение остатков с условием
Счет = 41.01
Организация = «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»
Чтение остатков с условием
Счет = 41.01
Организация - «Безенчук и Ко»
Контрагент = «ОАО МосИнвест»


Вопрос 3.2.
Что такое план запроса и зачем он нужен. Кто и когда формирует план запроса? Можно ли повлиять на выбор плана запроса.
Ответ:
План запроса это способ с помощью которого оптимизатор получает данные из таблиц СУБД. Формирует план запроса оптимизатор СУБД перед выполнением запроса. Повлиять на выбор плана запроса нельзя.

Вопрос 3.3 Имеется информационная система работающая в клиент-серверном варианте с использованием MSSQL. 
Пользователь 1 выполняет длинный запрос в транзакции.
Пользователь 2 выполняет свой запрос и оказывается заблокированным пользователем 1. Перечислите все известные Вам способы получения информации об этой блокировке. Перечислите информацию которая при этом будет получена.
Ответ:
Информацию можно получить как оперативно:
1) С помощью консоли кластера серверов. Показывает Кто кого заблокировал, длительность блокировки, гранулярность. 
2)С помощью монитора активности. Показывает кто кого заблокировал (id сеансов),какой ресурс ,если конфигурация в автоматическом режиме, то можно увидеть и текст запроса на языке SQL, гранулярность, режим(тип блокировки).
И неоперативно
3)Можно запустить ЦУП и собрать анализ ожиданий на блокировках.  Можно увидеть всю вышеперечисленную информацию.
4) SQL profiler. С помощью фильтра lock acquired> 1мс; (ресурс, длительность, режим,гранулярность,  id кого забокировали.






среда, 21 октября 2015 г.

1С: Эксперт. Решение билета №2

 К сожалению билет №2 достался в обрезанном виде, без третьего вопроса.


Вопрос 2.1
Регистр накопления имеет следующую структуру:
Измерения: Склад,т
овар;
Ресурсы:  Остаток

Будут ли перечисленные пары операций выполняться параллельно из разных сессий? Возможные блокировки на границах диапазона индекса не учитываются.
Что изменится если включить разделитель итогов? (остатки не контролируются)


ПараллельностьОперация1Операция2

Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Стул»

Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Телевизор»

Чтение с опцией "Для изменения" остатков регистра по условию
Склад= «Основной»
Товар = «Стул»

Чтение без опции "Для изменения"  остатков регистра по условию
Склад= «Основной»
Товар = «Стул»
Чтение без опции "Для изменения"  остатков регистра по условию
Склад= «Основной»
Товар = «Стул»
Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Стул»

Ответ:


ПараллельностьОперация1Операция2
+
Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Стул»

Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Телевизор»
+
Чтение с опцией "Для изменения" остатков регистра по условию
Склад= «Основной»
Товар = «Стул»

Чтение без опции "Для изменения"  остатков регистра по условию
Склад= «Основной»
Товар = «Стул»
 -
Чтение без опции "Для изменения"  остатков регистра по условию
Склад= «Основной»
Товар = «Стул»
Запись набора записей со следующими значениями измерений:
Склад= «Основной»
Товар = «Стул»

Если включить разделитель итогов? (остатки не контролируются) то ничего не изменится.



Вопрос 2.2
В конфигурации установлен «Автоматический и управляемый» режим. Пользователь проводит Документ1, у документа установлен «Автоматический» режим управления блокировкой данных. Документ создает движения по регистру накопления Регистр1, для регистра установлен «Управляемый» режим. В модуле регистра проверяются остатки, при этом считываются и блокируются некоторые записи остатков регистра. В какой момент будет снята блокировка с этих записей? Что изменится если поставить документу режим управляемый?


Ответ:
В какой момент будет снята блокировка с этих записей?
Транзакция будет выполнена в автоматическом режиме, следовательно, будут использовать только блокировки СУБД.
По условию задачи сначала идет запись движений, и только потом проверяются остатки (в модуле регистра). При записи накладывается X блокировка которая всегда держится до конца транзакции (до конца проведения документа).
Что изменится если поставить документу режим управляемый?
Блокировка также будет снята только после выполнения транзакции, только теперь это будет управляемая блокировка.




вторник, 20 октября 2015 г.

1С: Эксперт. Решение билета №1

Этой заметкой начинаю мини цикл по решению билетов к экзамену 1с: эксперт по технологическим вопросам крупных внедрений. Не помню точно где в сети нашел несколько билетов (точно говоря 10). Многие вопросы с самого начала могут быть совершенно непонятными (так и было со мной когда я первый раз их увидел), так что может случится что для понимания необходимо будет разобраться теме. Вопросы связанные с подготовкой к экзамену меня на данный момент (20.10.15) особо интересуют так что буду рад вашим вопросам и замечаниям в комментариях.


Вопрос 1.1
В метаданных определены две константы:
  • Конст1
  • Конст2

Будут ли перечисленные пары операций выполняться параллельно из разных сессий?


Ответ:
Ответ будет зависеть от версии платформы. Дело в что начиная с версии 8.2.14 каждая константа стала хранится в отдельной таблице, а в более ранних версиях все константы хранились в одной таблице.
Таким образом если версия ниже 8.2.14 или используется режим совместимости с версией 8.2.14 и  ниже, то ответ будет следующим:


Параллельность       Действие 1             Действие 2
            -                   Чтение Конст1        Запись Конст 1
            -                   Запись Конст1        Запись Конст2
           +                  Чтение Конст1        Чтение Конст1


в случае 8.2.14 и выше
Параллельность        Действие 1             Действие 2
             -                      Чтение Конст1        Запись Конст 1
            +                      Запись Конст1        Запись Конст2
            +                      Чтение Конст1        Чтение Конст1



Вопрос 1.2

Ответ:
Так как не сказано  какой режим управления блокировками установлен для конфигурации, то примем что транзакция  будет выполняется в управляемом режиме. 
Будут установлены следующие блокировки:
1) В строке Номенклатура = ВыбраннаяНоменклатура.ПолучитьОбъект() 
Будет установлена S блокировка на уровне СУБД при чтении объекта, которая снимется после ПолучитьОбъект();
Управляемая блокировка установлена не будет.
2) При выполнении команды Номенклатура.Записать() будут установлены как управляемая исключительная блокировка так и X блокировка СУБД.
Обе блокировки будут держатся до конца транзакции.

Если несколько пользователей одновременно будут изменять одну и туже номенклатуру возможна ситуация когда одна из транзакций получит
сообщение об ошибке о том, что данные изменены или удалены.

Вопрос 1.3
Ответ:
Указанные избыточные блокировки характерны только для автоматического режима управления блокировками. Следовательно необходимо перевести конфигурацию в управляемый режим. Делается это так: сначала  необходимо установить режим для конфигурации "Управляемый и автоматический" и затем постепенно переводить на  упр. режим для документы и регистры.


четверг, 1 октября 2015 г.

Работа над ошибками. Задача 1.10.

Иногда бывает посмотришь на код, и думаешь "Кто это сделал, руки бы ему поотрывать", и не хочется верить что это написал ты сам еще год назад.  Решил посмотреть на решение своей первой задачи и вот что из этого вышло.


1) Модуль документа "Приходная накладная".
       Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.Себестоимость.Записывать       = Истина;

Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Движение.ЕдиницаИзмерения = ТекСтрокаСписокНоменклатуры.ЕдиницаИзмерения;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;
КонецЦикла;

Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл
Движение = Движения.Себестоимость.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Движение.ЕдиницаИзмерения = ТекСтрокаСписокНоменклатуры.ЕдиницаИзмерения;
Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;
Движение.Сумма =ТекСтрокаСписокНоменклатуры.Сумма;
КонецЦикла;

Зачем 2 цикла? Конечно же все нужно запихнуть в 1 цикл.

Переходим к "Расходной накладной".

2)   Для каждого Стр Из СписокНоменклатуры Цикл
Если Стр.Номенклатура.ВидТовара = Перечисления.ВидыНоменклатуры.Услуга Тогда
Продолжить;
КонецЕсли;

Это неявный запрос в цикле. При такой конструкции каждый раз СУБД строит запрос в которой соединяет таблицу "Номенклатуры" с таблицей "ВидНоменклатуры". При большом количестве строк замедление может быть заметным.
Ил ладно бы еще эта проверка была нужна, но в запросе и так указано условие 
РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидТовара <> &ВидТовара
Так зачем же еще в было цикле добавлять это?.
Кроме того в условиях лучше использовать проверку на равенство, вместо условий "Не", "Не В", "< >".

3)  Можно было бы использовать ЗаполнитьЗначенияСвойств вместо
Движение = Движения.ОстаткиНоменклатуры.ДобавитьРасход();
Движение.Период           = Дата;
Движение.Склад            = Склад;
Движение.Номенклатура            = Стр.Номенклатура;
Движение.ЕдиницаИзмерения = Стр.ЕдиницаИзмерения;
Движение.Количество       = Стр.Количество;
но это не окажет никакого заметного влияния на производительность.

4) В самом начале табличная часть документа помещается во временную таблицу. И это хорошо. Но временную таблицу нужно индексировать по всем полям, которые будут участвовать в дальнейшем соединениях таблиц, а до изменений было только по номенклатуре.

5) В первом запросе есть неоптимальность которая называется "Соединение с виртуальной таблицей". Временная таблица соединялась с виртуальной. А ВТ тут вообще и не нужна, так как мы ни одного поля из нее не извлекаем.
Оптимальнее будет так:
ВЫБРАТЬ
ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
ОстаткиНоменклатурыОстатки.Номенклатура.Представление,
ОстаткиНоменклатурыОстатки.Номенклатура КАК Номенклатура,
ОстаткиНоменклатурыОстатки.Склад КАК Склад,
ОстаткиНоменклатурыОстатки.ЕдиницаИзмерения КАК ЕдиницаИзмерения
ИЗ
РегистрНакопления.ОстаткиНоменклатуры.Остатки(
&ТочкаИтогов,
(Склад, Номенклатура, ЕдиницаИзмерения) В
(ВЫБРАТЬ
ДокТЧ.Склад,
ДокТЧ.Номенклатура,
ДокТЧ.ЕдиницаИзмерения
ИЗ
ДокТЧ)) КАК ОстаткиНоменклатурыОстатки
ГДЕ
ОстаткиНоменклатурыОстатки.КоличествоОстаток < 0




6)        Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры ;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать(); 

Я вообще-то не пью и не курю,но глядя на это верится с трудом) 
Блокировка не того регистра. Нужно блокировать регистр "СебестоимостьНоменклатуры".

7) Во втором запросе та же проблема, что и в первом "Соединение с виртуальной таблицей".
В отличие от первого запроса,в этом пригодятся поля из ВТ. Поэтому лучше поступить так.
Первым запросом пакета данные из виртуальной таблицы помещаем во ВТ и затем во втором запросе соединим полученные ВТ.
Запрос примет следующий вид:
ВЫБРАТЬ
ДокТЧ.Номенклатура,
ДокТЧ.ЕдиницаИзмерения,
ДокТЧ.Количество,
ДокТЧ.Склад,
ЕСТЬNULL(СебестоимостьОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
СебестоимостьОстатки.Номенклатура.Представление,
ЕСТЬNULL(СебестоимостьОстатки.СуммаОстаток, 0) КАК ОстатокСум
ИЗ
ДокТЧ КАК ДокТЧ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Себестоимость.Остатки(
&ТочкаИтогов,
Номенклатура В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ДокТЧ.Номенклатура
ИЗ
ДокТЧ)) КАК СебестоимостьОстатки
ПО ДокТЧ.Номенклатура = СебестоимостьОстатки.Номенклатура
И ДокТЧ.ЕдиницаИзмерения = СебестоимостьОстатки.ЕдиницаИзмерения




8)  Не решена "Проблема копеек".

               Если   Выборка.ОстатокКол <> 0 Тогда
Движение.Сумма = (Выборка.ОстатокСум/ Выборка.ОстатокКол) *Выборка.Количество;
КонецЕсли;

нужно как-то так

               Если Выборка.ОстатокКол =Выборка.Количество Тогда
Движение.Сумма = Выборка.ОстатокСум;
ИначеЕсли    Выборка.ОстатокКол <> 0 Тогда
Движение.Сумма = (Выборка.ОстатокСум/ Выборка.ОстатокКол) *Выборка.Количество;
КонецЕсли;
9)  Есть еще ошибка.

//Запрос.Параметры.Вставить("ТочкаИтогов", МоментВремени());
Дело тут в чем.  Когда мы очищаем движения методом "очистить" старые движения еще "висят" в памяти. И если мы оперативно перепроведем документ то получим ошибку, так как на остатках товар не появился. 
Следует добавить очистку регистра при оперативном проведении

Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Движения.Себестоимость.Записать();
КонецЕсли;

10)  Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Движения.Себестоимость.БлокироватьДляИзменения = Истина;
КонецЕсли; 
Эти строчки кода демонстрируют полное непонимание назначение свойства "БлокироватьДляИзменения", которое никак не связано с режимом проведения.

Свойство "БлокироватьДляИзменения" позволяет параллельно записывать одинаковые наборы данных в регистр, но использовать его нет большого смысла если после записи идет проверка остатков. Кроме того использование этого свойства может привести к взаимоблокировке по причине повышения уровня изоляции. Таким образом Для регистра "ОстаткиНоменклатуры" можно вообще отключить это свойство в регистре.(Так как после записи идет проверка). А для регистра "Себестоимость" такой проверки нет и это свойство имеет смысл установить. 

11) В отчете соединения виртуальных таблиц, что тоже не очень хорошо, лучше бы как и в документе помещать данные виртуальных таблиц во временные таблицы, которые между собой потом соединить.(Но этого я уже делать не буду).

Возможно остались еще какие-то моменты, но пока достаточно как мне кажется.