-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transaction retries are not always handled properly #207
Comments
Are they already using the helper?
|
They mentioned they are using Pandas which is using sqlalchemy underneath, I do wonder if Pandas is making the right call underneath |
If they are using vanilla pandas https://pandas.pydata.org/docs/user_guide/io.html#io-sql-method |
I took a look at the pandas github repo. The code checks for a SQLAlchemy connection and the starts using the normal statement functionality. The code keeps going down the normal SQL text() statement path. Hopefully this information is helpful.
|
Further to my earlier comment, this is what I had in mind: import pandas as pd
import sqlalchemy as sa
from sqlalchemy_cockroachdb.transaction import run_transaction
engine = sa.create_engine(
"cockroachdb+psycopg2://root@localhost:26257/defaultdb"
)
def crdb_insert_trans(table, eng, keys, data_iter):
# to_sql() "method=" adapted from the example at
# https://pandas.pydata.org/docs/user_guide/io.html#io-sql-method
def callback(conn):
tbl = sa.Table(
table.name,
sa.MetaData(),
schema=table.schema,
autoload_with=eng,
)
data = [dict(zip(keys, row)) for row in data_iter]
conn.execute(sa.insert(tbl), data)
run_transaction(eng, callback)
df = pd.DataFrame([(1, "foo"), (2, "bar")], columns=["id", "txt"])
df.to_sql(
"table1", engine, if_exists="append", index=False, method=crdb_insert_trans
) |
@dikshant - Does my code sample above resolve the issue? |
@gordthompson The code calls the pandas read_sql_query().
|
@ddennerline3 - So is |
pd.read_sql_query() is only generating an error that is probably ignored somewhere when the exception is raised.
|
Try wrapping the import pandas as pd
import sqlalchemy as sa
from sqlalchemy_cockroachdb.transaction import run_transaction
engine = sa.create_engine(
"cockroachdb+psycopg2://root@localhost:26257/defaultdb"
)
def read_sql_qry_trans(qry, engine_):
def callback(conn):
return pd.read_sql_query(qry, conn)
return run_transaction(engine_, callback)
sql = """\
SELECT 1 AS id, 'foo' AS txt
UNION ALL
SELECT 2 AS id, 'bar' AS txt
"""
df = read_sql_qry_trans(sql, engine)
print(df)
"""
id txt
0 1 foo
1 2 bar
""" |
Is run_transaction() compatible with Postgres? |
I just tried my sample code above with a
True. Your wrapper could always call |
I recently built a custom DB query tool and used SQLAlchemy; it started experiencing transaction errors. To work around the Transaction retry errors, I created this run_statement() function below. I saw the CRDB adapter code is following a similar pattern, but I don't believe it’s auto-retrying. FWIW, it took some effort to find the right combination of exceptions and error code to make this function work correctly. It works for both Postgres and CRDB.
|
@ddennerline3 - Thanks for sharing your code. Just to confirm: Did it solve the
Did you try it? It's certainly set up to do that. One subtle difference between your code and the code in transaction.py is that your code interprets |
There are two issues I was trying to address:
On both items, I suspect if the transaction.py code was changed slightly, then raw SQLAlchemy statements and Pandas my operate correctly. The run_statement() code above is required because the transaction.py code doesn't seem to retry.
I didn't try to 100% emulate the transaction.py interface; thus the difference in retry=None. |
Oh, so you suspect that except sqlalchemy.exc.DatabaseError as e: in transaction.py might be too specific? |
Also, are you running SQLAlchemy 2.0, or 1.4? |
SQLAlchemy 2.0 I tried originally to use DatabaseError, but that exception wasn't caught. When I shifted to DBAPIError, the exception was caught and I could check the original error. I did have benefit of running the code on stressed cluster in a debugger. |
Fixes: cockroachdb#207 Catch DBAPIError to handle errors not covered by DatabaseError.
Okay, thanks. I have pushed an update to my branch. Before I submit a PR I would be grateful if you could
and verify that it avoids the issue in your particular environment. |
We have a customer who is experiencing issues with transaction retries not being handled in sqlalchemy v 1.4.x. More details to follow but we would like to add transaction retries where applicable.
cc: @gordthompson @rafiss
The text was updated successfully, but these errors were encountered: