<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[SQLite: PRAGMA и WAL — полный гайд]]></title><description><![CDATA[<p dir="auto"><strong>PRAGMA</strong> - это SQL-расширение, специфичное для SQLite. Это команда-«рычаг управления» движком: она позволяет <strong>читать и менять внутренние параметры</strong> базы данных  (режим журналирования, размер кэша, поведение fsync, целостность схемы и многое другое).</p>
<p dir="auto">Синтаксически PRAGMA выглядит как обычный SQL, но работает иначе:</p>
<pre><code class="language-sql">-- Чтение параметра
PRAGMA journal_mode;

-- Установка параметра (две эквивалентные формы)
PRAGMA journal_mode = WAL;
PRAGMA journal_mode(WAL);

-- С указанием схемы (для ATTACH-баз)
PRAGMA main.journal_mode = WAL;
PRAGMA temp.cache_size;
</code></pre>
<h3>Чем PRAGMA отличается от обычного SQL</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Свойство</th>
<th>Обычный SQL</th>
<th>PRAGMA</th>
</tr>
</thead>
<tbody>
<tr>
<td>Переносимость</td>
<td>Стандарт SQL</td>
<td>Только SQLite</td>
</tr>
<tr>
<td>Обратная совместимость</td>
<td>Гарантирована</td>
<td>Не гарантирована</td>
</tr>
<tr>
<td>Ошибка при опечатке</td>
<td>Выдаётся</td>
<td><strong>Молча игнорируется</strong></td>
</tr>
<tr>
<td>Момент выполнения</td>
<td><code>sqlite3_step()</code></td>
<td>Может быть в <code>sqlite3_prepare()</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p dir="auto"><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ <strong>Важно</strong>: если допустить опечатку в названии PRAGMA (<code>PRAGMA jouranl_mode = WAL</code>), SQLite не выдаст ошибку - команда просто не выполнится. Всегда проверяйте возвращаемое значение.</p>
</blockquote>
<h3>PRAGMA как табличные функции</h3>
<p dir="auto">Начиная с SQLite 3.16.0, PRAGMA без побочных эффектов можно использовать в <code>SELECT</code> как табличные функции с префиксом <code>pragma_</code>:</p>
<pre><code class="language-sql">-- Через PRAGMA
PRAGMA table_info('users');

-- Через функцию (можно в JOIN, WHERE, агрегатах)
SELECT name, type FROM pragma_table_info('users') WHERE pk = 1;

-- Пример: все проиндексированные колонки во всех таблицах
SELECT DISTINCT m.name || '.' || ii.name AS indexed_col
  FROM sqlite_schema AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type = 'table'
 ORDER BY 1;
</code></pre>
<hr />
<h2>Ключевые PRAGMA: обзор</h2>
<h3>Производительность и кэш</h3>
<pre><code class="language-sql">-- Размер кэша: положительное = страницы, отрицательное = KiB
PRAGMA cache_size = -8000;     -- ~8 МБ кэша
PRAGMA cache_size;             -- читаем текущее значение (по умолч: -2000)

-- Размер страницы (только до первой записи!)
PRAGMA page_size = 4096;

-- Временные таблицы в RAM вместо диска
PRAGMA temp_store = MEMORY;

-- Memory-mapped I/O (0 = выключено)
PRAGMA mmap_size = 268435456; -- 256 МБ
</code></pre>
<h3>Целостность и безопасность</h3>
<pre><code class="language-sql">-- Проверка целостности базы
PRAGMA integrity_check;
PRAGMA integrity_check(10);          -- первые 10 ошибок
PRAGMA integrity_check('orders');    -- только таблица orders

-- Быстрая проверка (без некоторых тестов, зато быстрее)
PRAGMA quick_check;

-- Внешние ключи (по умолчанию ВЫКЛЮЧЕНЫ!)
PRAGMA foreign_keys = ON;
PRAGMA foreign_key_check;

-- Версия приложения (для идентификации формата файла)
PRAGMA user_version = 3;
PRAGMA user_version;
</code></pre>
<h3>Информация о схеме</h3>
<pre><code class="language-sql">-- Колонки таблицы
PRAGMA table_info('orders');

-- Индексы таблицы
PRAGMA index_list('orders');

-- Подробности по конкретному индексу
PRAGMA index_info('idx_user_id');

-- Все присоединённые базы
PRAGMA database_list;

-- Список всех PRAGMA
PRAGMA pragma_list;
</code></pre>
<h3>Таймаут при блокировке</h3>
<pre><code class="language-sql">-- Ждать 5 секунд вместо немедленного SQLITE_BUSY
PRAGMA busy_timeout = 5000;
</code></pre>
<hr />
<h2>Режимы журналирования (journal_mode)</h2>
<p dir="auto">SQLite обеспечивает атомарность транзакций через журнал. Всего режимов шесть:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Режим</th>
<th>Описание</th>
<th>Когда использовать</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DELETE</code></td>
<td>Журнал удаляется при коммите. <strong>По умолчанию</strong></td>
<td>Простые однопользовательские сценарии</td>
</tr>
<tr>
<td><code>TRUNCATE</code></td>
<td>Журнал обрезается до 0 (не удаляется). Быстрее DELETE на некоторых ОС</td>
<td>Альтернатива DELETE</td>
</tr>
<tr>
<td><code>PERSIST</code></td>
<td>Заголовок журнала перезаписывается нулями</td>
<td>Оптимизация на платформах, где удаление файла дорого</td>
</tr>
<tr>
<td><code>MEMORY</code></td>
<td>Журнал только в RAM, нет fsync. Быстро, но нет durability</td>
<td>Тесты, временные операции</td>
</tr>
<tr>
<td><code>WAL</code></td>
<td>Write-Ahead Log - изменения пишутся в отдельный файл</td>
<td>Конкурентный доступ, большинство реальных приложений</td>
</tr>
<tr>
<td><code>OFF</code></td>
<td>Нет журнала вообще. Нет атомарности!</td>
<td>Только bulk-import с полным контролем</td>
</tr>
</tbody>
</table>
<pre><code class="language-sql">PRAGMA journal_mode;        -- узнать текущий
PRAGMA journal_mode = WAL;  -- включить WAL, возвращает 'wal' при успехе
PRAGMA journal_mode = DELETE; -- вернуться к стандартному
</code></pre>
<hr />
<h2>Как работает WAL - механика</h2>
<h3>Rollback Journal vs WAL: принципиальное отличие</h3>
<p dir="auto"><strong>Rollback Journal (DELETE-режим):</strong></p>
<ol>
<li>Перед изменением страницы - скопировать оригинал в журнал</li>
<li>Записать изменения прямо в <code>.db</code> файл</li>
<li>Коммит = удалить журнал</li>
<li>Откат = восстановить из журнала в <code>.db</code></li>
</ol>
<p dir="auto"><strong>WAL (Write-Ahead Log):</strong></p>
<ol>
<li>Оригинал в <code>.db</code> -  <strong>не трогать</strong></li>
<li>Изменения <strong>дописать</strong> в конец <code>.wal</code> файла</li>
<li>Коммит = записать специальную commit-запись в <code>.wal</code></li>
<li>Читатели работают с <code>.db</code> + нужный «срез» <code>.wal</code></li>
<li>Checkpoint = перенести WAL → <code>.db</code></li>
</ol>
<pre><code>┌─────────────────────────────────────────────────────────────┐
│  Файлы на диске при WAL-режиме                              │
│                                                             │
│  mydb.db     ← основная база (стабильные данные)           │
│  mydb.db-wal ← новые изменения (дописываются в конец)      │
│  mydb.db-shm ← shared-memory индекс (wal-index)           │
└─────────────────────────────────────────────────────────────┘
</code></pre>
<h3>Как читатели видят данные</h3>
<p dir="auto">Когда читатель открывает транзакцию, он фиксирует <strong>«end mark»</strong> - позицию последней commit-записи в WAL на этот момент. Все его чтения используют только данные до этой метки: сначала WAL (в обратном порядке, берётся последняя версия страницы), затем <code>.db</code>. Это обеспечивает <strong>снапшотную изоляцию</strong> без блокировки писателя.</p>
<h3>Checkpoint: возврат данных из WAL в .db</h3>
<p dir="auto">Checkpoint - это операция переноса страниц из WAL обратно в основную базу. Она происходит автоматически (каждые 1000 страниц по умолчанию) или вручную.</p>
<p dir="auto">Режимы checkpoint’а:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Режим</th>
<th>Поведение</th>
<th>Блокирует?</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>PASSIVE</code></td>
<td>Делает что может, не мешая другим. <strong>По умолчанию</strong></td>
<td>Нет</td>
</tr>
<tr>
<td><code>FULL</code></td>
<td>Ждёт завершения всех текущих писателей, затем checkpoint</td>
<td>Ждёт писателей</td>
</tr>
<tr>
<td><code>RESTART</code></td>
<td>FULL + ждёт читателей, чтобы сбросить WAL с начала</td>
<td>Ждёт всех</td>
</tr>
<tr>
<td><code>TRUNCATE</code></td>
<td>RESTART + физически обрезает файл <code>.wal</code> до 0 байт</td>
<td>Ждёт всех</td>
</tr>
</tbody>
</table>
<pre><code class="language-sql">PRAGMA wal_checkpoint;           -- PASSIVE (по умолчанию)
PRAGMA wal_checkpoint(FULL);     -- ждёт писателей
PRAGMA wal_checkpoint(RESTART);  -- ждёт всех
PRAGMA wal_checkpoint(TRUNCATE); -- + обрезает файл

-- Возвращает 3 числа: (busy, log_pages, checkpointed_pages)
-- busy=0 → checkpoint прошёл без блокировок
-- log_pages == checkpointed_pages → WAL полностью перенесён
</code></pre>
<hr />
<h2>WAL: включение и настройка</h2>
<h3>Минимальный старт</h3>
<pre><code class="language-python">import sqlite3

conn = sqlite3.connect("mydb.db")

# Включаем WAL - настройка персистентна (сохраняется между перезапусками)
result = conn.execute("PRAGMA journal_mode = WAL").fetchone()
print(result)  # → 'wal' при успехе, или прежний режим при неудаче
</code></pre>
<h3>Оптимальная конфигурация для production</h3>
<pre><code class="language-python">import sqlite3

def get_connection(db_path: str) -&gt; sqlite3.Connection:
    conn = sqlite3.connect(db_path, timeout=30)

    # WAL - основной режим
    conn.execute("PRAGMA journal_mode = WAL")

    # NORMAL: fsync только при checkpoint, безопасно для WAL
    # FULL = fsync на каждый коммит (медленнее, максимальная стойкость)
    conn.execute("PRAGMA synchronous = NORMAL")

    # Кэш ~32 МБ
    conn.execute("PRAGMA cache_size = -32000")

    # Временные таблицы в памяти
    conn.execute("PRAGMA temp_store = MEMORY")

    # 256 МБ memory-mapped reads
    conn.execute("PRAGMA mmap_size = 268435456")

    # Checkpoint раз в 500 страниц вместо 1000
    conn.execute("PRAGMA wal_autocheckpoint = 500")

    # Ждать до 5 сек при блокировке
    conn.execute("PRAGMA busy_timeout = 5000")

    # Включить внешние ключи (по умолчанию выключены!)
    conn.execute("PRAGMA foreign_keys = ON")

    return conn
</code></pre>
<h3>Конфигурация synchronous с WAL</h3>
<pre><code class="language-sql">-- OFF: нет fsync вообще. Быстро, но риск порчи при сбое питания
PRAGMA synchronous = OFF;

-- NORMAL: fsync только при checkpoint. Рекомендуется для WAL
-- Потеря данных возможна только при сбое ОС, не при сбое приложения
PRAGMA synchronous = NORMAL;

-- FULL: fsync при каждом коммите и checkpoint
PRAGMA synchronous = FULL;

-- EXTRA: FULL + extra fsync на директорию (максимальная защита)
PRAGMA synchronous = EXTRA;
</code></pre>
<blockquote>
<p dir="auto">В WAL-режиме при <code>synchronous=NORMAL</code> данные не теряются при сбое приложения, но возможны потери при сбое ОС или питания. Это приемлемый компромисс для большинства приложений.</p>
</blockquote>
<hr />
<h2>Конкурентный доступ: как это реально работает</h2>
<pre><code class="language-python">import sqlite3
import threading

DB = "shared.db"

def setup():
    conn = sqlite3.connect(DB)
    conn.execute("PRAGMA journal_mode = WAL")
    conn.execute("PRAGMA busy_timeout = 3000")
    conn.execute("""
        CREATE TABLE IF NOT EXISTS events (
            id    INTEGER PRIMARY KEY AUTOINCREMENT,
            name  TEXT NOT NULL,
            ts    TEXT DEFAULT (datetime('now'))
        )
    """)
    conn.commit()
    conn.close()

def writer(thread_id: int):
    # Каждый поток открывает своё соединение
    conn = sqlite3.connect(DB, timeout=10)
    conn.execute("PRAGMA journal_mode = WAL")
    conn.execute("PRAGMA busy_timeout = 3000")

    for i in range(50):
        conn.execute("INSERT INTO events(name) VALUES (?)", (f"t{thread_id}-e{i}",))
        conn.commit()

    conn.close()

def reader():
    conn = sqlite3.connect(DB, timeout=10)
    conn.execute("PRAGMA journal_mode = WAL")

    # В WAL-режиме: читатель НЕ блокирует писателя и наоборот
    rows = conn.execute("SELECT COUNT(*) FROM events").fetchone()
    print(f"Читатель видит: {rows} записей")
    conn.close()

setup()

# Запускаем 4 писателя одновременно
writers = [threading.Thread(target=writer, args=(i,)) for i in range(4)]
for w in writers: w.start()

# Читатель работает параллельно с писателями
reader_thread = threading.Thread(target=reader)
reader_thread.start()

for w in writers: w.join()
reader_thread.join()
</code></pre>
<h3>Ручной checkpoint</h3>
<pre><code class="language-python">def manual_checkpoint(db_path: str, mode: str = "FULL"):
    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode = WAL")

    result = conn.execute(f"PRAGMA wal_checkpoint({mode})").fetchone()
    busy, log_pages, checkpointed = result

    print(f"Busy: {busy}")
    print(f"Pages in WAL: {log_pages}")
    print(f"Pages checkpointed: {checkpointed}")

    if log_pages == checkpointed:
        print("✓ WAL полностью перенесён в .db")
    else:
        print(f"⚠ Не перенесено {log_pages - checkpointed} страниц (есть активные читатели)")

    conn.close()

manual_checkpoint("mydb.db", "TRUNCATE")
</code></pre>
<hr />
<h2>Преимущества и ограничения WAL</h2>
<h3>Преимущества</h3>
<ol>
<li><strong>Быстрее</strong> для большинства сценариев - записи sequential, нет двойной записи</li>
<li><strong>Конкурентность</strong> - читатели не блокируют писателя, писатель не блокирует читателей</li>
<li><strong>Меньше fsync()</strong> - уязвимость к broken fsync снижена</li>
<li><strong>Снапшотная изоляция</strong> - каждый читатель видит согласованный срез</li>
</ol>
<h3>Ограничения</h3>
<ol>
<li><strong>Только на одной машине</strong> - WAL требует общей памяти (<code>.shm</code>), сетевые ФС не поддерживаются</li>
<li><strong>Один писатель</strong> - конкурентная запись невозможна, только последовательная</li>
<li><strong>Нельзя менять page_size</strong> после перехода в WAL</li>
<li><strong>Читаемость снижается</strong> при большом WAL - каждый читатель сканирует WAL для поиска страниц</li>
<li><strong>Дополнительные файлы</strong> - <code>.wal</code> и <code>.shm</code> должны храниться рядом с <code>.db</code></li>
<li><strong>ATTACH + несколько баз</strong> - атомарность только внутри одной базы, не между ними</li>
</ol>
<h3>WAL-reset bug (CVE-подобная проблема)</h3>
<p dir="auto">В SQLite 3.7.0–3.51.2 существовал редкий race condition при двух одновременных checkpoint’ах, который мог привести к порче базы. Исправлено в версии <strong>3.51.3 (2026-03-13)</strong>. Если вы используете WAL с многопроцессным доступом - обновитесь.</p>
<hr />
<h2>Когда НЕ использовать WAL</h2>
<pre><code class="language-python"># WAL НЕ подходит если:

# 1. Сетевая файловая система (NFS, SMB, CIFS)
conn = sqlite3.connect("//nas/share/mydb.db")  # ❌ WAL сломается

# 2. База открывается в read-only режиме без .shm файла
# (решается через PRAGMA locking_mode=EXCLUSIVE или флаг immutable)

# 3. Нужно менять page_size
conn.execute("PRAGMA page_size = 8192")   # нужно делать ДО WAL
conn.execute("PRAGMA journal_mode = WAL") # после этого page_size не сменить

# 4. Транзакции &gt; 100 МБ на старых версиях SQLite &lt; 3.11.0
# (на 3.11.0+ это ограничение снято)
</code></pre>
<hr />
<h2>Диагностика и мониторинг WAL</h2>
<pre><code class="language-python">import sqlite3

def wal_status(db_path: str):
    conn = sqlite3.connect(db_path)

    mode = conn.execute("PRAGMA journal_mode").fetchone()
    sync = conn.execute("PRAGMA synchronous").fetchone()
    cache = conn.execute("PRAGMA cache_size").fetchone()
    page_size = conn.execute("PRAGMA page_size").fetchone()
    page_count = conn.execute("PRAGMA page_count").fetchone()
    auto_cp = conn.execute("PRAGMA wal_autocheckpoint").fetchone()
    fk = conn.execute("PRAGMA foreign_keys").fetchone()

    # Статус WAL
    cp = conn.execute("PRAGMA wal_checkpoint(PASSIVE)").fetchone()

    print(f"journal_mode:       {mode}")
    print(f"synchronous:        {sync}  (0=OFF 1=NORMAL 2=FULL 3=EXTRA)")
    print(f"cache_size:         {cache} pages")
    print(f"page_size:          {page_size} bytes")
    print(f"page_count:         {page_count}")
    print(f"db_size:            {page_size * page_count / 1024:.1f} KB")
    print(f"wal_autocheckpoint: {auto_cp} pages")
    print(f"foreign_keys:       {'ON' if fk else 'OFF'}")
    print(f"WAL checkpoint:     busy={cp}, log={cp[^1]}, checkpointed={cp[^2]}")

    conn.close()

wal_status("mydb.db")
</code></pre>
<hr />
<h2>Полный шаблон: production-ready SQLite + WAL</h2>
<pre><code class="language-python">import sqlite3
from contextlib import contextmanager
from pathlib import Path


class Database:
    def __init__(self, path: str | Path):
        self.path = str(path)
        self._init_db()

    def _make_conn(self) -&gt; sqlite3.Connection:
        conn = sqlite3.connect(self.path, timeout=30)
        conn.row_factory = sqlite3.Row
        conn.execute("PRAGMA journal_mode = WAL")
        conn.execute("PRAGMA synchronous = NORMAL")
        conn.execute("PRAGMA cache_size = -32000")   # ~32 MB
        conn.execute("PRAGMA temp_store = MEMORY")
        conn.execute("PRAGMA mmap_size = 134217728") # 128 MB
        conn.execute("PRAGMA foreign_keys = ON")
        conn.execute("PRAGMA busy_timeout = 5000")
        conn.execute("PRAGMA wal_autocheckpoint = 1000")
        return conn

    def _init_db(self):
        with self._make_conn() as conn:
            conn.execute("""
                CREATE TABLE IF NOT EXISTS items (
                    id      INTEGER PRIMARY KEY AUTOINCREMENT,
                    name    TEXT NOT NULL,
                    value   REAL,
                    created TEXT DEFAULT (datetime('now'))
                )
            """)
            conn.commit()

    @contextmanager
    def connection(self):
        conn = self._make_conn()
        try:
            yield conn
            conn.commit()
        except Exception:
            conn.rollback()
            raise
        finally:
            conn.close()

    def checkpoint(self, mode: str = "PASSIVE") -&gt; dict:
        with self.connection() as conn:
            busy, log, done = conn.execute(
                f"PRAGMA wal_checkpoint({mode})"
            ).fetchone()
            return {"busy": busy, "log_pages": log, "checkpointed": done}


# Использование
db = Database("app.db")

with db.connection() as conn:
    conn.execute("INSERT INTO items(name, value) VALUES (?, ?)", ("test", 3.14))

print(db.checkpoint("FULL"))
</code></pre>
<hr />
<h2>Шпаргалка: наиболее используемые PRAGMA</h2>
<pre><code class="language-sql">-- === ОБЯЗАТЕЛЬНО при старте соединения ===
PRAGMA journal_mode = WAL;     -- WAL-режим (персистентен)
PRAGMA synchronous = NORMAL;   -- баланс скорость/надёжность для WAL
PRAGMA foreign_keys = ON;      -- внешние ключи (выкл. по умолчанию!)
PRAGMA busy_timeout = 5000;    -- не падать сразу при блокировке

-- === ПРОИЗВОДИТЕЛЬНОСТЬ ===
PRAGMA cache_size = -32000;    -- 32 МБ кэша
PRAGMA temp_store = MEMORY;    -- временные таблицы в RAM
PRAGMA mmap_size = 134217728;  -- 128 МБ memory-mapped I/O

-- === НАСТРОЙКА WAL ===
PRAGMA wal_autocheckpoint = 1000;  -- авто-checkpoint каждые N страниц
PRAGMA wal_checkpoint(PASSIVE);    -- мягкий checkpoint
PRAGMA wal_checkpoint(TRUNCATE);   -- checkpoint + обрезать .wal файл

-- === ДИАГНОСТИКА ===
PRAGMA integrity_check;        -- полная проверка базы
PRAGMA journal_mode;           -- текущий режим
PRAGMA page_size;              -- размер страницы
PRAGMA page_count;             -- число страниц
PRAGMA table_info('tbl');      -- колонки таблицы
PRAGMA index_list('tbl');      -- индексы таблицы
PRAGMA database_list;          -- все attach'нутые базы
</code></pre>
<hr />
<h2>References</h2>
<ol>
<li>
<p dir="auto"><a href="https://sqlite.org/pragma.html" target="_blank" rel="noopener noreferrer">Pragma statements supported by SQLite</a></p>
</li>
<li>
<p dir="auto"><a href="https://www.oreilly.com/library/view/using-sqlite/9781449394592/re96.html" target="_blank" rel="noopener noreferrer">PRAGMA - Using SQLite [Book]</a> - NamePRAGMA - Look up or modify an SQLite configurationSyntaxCommon UsagePRAGMA page_size; PRAGMA cac…</p>
</li>
<li>
<p dir="auto"><a href="https://www.sqlite.org/pragma.html" target="_blank" rel="noopener noreferrer">Pragma statements supported by SQLite</a></p>
</li>
<li>
<p dir="auto"><a href="https://deepwiki.com/sqlite/sqlite/4.2-pragma-system" target="_blank" rel="noopener noreferrer">PRAGMA System | sqlite/sqlite | DeepWiki</a> - The PRAGMA system provides runtime configuration and introspection capabilities for SQLite databases…</p>
</li>
<li>
<p dir="auto"><a href="https://sqlite.org/wal.html" target="_blank" rel="noopener noreferrer">Write-Ahead Logging - SQLitesqlite.org › wal</a></p>
</li>
</ol>
]]></description><link>https://forum.exlends.com/topic/2218/sqlite-pragma-i-wal-polnyj-gajd</link><generator>RSS for Node</generator><lastBuildDate>Sat, 02 May 2026 13:10:13 GMT</lastBuildDate><atom:link href="https://forum.exlends.com/topic/2218.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 30 Apr 2026 13:06:08 GMT</pubDate><ttl>60</ttl></channel></rss>