понедельник, 1 апреля 2013 г.

Ошибка СУБД Microsoft OLE DB Provider for SQL базы 1С Предприятие 8.2

В пятницу под вечер случилась скажем так, неприятная вещь. Из отделов начали жаловаться на  ошибку табличных частей. С программистами 1с, пытались решить данную проблему в кротчайшие сроки, но ничего на ум особого не приходило. Ошибка следующего характера:

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Недопустимое имя объекта "_Document179_VT3549".
HRESULT=80040E37, SQLSrvr: SQLSTATE=42S02, state=1, Severity=10, native=208, line=1

Ошибка хоть и не была критичной, но не давала работать людям. Решили оставить все на понедельник. Понедельник наступил, а решения проблемы так и не появилось. Были предприняты попытки связаться с интегратором, чтобы он хоть чем-то помог. В основном поступали предложения о том, чтобы загрузить Конфигуратор и попытаться выгрузить/загрузить базу, а также отсоединить/присоединить. Из-за большого объема данных, это бы заняло на нашем даже производительном сервере по меньшей мере сутки! Это нас не устраивало естественно. Часа 2 я искал в интернете решение проблемы и тут от интегратора получил сообщение:

Попробуйте залить в демо базу архив скажем недельной давности и проверить структуру таблиц, есть ли там например такая строчка  "_Document188_VT3785". 

Естественно я до этого почему-то не догадался :( Был взят бэкап недельной давности, а точнее за 25 число и загружен в демо базу. В табличной части была найдена данная таблица, которая содержала порядка 2500 строк информации. А дальше, дальше я уже понял, что нужно делать. Распишу по пунктам, мало ли сам забуду или кому-нибудь пригодиться.

1. Самое немаловажное это бэкап где нет битых табличных частей и структур. Если он у вас есть, значит переходим ко второй части. Если нет, то думаем кого пинать и ругать, т.к. это неотъемлемая часть в сохранности информации в компании.
2. Заливаем бэкап в демо базу. Я не использовал консоль, у меня есть Microsoft Managment Studio 2008, поэтому мне было проще. Кто любит извращаться с помощью консоли - Бога ради, пусть делает запросы с помощью нее.
3. Собираем все ошибки воедино, т.е. те которые появляются у пользователей на Недопустимое имя объекта. У меня их обнаружилось всего две, но есть подозрение, что их гораздо больше. (Ошибка таблицы "_Document179_VT3549" и "_Document188_VT3785").
4. Смотрим в "Плохую базу" есть ли такие табличные части. Если нет, а их скорее всего нет делаем следующее в демо базе: Находим строку dbo._Document179_VT3549 --> Нажимаем правой кнопкой мыши и выбираем Создать сценарий для таблицы --> Используя CREATE --> Новое окно редактора запросов. Появиться окно с запросом CREATE:


USE [Torg_demo]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[_Document179_VT3549](
[_Document188_IDRRef] [binary](16) NOT NULL,
[_KeyField] [binary](4) NOT NULL,
[_LineNo3786] [numeric](5, 0) NOT NULL,
[_Fld3787RRef] [binary](16) NOT NULL,
[_Fld3788RRef] [binary](16) NOT NULL,
[_Fld3789RRef] [binary](16) NOT NULL,
[_Fld3790RRef] [binary](16) NOT NULL,
[_Fld3791] [numeric](15, 3) NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO


Выполняем его на "Плохой базе" предварительно изменив USE [Torg_demo] на USE [Torg]. В результате этого запроса, будет создана таблица. Проделываем данный пункт со всеми табличными частями к которым утрачен доступ и которые требуется создать заново. Напомню мне нужно было создать 2-е таблицы "_Document179_VT3549" и "_Document188_VT3785".
5. В "Здоровой базе" - демо, делаем следующее с таблицами которые нам требуется восстановить. Находим строку dbo._Document179_VT3549 --> Нажимаем правой кнопкой мыши и выбираем Создать сценарий для таблицы --> Используя SELECT, затем Используя INSERT. Должно появиться 2-а запроса (заготовки) к базе данных, которые обращаются к табличным частям. Их требуется объединить в один, по моему принципу: INSERT INTO <название таблицы> SELECT <имя столбца>,... FROM <название таблицы>. Данный запрос перенесет все данные которые были в демо базе в основную. 
Пример:


INSERT INTO [Плохая база].[dbo].[_Reference120_VT120]
            ([_Reference120_IDRRef]
            ,[_KeyField]
            ,[_LineNo1924]
            ,[_Fld1925RRef]
            ,[_Fld1926RRef])
SELECT
            [_Reference120_IDRRef]
            ,[_KeyField]
            ,[_LineNo1924]
            ,[_Fld1925RRef]
            ,[_Fld1926RRef])
FROM [Здоровая база].[dbo].[_Reference120_VT120]
GO


Конечный вариант который получился у меня для одной таблицы (проделываем со всеми, то же самое):


INSERT INTO [Torg].[dbo].[_Document179_VT3549]
           ([_Document179_IDRRef]
           ,[_KeyField]
           ,[_LineNo3550]
           ,[_Fld3551RRef]
           ,[_Fld3552RRef]
           ,[_Fld3553RRef]
           ,[_Fld3554]
           ,[_Fld3555]
           ,[_Fld3556]
           ,[_Fld3557]
           ,[_Fld7555]
           ,[_Fld9166]
           ,[_Fld9167RRef]
           ,[_Fld9168RRef]
           ,[_Fld9169RRef])
SELECT 
           [_Document179_IDRRef]
           ,[_KeyField]
           ,[_LineNo3550]
           ,[_Fld3551RRef]
           ,[_Fld3552RRef]
           ,[_Fld3553RRef]
           ,[_Fld3554]
           ,[_Fld3555]
           ,[_Fld3556]
           ,[_Fld3557]
           ,[_Fld7555]
           ,[_Fld9166]
           ,[_Fld9167RRef]
           ,[_Fld9168RRef]
           ,[_Fld9169RRef]
FROM [Torg_demo].[dbo].[_Document179_VT3549]
GO



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


понедельник, 26 сентября 2011 г.

Костылинг dhcp, или как заставить работать UTM5 c isc-dhcp

В данной статье я расскажу как все же заставить работать isc-dhcpd с биллинговой системой UTM5 от компании NetUP (Российская Федерация).

Данный костыль не рассчитывает быть полноценным, но его можно использовать на первое время, если у вас не особо то и сегментированная сеть. Если же вы используете в своей сети opt82 (выдача ip-адреса по порту коммутатора), то придется писать немного другой скриптик, но об этом в другой раз

Приступим.
На сервере dhcp должны быть установлены следующие программы и модули:
1. isc-dhcp30-relay-3.0.7
2. isc-dhcp30-server-3.0.7_5
3. p5-DBD-mysql50-4.013
4. p5-DBI-1.60.9
5. p5-Storable-2.21
6. perl-5.10.1 

Далее создаем каталог dhcp в /usr/local/etc/. Мне было удобно именно в этой папке, там же лежит и dhcpd.conf.

В /usr/local/etc/dhcp/ кладем вот такой файл на перле:
#!/usr/bin/perl
use DBI;
use DBD::mysql;
#use lib '/cktv/perl';
#use cktv::logger;

# Инициализация
#loginfo "Обновление DHCPD";
$dbh = DBI->connect("DBI:mysql:UTM5;192.168.1.1", "login", "password", {'RaiseError' => 1}) or die crit msg "Can't connect to DB!";

open F, ">", "/tmp/dhcpd.hosts.new";

# Получаем данные (192.168.xx.xx)
my $items = $dbh->selectall_arrayref( "SELECT inet_ntoa(ip & 0xFFFFFFFF) as ip, ip_groups.mac, accounts.is_blocked FROM ip_groups,iptraffic_service_links, service_links, users, accounts WHERE ip_groups.mac!='' AND accounts.id=users.basic_account AND service_links.user_id=users.id AND service_links.is_deleted='0' AND ip_groups.is_deleted='0' AND iptraffic_service_links.ip_group_id=ip_groups.ip_group_id AND service_links.id=iptraffic_service_links.id GROUP BY ip_groups.ip ORDER BY ip_groups.ip" );

# Таблица для поиска дублей
my ( %MAC, %IP ) = ();

for my $item ( @$items ) {
    my ( $ip, $mac ) = @$item;

    $mac =~ s/^\s+//;
    $mac =~ s/\s+$//;
    $mac = uc $mac;

    # Проверяем мак
    unless ( $mac ) {
        # DHCP не нужен
        next;
    } elsif ( $mac =~ /^[0-9A-F]{2}(?::[0-9A-F]{2}){5}$/ ) {
        # Мак правильный
    } elsif ( $mac =~ /([0-9A-F]{2})([0-9A-F]{2})\.?
                ([0-9A-F]{2})([0-9A-F]{2})\.?
                ([0-9A-F]{2})([0-9A-F]{2})/x ) {
        # Цисковский или просто числа
        $mac = "$1:$2:$3:$4:$5:$6";
        #crit msg "Fixed: $ip $mac";
         print "Fixed: $ip $mac";
    } else {
        #msg "Wrong: $ip $mac";
        print "Wrong: $ip $mac";
        next;
    }

    # Проверка на дубликаты
    if ( $MAC{$mac} ) {
        #crit msg "Duplicate MAC: $ip $mac";
 #       print 12;
        print "Duplicate MAC: $ip $mac";
        next;
    }

    if ( $IP{$ip} ) {
        #crit msg "Duplicate IP: $ip $mac";
        print "Duplicate IP: $ip $mac";
        next;
    }

    $IP{$ip} = 1;
    $MAC{$mac} = 1;

    # Сохраняем в конфиг
    $ip =~ /^(\d+\.\d+)\.(\d+)\.(\d+)$/;
        my $opt = '';

#    if ( $ip =~ /^123\.123\.123\./ ) {
#        # Внешний адрес нашего C-класса
#        $opt .= sprintf "option host-name pc_%03s_%03s; ", $2, $3;
#    }

     if ( $ip =~ /^123\.123\.123\./ ) {
        # Внешний адрес нашего C-класса
        $opt .= sprintf "option host-name host-%0s-%0s.broadband.domain.ru; ", $2, $3;
     }

#    printf F "host pc_%03s_%03s { hardware ethernet %s; fixed-address %s; option routers %s; }\n",
#        $2, $3, $mac, $ip, "$1.$2.1",$opt;

#    printf F "host $ip { hardware ethernet %s; fixed-address %s; option routers %s; }\n",
#        $mac, $ip, "$1.$2.1",$opt;

printf F "host $ip { hardware ethernet %s; fixed-address %s; }\n",
        $mac, $ip;
}

# Отключаемся
$dbh->disconnect;
close F;

Далее создаем в этой же папке /usr/local/etc/dhcp/ файл dhcp.sh следующего содержания:
#!/bin/sh

/usr/local/etc/dhcp/dhcp.pl

diff /etc/dhcpd.hosts /tmp/dhcpd.hosts.new > /dev/null >> /var/log/dhcpd_updater ||
(/usr/local/sbin/dhcpd -t -cf /usr/local/etc/dhcpd.conf 2>&1 &&
cp /tmp/dhcpd.hosts.new /etc/dhcpd.hosts &&
/usr/local/etc/rc.d/isc-dhcpd forcerestart 2>&1 &&
echo Reboot: \`date\` >> /var/log/dhcpd_updater); 

И ставим этот файл на запуск в крон. Как вашей душе угодно я выставил каждые 10 минут.

Все данные пишутся в файл /etc/dhcpd.hosts в виде:
host 192.168.10.2 { hardware ethernet 00:00:00:00:00:00; fixed-address 192.168.10.2; }

Дальше нам остается добавить в /usr/local/etc/dhcpd.conf в конец конфига строчку: include "/etc/dhcpd.hosts".

В общем то и все

Конфиг dhcpd.conf:
# /usr/local/etc/dhcpd.conf
#
# Конфигурация для isc-dhcp сервера
#
# Глобальные параметры
#========================================================
# Доменый суффикс, который будет присвоен клиентам
option domain-name "domain.ru";

# Список DNS серверов, которые должен использовать клиент
option domain-name-servers 192.168.1.1;
server-name "domain";

# На какое время выдавать клиентам настройки (в секундах) 86400сек=1день
default-lease-time 86400;

# На какое максимальное время выдавать клиентам настройки (в секундах)
max-lease-time 172800;

# Минимально на сколько выдается IP-адрес
min-lease-time 86400;
#========================================================

#Параметр определяет, будет ли DHCP-сервер пытаться обновить DNS при выдаче конфигурационной информации
ddns-update-style none;
#ddns-update-style interim;

# Данный параметр говорит, что мы будем обновлять DNS зону (т.к. мы уже выбрали, что не будем ее обновлять, то комментируем эту строчку)
#ddns-update-style ad-hoc;

# Включаем IP-Forwarding
option ip-forwarding on;
#ddns-fwd-name ns.domain.ru;

# Объявляем, что наш DHCP-сервер самый авторитетный (т.е. главный в сети)
authoritative;
# Логи которые отправляет DHCP-сервер
log-facility local7;
ignore client-updates;
deny bootp;
deny client-updates;
deny duplicates;
ignore declines;

# Локальные параметры сети (настройка сети)
#==========================================
shared-network domain {

subnet 192.168.10.0 netmask 255.255.255.0 { # Сеть которую объявляем и маска данной сети
        option subnet-mask 255.255.255.0;
        option routers 192.168.10.1;
        option broadcast-address 192.168.10.255;
        option domain-name-servers 192.168.1.1;
pool {
        range 192.168.10.2 192.168.10.254;
        deny unknown-clients; # Запретить выдачу IP-адресов не известным клиентам
#       deny client-updates;
#       deny bootp;
#       deny duplicates;
#       ignore declines;
}
option netbios-node-type 8;
option ntp-servers 192.168.1.1; # Сервер синхронизации времени

default-lease-time 86400; # Поумолчанию на сколько выдается IP-адрес
max-lease-time 172800; # Максимально на сколько выдается IP-адрес, после чего мы его сами забираем
}
subnet 192.168.11.0 netmask 255.255.255.0 { # Сеть которую объявляем и маска данной сети
        option subnet-mask 255.255.255.0;
        option routers 192.168.11.1;
        option broadcast-address 192.168.11.255;
        option domain-name-servers 192.168.1.1;
pool {
        range 192.168.11.2 192.168.11.254;
        deny unknown-clients; # Запретить выдачу IP-адресов не известным клиентам
#       deny client-updates;
#       not authoritative;
#       deny bootp;
#       deny duplicates;
#       ignore declines;
}
option netbios-node-type 8;
option ntp-servers 192.168.1.1; # Сервер синхронизации времени

default-lease-time 86400; # Поумолчанию на сколько выдается IP-адрес
max-lease-time 172800; # Максимально на сколько выдается IP-адрес, после чего мы его сами забираем
}
include "/etc/dhcpd.hosts";


Естественно все ip-адреса и mac-адреса вымышленные Удачи!

Еще добавлю, для защиты от dhcp-snooping, на порту коммутатора (у меня cisco) нужно указать следующие опции:
 switchport access vlan xx #VLAN в котором сидит dhcp
 switchport mode access
 no cdp enable
 ip dhcp snooping limit rate 500 #Лимит запросов
 ip dhcp snooping trust #Объявляем, что наш dhcp самый главный в сети (так называемая защита от подмены запросов) 


понедельник, 19 сентября 2011 г.

Для чего я создал блог?

Хотелось бы отметить, что все мы люди и всем свойственно забывать некоторые вещи в своей жизни. Так устроен наш разум, так устроен наш мозг. Блог для меня - это прежде всего записная книжка, как для себя так и для рабочих моментов. Ведь не всегда я помню как настроить те или иные моменты.