【问题标题】:Two instances of an application connected with two schemas of same postgres database is unable to differentiate与同一个 postgres 数据库的两个模式连接的应用程序的两个实例无法区分
【发布时间】:2017-06-20 18:17:51
【问题描述】:

我正在开发一个 SaaS 解决方案,目前在 kubernetes 上配置 sonarqube 和 gerrit 应用程序。

作为其中的一部分,我想在我的 postgres 数据库中为我提供的每个新应用程序创建一个新模式。应用程序正在使用以下连接字符串进行连接,(即,instance1、instance2、instance3...等等)

jdbc:postgresql://localhost/gerrit?user=instance1&password=instance1&currentSchema=instance1

通过在新架构中创建关联表,该解决方案适用于第一次配置 gerrit 和 sonarqube。但是,它在同一数据库中的另一个新架构第二次失败,这些失败很可能与尝试创建关联表但它已经存在的应用程序有关。

我正在使用以下 sql 创建架构。

create user instance1 with login password 'instance1';
CREATE SCHEMA instance1 AUTHORIZATION instance1;
ALTER ROLE instance1 SET search_path=instance1;


create user instance2 with login password 'instance2';
CREATE SCHEMA instance2 AUTHORIZATION instance2;
ALTER ROLE instance2 SET search_path=instance2;

我很难理解这种行为,针对同一数据库的两个不同架构配置的两个单独的应用程序如何能够看到彼此的表。

为了重现这个问题,我快速编写了一个 python 脚本来连接同一个数据库的两个不同模式并创建同一个表,它工作正常。

import psycopg2
import sys
import random

_user = raw_input("user: ")
con = None

try:

   con = psycopg2.connect(database='gerrit', user=_user,
                           password=_user, host='localhost')
   cur = con.cursor()
   cur.execute('SELECT version()')
   ver = cur.fetchone()
   print ver
   table_name = 'tbl_%d' %(1)#random.randint(1,100))
   cur.execute('CREATE TABLE %s (id serial, name varchar(32));' %(table_name))
   cur.execute('INSERT INTO %s values (1, \'%s\');' %(table_name, table_name+_user))
   con.commit()
   cur.execute('SELECT * from %s' %(table_name))
   ver = cur.fetchone()
   print ver
except psycopg2.DatabaseError, e:
   print 'Error %s' % e
   sys.exit(1)
finally:
   if con:
       con.close()

输出如下

$ python pg_test_connect.py
user: instance1
(1, 'tbl_1instance1')

$ python pg_test_connect.py
user: instance2
(1, 'tbl_1instance2')

由于我能够从 python 验证此工作流程,这是 JDBC 或应用程序(gerrit 和 sonarqube)的限制,有人遇到过 postgres 的这个问题吗?

【问题讨论】:

  • 在 postgres 端,您可以增加日志记录(记录所有语句)以查看这些残缺的 ORM 尝试做什么。另外:我会将 pg_catalog 添加到 search_paths。 (甚至可能是公开的)

标签: postgresql sonarqube multi-tenant gerrit saas


【解决方案1】:

默认的 search_path 是“$user”,public。其中 $user 将替换为 SESSION_USER 的值,因此无需显式指定 ROLE 的 search_path。 但需要注意的是,用户必须对搜索路径中的任何模式拥有 USAGE 权限。如果“$user”模式不存在,它将被忽略。 (https://www.postgresql.org/docs/9.4/static/runtime-config-client.html)。

【讨论】:

    【解决方案2】:

    所以,在修改了 gerrit 源代码后,我发现它不支持 currentSchema 选项。这或多或少地解释了它为什么会这样。

    【讨论】:

      猜你喜欢
      • 2011-06-03
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      • 2014-02-09
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多