实时的Postgres变更数据捕获(CDC)功能监听数据库的变更,并将其发送给客户端。客户端需要通过JWT订阅,该JWT决定了他们可以根据数据库的行级安全接收哪些变化。

任何能够访问用项目的JWT秘密签名的有效JWT的人都能够监听你的数据库的变化,除非表启用了行级安全并制定了策略。

客户端可以选择接收 INSERTUPDATEDELETE*(all)的变化,用于接收模式中的所有变化、模式中的一个表或表中的一个列的值。你的客户应该只监听public模式中的表,你必须首先启用你希望客户监听的表。

Postgres CDC对 public模式中的表是开箱即用的。你可以通过给访问令牌中的数据库角色授予表 SELECT的权限来监听你的私有模式中的表。你可以运行一个类似于以下的查询。

  GRANT SELECT ON "private_schema"."table" TO authenticated;
  

你可以在仪表板的Replication部分或用SQL editor来做这个。

  begin;
  -- remove the supabase_realtime publication
  drop publication if exists supabase_realtime;

  -- re-create the supabase_realtime publication with no tables
  create publication supabase_realtime;
commit;

-- add a table to the publication
alter publication supabase_realtime add table messages;
  

默认情况下,只发送 的记录变化,但如果你想在每次 UPDATEDELETE一个记录时接收 的记录(以前的值)。 你可以将你的表的replica identity 设置为 full

  alter table messages replica identity full;
  

监听public模式中的所有变化:

  const { createClient } = require('@supabase/supabase-js')

const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY)

/*
  Channel name can be any string.
  Event name can can be one of:
    - INSERT
    - UPDATE
    - DELETE
    - *
*/
const channel = supabase
  .channel('schema-db-changes')
  .on('postgres_changes', { event: '*', schema: 'public' }, (payload) => console.log(payload))
  .subscribe()
  

监听public模式中的一张表的变化:

  // Supabase client setup

const channel = supabase
  .channel('table-db-changes')
  .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, (payload) =>
    console.log(payload)
  )
  .subscribe()
  

当表中某一列的值与客户指定的值相匹配时,监听其变化:

  // Supabase client setup

const channel = supabase
  .channel('value-db-changes')
  .on(
    'postgres_changes',
    {
      event: 'UPDATE',
      schema: 'public',
      table: 'messages',
      filter: 'body=eq.hey',
    },
    (payload) => console.log(payload)
  )
  .subscribe()
  

使用同一个通道来监听不同的事件和模式/表/过滤器组合:

  // Supabase client setup

const channel = supabase
  .channel('db-changes')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'messages', filter: 'body=eq.bye' },
    (payload) => console.log(payload)
  )
  .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'users' }, (payload) =>
    console.log(payload)
  )
  .subscribe()