当应用程序出现错误SQL,无法立即修改时,可以通过SQL映射功能,将错误的SQL映射为正确的SQL。SQL映射功能设置成功后,应用程序即使发送了错误的SQL,也会自动映射为正确的SQL。

注意事项

SQL映射功能会将字符串匹配的SQL全部映射为指定的SQL,请谨慎使用。

前提条件

  • 确保Postgresql.conf配置文件中的shared_preload_libraries中已包含polar_sql_mapping,默认已加载该配置;否则添加该配置,然后重启数据库。
  • 确保所在数据库已创建polar_sql_mapping插件, 新创建的数据库默认已创建该插件,旧的数据库仍需手动创建。
    执行以下命令,手动创建插件。
    set default_with_rowids to off;
    create extension polar_sql_mapping;

使用指南

  1. 设置polar_sql_mapping.use_sql_mapping参数,开启SQL映射功能,默认为off
    alter system set polar_sql_mapping.use_sql_mapping=on;
    select pg_reload_conf();
  2. 设置polar_sql_mapping.record_error_sql参数,开启自动收集错误的SQL功能, 默认为off
    alter system set polar_sql_mapping.record_error_sql=on;
    select pg_reload_conf();
    说明 使用完SQL映射功能之后建议关闭错误记录功能,减少对性能的影响。
    alter system set polar_sql_mapping.record_error_sql=off;
    select pg_reload_conf();
  3. 查询错误的SQL。
    select * from emp;
    返回结果如下:
    ERROR:  relation "emp" does not exist
  4. 错误的SQL被记录到了polar_sql_mapping.error_sql_info中,执行以下命令,查询polar_sql_mapping.error_sql_info详细信息。
    select * from polar_sql_mapping.error_sql_info ;
    返回结果如下:
    id  |       query        |           emessage            | calls 
    ----+--------------------+-------------------------------+-------
      1 | select * from emp; | relation "emp" does not exist |     1
  5. 建立映射关系,将error_sql_info中ID为1的SQL映射成指定的SQL。
    select polar_sql_mapping.insert_mapping_id(1, ' select 1');
  6. 再次查询错误的SQL。
    select * from emp;
    返回结果如下:
     ?column? 
    ----------
            1
    (1 row)
    说明 对于大部分的应用程序都是使用PreparedStmt,在写新的SQL的时,需要注意占位符应该是$n而不是'?',示例如下:
    select * from polar_sql_mapping.polar_sql_mapping_table ;
    返回结果如下:
    id |            source_sql            |           target_sql
    ----+----------------------------------+---------------------------------
    4 | select 1 from dual where a = $1; | select 1 from dual where 1 = $1
    (1 row)

参数说明

参数 说明
polar_sql_mapping.max_num 用于控制最多被收集的不同的错误SQL的数量,超过设置数量的SQL会直接被忽略,如果需要修改则需要重启,默认值为10。
polar_sql_mapping.error_sql_info_clear() 用于清空已记录的错误SQL。

替换运行正常的SQL

如果遇到运行没有错误的SQL,仍然想替换,可按照以下步骤进行操作:
  1. 设置polar_sql_mapping.use_sql_mapping参数,开启SQL映射功能,默认为off
    alter system set polar_sql_mapping.use_sql_mapping=on;
    select pg_reload_conf();
  2. 设置polar_sql_mapping.record_error_sql参数,开启自动收集错误的SQL功能, 默认为off
    alter system set polar_sql_mapping.record_error_sql=on;
    select pg_reload_conf();
    说明 使用完SQL映射功能之后建议关闭错误记录功能,减少对性能的影响。
    alter system set polar_sql_mapping.record_error_sql=off;
    select pg_reload_conf();
  3. 设置匹配模式,所有模式匹配的SQL都会被保存到polar_sql_mapping.error_sql_info中。

    在如下示例中,即含有test_table的SQL都会被抓取(匹配逻辑和SQL中的LIKE操作符一致)。

    1. 设置匹配模式。
      set polar_sql_mapping.error_pattern to '%test_table%';
    2. 开启匹配模式。
      set polar_sql_mapping.record_error_sql to true;
    3. 创建被抓取的SQL语句。
      select * from test_table;
      
      select a from test_table;
      
      select max(a) from test_table;
    4. 查看polar_sql_mapping.error_sql_info中的抓取结果。
      select * from polar_sql_mapping.error_sql_info;
      返回结果如下:
      id  |             query              |          emessage          | calls
      ----+--------------------------------+----------------------------+-------
        1 | select * from test_table;      | Error Pattern Force Record |     1
        2 | select a from test_table;      | Error Pattern Force Record |     1
        3 | select max(a) from test_table; | Error Pattern Force Record |     1
      (3 rows)
      所有含有test_table的SQL都被抓取到了polar_sql_mapping.error_sql_info中。
  4. 将错误的SQL替换为正确的SQL。
    select polar_sql_mapping.insert_mapping_id(x, 'text');
    说明 其中,x表示SQL的ID,text表示SQL的文本,请根据实际情况进行替换。
  5. 使用完后需要进行还原操作,以免影响性能。
    reset polar_sql_mapping.error_pattern;