惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
爱范儿
爱范儿
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
博客园_首页
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
P
Proofpoint News Feed
博客园 - 司徒正美
有赞技术团队
有赞技术团队
Engineering at Meta
Engineering at Meta
Last Week in AI
Last Week in AI
MongoDB | Blog
MongoDB | Blog

alexwlchan’s notes

What is WS11 1DB? Blocking referrers with Caddy How to type a Spanish question mark (¿) on a Mac Non-overlapping type comparisons and Python type checkers Why does t.Setenv panic after t.Parallel? Use Path.glob() and Path.rglob() for typed versions of glob.glob() Curious clocks and colourful eyes Track which templates are used by Jinja2 Archeologists distinguish between “sherds” and “shards” A single command to test all my changed Go packages Disable the new message animations in WhatsApp Finding high-churn folders that bother Backblaze Always-on SSH agent forwarding with my Git pushes Managing the caption of a photo with AppleScript (but not PhotoKit) Goodhart’s and Campbell’s Law are different Notes from The Cornishman No. 176 (Spring 2026) Notes from The Cornishman No. 176 (Spring 2026) GitUp can’t diff text files larger than 8MB Home Testing the width of a page on a mobile device using Playwright Disable AirPods charging notifications Start a Caddy server in a subprocess during a Python session Filter a list of JSON object based on a list of tags HOME_GET_ME_HOME is a Citymapper Shortcuts action The FileExistsError exception exposes a filename attribute The red-lined bubble snail Why can’t Python connect to example.com? Useful type hints for Python How to truncate the middle of long command output AirPlay Receiver can interfere with Flask apps
The file(1) command can read SQLite databases
2026-03-14 · via alexwlchan’s notes

It can identify a SQLite database and give you basic information about the version, page count, encoding, and more.

Here’s a neat trick that Percy showed me today: the file(1) command is able to recognise SQLite databases, and print some information about the structure of the database.

Here’s an example from my Mac:

$ file example.db
example.db: SQLite 3.x database, last written using SQLite version 3050004, file counter 89, database pages 4, cookie 0x2, schema 4, UTF-8, version-valid-for 89

These values are read from the database header, the first 100 bytes of the file which include information about the database. A couple of fields stood out to me:

  • The SQLite version. This is an integer, specifically SQLITE_VERSION_NUMBER, which is a representation of the version number. In this example, 3050004 means the database was last written by SQLite 3.50.4.

  • The file (change) counter counts changes to the database. If multiple processes are working in the same database, they can detect when another process made a change, and invalidate their page cache.

    I was surprised that this value was so low for our production databases at work (just 1196), but the SQLite docs explain that if you run your database in WAL mode – which we do – changes are tracked through the wal-index, and so the change counter might not be incremented. That must be happening in our databases.

  • The (schema) cookie gets incremented whenever the database schema changes. I ran a quick example and I can see it increasing from 0x2 to 0x3 in my example database:

    $ file example.db
    example.db: SQLite 3.x database, last written using SQLite version 3050004, file counter 90, database pages 4, cookie 0x2, schema 4, UTF-8, version-valid-for 90
    
    $ sqlite3 example.db 'CREATE TABLE NewTable(x);'
    
    $ file example.db
    example.db: SQLite 3.x database, last written using SQLite version 3050004, file counter 91, database pages 5, cookie 0x3, schema 4, UTF-8, version-valid-for 91

    The field that file(1) labels as “schema” is the schema format number, and tracks the version of SQL formatting used in the database. As of 13 March 2026, schema format 4 is the highest possible value, and it has been since January 2006.

  • The user version field is an integer for “applications to use however they want” which SQLite doesn’t read. I imagine this might be quite useful for storing, say, a schema version in an easily accessible location.

    You can set it using the user_version pragma, and then it appears in the file(1) output:

    $ sqlite3 example.db 'PRAGMA user_version = 42;'
    
    $ file example.db
    example.db: SQLite 3.x database, user version 42, last written using SQLite version 3050001, file counter 92, database pages 5, cookie 0x3, schema 4, UTF-8, version-valid-for 92
  • The application ID is a field to identify the application that “owns” the database. Lots of applications use SQLite as their storage format, and they can record their ID in this field.

    There are well-known values in magic.txt in the SQLite repository. If you use one of these, file(1) adds the human-readable name to its output:

    $ sqlite3 example.db 'PRAGMA application_id = 0x0f055112;'
    
    $ file example.db
    example.db: SQLite 3.x database (Fossil checkout), last written using SQLite version 3050001, file counter 94, database pages 5, cookie 0x3, schema 4, UTF-8, version-valid-for 94

    If you use a different value, file(1) prints the literal value:

    $ sqlite3 example.db 'PRAGMA application_id = 0x42424242;'
    
    $ file example.db
    example.db: SQLite 3.x database, application id 1111638594, last written using SQLite version 3050001, file counter 95, database pages 5, cookie 0x3, schema 4, UTF-8, version-valid-for 95

    This lookup comes from a sql “magic” file which ships with file(1), embedding all the values from SQLite’s magic.txt and many more besides.