- Wiadomość jest najpierw zapisywana do kolejki, a dopiero potem wysyłana — dzięki temu awaria serwera pocztowego niczego nie gubi.
- Status w kolumnie
ACHodróżnia wiadomość oczekującą od wysłanej, a licznikREPEATzlicza próby. - Powiązanie przez
REFNO_TEMPLATEiREFNO_GROUPpozwala grupować wysyłki i korzystać ze wspólnych szablonów. - Dziesięć indeksów obsługuje zarówno pracę usługi wysyłającej, jak i późniejsze ustalanie, czy wiadomość została nadana.
Do czego służy tabela [dbo].[_send]
Powiadomienie o zmianie statusu reklamacji, potwierdzenie awizacji, raport wysyłany co rano — wszystkie one mają wspólną cechę: powstają w chwili, gdy system nie ma pewności, czy serwer pocztowy odpowie. Tabela [dbo].[_send] rozwiązuje to rozdzieleniem obu czynności. Wiadomość trafia najpierw do kolejki, a usługa wysyłająca zabiera ją stamtąd niezależnie.
Rozdzielenie daje trzy korzyści. Operacja użytkownika kończy się natychmiast, bo nie czeka na serwer pocztowy. Awaria łącza nie powoduje utraty powiadomienia — pozostaje ono w kolejce do czasu, aż wysyłka się powiedzie. A liczba prób zapisana w kolumnie REPEAT pozwala odróżnić wiadomość, która właśnie czeka, od tej, która nie może zostać nadana od trzech dni.
Wiersz zawiera komplet danych potrzebnych do nadania: trzy grupy odbiorców, temat, treść, adres zwrotny oraz konto nadawcze wskazane symbolem ze skorowidza. Znacznik SEND_AS_USER decyduje, czy wiadomość zostanie wysłana w imieniu użytkownika, który ją wywołał, czy z konta systemowego — różnica istotna wtedy, gdy odbiorca ma odpowiedzieć konkretnej osobie.
Operacja użytkownika kończy się na drugim kroku — nie czeka na serwer pocztowy, więc awaria poczty nie blokuje pracy w systemie.
Budowa tabeli — wykaz kolumn
Dwadzieścia trzy kolumny dzielą się na treść wiadomości, jej adresatów, powiązania oraz metrykę wysyłki.
| Kolumna | Typ | Wymagana | Znaczenie |
|---|---|---|---|
| Treść i adresaci | |||
SUBJECT | varchar(max) tekst bez limitu długości | tak | Temat maila |
MAIL_CONTENT | varchar(max) tekst bez limitu długości | tak | Treść maila |
EMAIL | varchar(5000) tekst do 5000 znaków | nie | Adresy email odbiorców wiadomości |
DW | varchar(150) tekst do 150 znaków | nie | Adresy email odbiorców „do wiadomości” |
UDW | varchar(150) tekst do 150 znaków | nie | Adresy email odbiorców „ukryte do wiadomości” |
REPLY_TO | varchar(150) tekst do 150 znaków | tak | Adres odpowiedzi |
KONTO_MAIL | varchar(5) tekst do 5 znaków | nie | Konto mailowe ze skorowidza KEML |
SEND_AS_USER | bit wartość logiczna 0/1 | tak | Flaga wskazująca, czy e-mail powinien być wysłany w imieniu użytkownika |
| Powiązania | |||
REFNO | bigint liczba całkowita 64-bitowa | tak | Numer referencyjny wysyłki |
REFNO_GROUP | bigint liczba całkowita 64-bitowa | tak | Identyfikator grupy |
REFNO_TEMPLATE | bigint liczba całkowita 64-bitowa | tak | Indentyfikator szablonu mailowego |
PRX | varchar(5) tekst do 5 znaków | tak | Identyfikator grupy rekordów |
FIRMA | varchar(20) tekst do 20 znaków | nie | Identyfikator firmy |
ODDZIAL | varchar(5) tekst do 5 znaków | nie | Identyfikator oddziału osoby dokonującej zapisu w bazie |
MPK | varchar(20) tekst do 20 znaków | nie | Symbol miejsca powstawania kosztów |
ROLASYS | varchar(3) tekst do 3 znaków | nie | Identyfikator roli |
| Stan wysyłki | |||
ID_SEND | int liczba całkowita | tak | Unikalny identyfikator wiersza tabeli |
ACH | varchar(1) tekst do 1 znaków | tak | Jednoznakowe oznaczenie stanu danego wiersza w tabeli: 0-bufor, 1-zatwierdzony, X-usunięty |
REPEAT | int liczba całkowita | tak | Ilość prób wysłania maila |
KIEDY | datetime data i godzina | tak | Data i godzina dopisania rekordu w bazie |
DDOWOD | date data | nie | Data zapisania dokumentu |
LOGIN | varchar(50) tekst do 50 znaków | nie | Login użytkownika dokonującego zapisu w bazie |
STAMP | timestamp znacznik wersji wiersza | tak | Wewnętrzny identyfikator aktualizacji wiersza |
Kolumna EMAIL mieści pięć tysięcy znaków, a więc setki adresów. Przy wysyłkach masowych warto jednak rozważyć osobne wiersze dla każdego odbiorcy — inaczej jeden nieprawidłowy adres potrafi zablokować całą wiadomość.
Indeksy i wydajność zapytań
Dziesięć indeksów to nietypowo dużo jak na jedną tabelę i wynika z dwóch odmiennych sposobów jej używania.
| Indeks | Kolumny | Rodzaj |
|---|---|---|
ACH | ACH | zwykły |
DDOWOD | DDOWOD | zwykły |
KIEDY | KIEDY | zwykły |
LOGIN | LOGIN | zwykły |
PK_send | ID_SEND | klucz główny |
PRX | PRX | zwykły |
REFNO | REFNO | zwykły |
REFNO_GROPU | REFNO_GROUP | zwykły |
REFNO_GROUP_REFNO_TEMPLATE | REFNO_GROUP, REFNO_TEMPLATE | zwykły |
REFNO_TEMPLATE | REFNO_TEMPLATE | zwykły |
Pierwszy zbiór — indeksy na ACH, KIEDY i REPEAT — obsługuje usługę wysyłającą, która co kilkadziesiąt sekund pyta o wiadomości oczekujące. Drugi, oparty na REFNO, REFNO_GROUP i REFNO_TEMPLATE, służy późniejszym pytaniom: czy powiadomienie o tej reklamacji zostało wysłane i kiedy. Taka liczba indeksów ma swoją cenę przy zapisie, ale kolejka jest odczytywana znacznie częściej, niż zapisywana.
Wiadomość nie dotarła — od czego zacząć
Zgłoszenie „nie dostałem powiadomienia” ma kilka możliwych przyczyn, a kolejka pozwala szybko zawęzić je do jednej.
| Co widać w tabeli | Co to oznacza | Gdzie szukać dalej |
|---|---|---|
| Brak wiersza | Wiadomość w ogóle nie powstała | Konfiguracja zdarzenia albo warunek w zadaniu automatycznym |
| Wiersz ze statusem oczekiwania, REPEAT = 0 | Czeka na najbliższy przebieg usługi | Nic — wystarczy odczekać |
| REPEAT rośnie, status bez zmian | Serwer pocztowy odrzuca wiadomość | Rejestr błędów i konfiguracja konta nadawczego |
| Status wysłany, odbiorca nie ma wiadomości | Nadanie się powiodło, problem po stronie odbiorcy | Filtr antyspamowy, poprawność adresu |
| Adres w kolumnie EMAIL wygląda inaczej niż oczekiwano | Błąd w danych źródłowych | Kartoteka kontrahenta lub konto użytkownika |
Trzeci wiersz jest najczęstszy przy nowo uruchomionej integracji — zwykle wskazuje na brak autoryzacji konta nadawczego.
Warto ustawić prosty próg alarmowy: zapytanie zliczające wiadomości z licznikiem prób powyżej trzech, uruchamiane raz dziennie. Rosnąca liczba takich wierszy oznacza, że wysyłka przestała działać — a to sytuacja, o której nikt nie zgłosi, bo brak powiadomienia jest z natury niewidoczny.
Jak korzystać z tabeli w praktyce
Przy utrzymaniu kolejki wiadomości sprawdzają się poniższe zasady:
- Monitoruj wiersze z wysoką wartością
REPEAT— to jedyny sygnał, że wysyłka przestała działać. - Twórz osobne wiersze dla poszczególnych odbiorców przy wysyłkach masowych; jeden błędny adres nie zablokuje wtedy pozostałych.
- Ustawiaj
SEND_AS_USERtam, gdzie odbiorca ma odpowiedzieć konkretnej osobie, a nie na skrzynkę systemową. - Korzystaj z
REFNO_TEMPLATEzamiast wpisywać treść bezpośrednio; zmiana szablonu obejmie wtedy wszystkie przyszłe wysyłki. - Archiwizuj wiadomości wysłane starsze niż kilka miesięcy — kolumna z treścią ma typ
varchar(max)i szybko rośnie. - Nie usuwaj wierszy oczekujących w celu „odblokowania” kolejki; najpierw ustal, dlaczego nie zostały nadane.
Kontrola kolejki: wiadomości oczekujące dłużej niż godzinę oraz te, przy których próby wysyłki się powtarzają:
SELECT ID_SEND,
KIEDY,
LEFT(EMAIL, 60) AS ODBIORCA,
LEFT(SUBJECT, 60) AS TEMAT,
REPEAT AS PROB,
DATEDIFF(MINUTE, KIEDY, GETDATE()) AS CZEKA_MINUT
FROM dbo._send
WHERE ACH <> '1'
AND KIEDY < DATEADD(HOUR, -1, GETDATE())
ORDER BY REPEAT DESC, KIEDY;
Wiersze z licznikiem prób powyżej trzech zasługują na osobną uwagę — zwykle wskazują na problem z kontem nadawczym, a nie z pojedynczą wiadomością.
Kolejka wiadomości należy do mechanizmów, których awaria jest niewidoczna. Nikt nie zgłosi, że nie dostał powiadomienia, którego się nie spodziewał — dlatego jedno zapytanie kontrolne uruchamiane codziennie jest tu wart więcej niż rozbudowana konfiguracja.
Powiązane tabele i dokumentacja
Kolejka e-mail działa razem z pozostałymi mechanizmami powiadamiania i automatyzacji: