Кэширует ли Postgres наши запросы и как мы можем их обойти? - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь запустить следующий фрагмент кода python3:

import os
import psycopg2
import logging

# Set max attempts before giving up
MAX_ATTEMPTS = 5

# Set basic logging config to debug (i.e. log everything).
# By default, this will log te stdout (i.e. it will behave the same as print)
logging.basicConfig(level=logging.DEBUG)

# Grab DB url from env variable
database_url = os.environ.get('DATABASE_URL')

assert database_url is not None, 'DATABASE_URL env variable must be set to a postgres connection string.'

# Initiate psycopg2 and instantiate a cursor object
conn = psycopg2.connect(database_url)
cursor = conn.cursor()


# Define function to delete old records
def delete_old_records(cur):
    # execute a query to delete old records. We're going to refer to this as the "delete" command
    query = 'DELETE FROM my_table WHERE id NOT IN ( SELECT id FROM ( SELECT id FROM my_table ORDER BY id DESC LIMIT 1850 ) foo);'
    cur.execute(query)


# Set variables to keep track of loop
successful = False
attempts = 0

# While not successful and max attempts not reached
while not successful and attempts < MAX_ATTEMPTS:
    try:
        # Attempt to delete old records
        delete_old_records(cursor)
        # Set successful to True if no errors were encountered in the previous line
        successful = True
        # Log a message
        logging.info('Successfully truncated old records!')
    # If some psycopg2 error happens
    except psycopg2.Error as e:
        # Log the error
        logging.exception('Got exception when executing query')
        # Rollback the cursor and get ready to try again
        conn.rollback()
        # Increment attempts by 1
        attempts += 1

# If not able to perform operation after max attempts, log message to indicate failure
if not successful:
    logging.warning(f'Was not successfully able to truncate logs after {MAX_ATTEMPTS} retries. '
                    f'Check logs for traceback (console output by default).')

Вот проблема:

  1. Код выполняется успешно и без ошибок.Однако, когда мы запускаем следующую команду (в дальнейшем называемую командой «count») на postico (Postgres GUI для Mac):

    SELECT count(*) from my_table;
    

    Мы получаем 1860 вместо 1850 (т.е. строки не были удалены).

  2. При выполнении команды удаления вручную в psql или в postico мы получаем правильные результаты при выполнении команды COUNT в psql или postico соответственно.Однако мы получаем разные результаты при выполнении команды в ipython.

  3. Когда у меня есть открытое соединение с БД на ipython на компьютере A, и я запускаю команду удаления, и я открываюдругой соединитель с БД на ipython на компьютере B и запустите команду count, я вижу, что число строк БД не изменилось, т.е. все еще 1860, не сокращено до 1850.

Я подозреваю, что кэширование/ памятка, но я не совсем уверен, что моя команда действительно работает.Есть ли что-то в psycopg2, postico или postgres, которые могут быть причиной этого?и как мы можем обойти это?Мы не видим четкого кэша на postico или psycopg2 / postgres.

1 Ответ

0 голосов
/ 28 сентября 2018

Кэширование не включено.PostgreSQL не кэширует результаты запроса.

Вы просто забыли COMMIT удалить транзакцию, поэтому ее эффекты не видны ни в одной параллельной транзакции.

...