| Bug #102053 | Python sql connection pool not updating after query with zero results | ||
|---|---|---|---|
| Submitted: | 22 Dec 2020 19:37 | Modified: | 17 Mar 2021 4:32 |
| Reporter: | James Morris | Email Updates: | |
| Status: | No Feedback | Impact on me: | |
| Category: | Connector / Python | Severity: | S1 (Critical) |
| Version: | 8.0.22 | OS: | Ubuntu (18.04) |
| Assigned to: | CPU Architecture: | x86 | |
| Tags: | connection-pool, python | ||
[22 Dec 2020 19:37]
James Morris
[23 Dec 2020 6:23]
MySQL Verification Team
Hello James Morris, Thank you for the report! regards, Umesh
[16 Feb 2021 0:16]
Jose Israel Gomez Delgado
Hello James, and thanks for submit your bug. The behavior you described is
not a bug and is an expected behavior due to the default value of the
`autocommit` option, which is set to False by default, in short by setting
`autocommit=True` or adding `'autocommit':True` to your connection settings
dictionary object you will get a more aligned behavior to your expectations.
However, please allow me to try to explain why you got this behavior even
after you have invoked the `commit()` method after your insert statement and
how you can get the same results with the `autocommit` option set to False.
By default, `autocommit` option is set to False, whenever you use a pool of
connections or a single connection; this allow to each connection work as in
a different session, and any change will not be applied or see be visible by
other sessions until commit is invoked. And in addition, that for each
session it is very important to invoke or execute `commit()` statement but
not just to commit the changes on this session, it becomes very important in
order of accept the changes committed by other sessions after this session
were started. Furthermore, while implementing pooling due to the nature of
how it works internally because on pooling the connections are not fully
close and reopen; they are just cleanup in order of be reused later, which
is faster than open new connections.
If we apply this theory adding a commit call prior of the `select` statement,
will do the trick
-----------8<---------
for _ in range(12):
con = mysql.connector.connect(pool_name="mypool")
cur = con.cursor()
con.commit() # This commit accepts the inserts by the other session.
cur.execute("SELECT id FROM test WHERE id = '123';")
result = cur.fetchall()
cur.close()
con.close()
print(result)
----------->8---------
and gives us the expected output:
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
[('123',)]
In the following script, at the run_test() method you can find the same test
code but with the call to `commit()` prior the select:
#!/usr/bin/python
import mysql.connector
def create_clean():
# db has 1 empty table 'test' with one varchar field 'id'
# Drop table if exists, and create it new
con1 = mysql.connector.connect(**dbvars)
cur1 = con1.cursor()
stmt_drop = "DROP TABLE IF EXISTS test"
cur1.execute(stmt_drop)
stmt_create = (
"CREATE TABLE test ("
"id VARCHAR(30) DEFAULT '' NOT NULL, "
"PRIMARY KEY (id))"
)
cur1.execute(stmt_create)
cur1.execute("COMMIT;")
return True
def insert():
con1 = mysql.connector.connect(**dbvars)
cur1 = con1.cursor()
cur1.execute("INSERT INTO test VALUES ('789');")
cur1.execute("COMMIT;")
return True
def run_test():
con = mysql.connector.connect(pool_name="mypool", pool_size=3,
pool_reset_session=False, **dbvars)
cur = con.cursor()
cur.execute("SELECT id FROM test WHERE id = '123';")
result = cur.fetchall()
cur.close()
con.close()
con = mysql.connector.connect(pool_name="mypool")
cur = con.cursor()
cur.execute("INSERT INTO test VALUES ('123');")
con.commit()
cur.close()
con.close()
for _ in range(12):
con = mysql.connector.connect(pool_name="mypool")
cur = con.cursor()
con.commit() # This commit accepts the inserts by the other session.
cur.execute("SELECT id FROM test WHERE id = '123';")
result = cur.fetchall()
cur.close()
con.close()
print(result)
if __name__ == '__main__':
dbvars = {
'host':'localhost',
'user':'root','passwd':'',
'db':'test',
"port": 4824,
#"use_pure":True,
#'autocommit':True
}
create_clean()
run_test()
I hope this behavior is clarified now, finally once again thank you for open
a bug and use C/py.
[18 Mar 2021 1:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
