Opened 7 years ago

Last modified 4 months ago

#7732 assigned New feature

Oracle Backend with SessionPool

Reported by: halturin Owned by: mboersma
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: yandex-sprint oracle session pool
Cc: halturin@…, nleschev@…, ikelly, mboersma, dbergstr@…, erny@… Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

This new backend uses Oracle session pool to improve database performance in threaded environment. Overall speedup for large amounts of small queries is 2-3 times.

Attachments (7)

oracle_pool.tar.gz (10.4 KB) - added by halturin 7 years ago.
Tarball with oracle_pool db backend
oracle_pool.diff (4.3 KB) - added by jbronn 7 years ago.
Oracle pooling patch derived from tarball.
oracle_pool.2.diff (4.1 KB) - added by ikelly 7 years ago.
Modified patch with print statements removed
oracle_pool.3.diff (4.7 KB) - added by nleschev 7 years ago.
oracle_pool.4.diff (7.3 KB) - added by dbergstr@… 6 years ago.
Patch against revision 10578 (1.1beta). Use settings.DATABASE_OPTIONS, general code cleanup.
oracle_pool.5.diff (7.4 KB) - added by mboersma 6 years ago.
Modified patch against trunk [10832] that passes the Django test suite
oracle_pool.6.diff (3.9 KB) - added by erny 6 years ago.
Oracle Pool for 1.0.X branch

Download all attachments as: .zip

Change History (36)

Changed 7 years ago by halturin

Tarball with oracle_pool db backend

comment:1 Changed 7 years ago by serialx

  • milestone set to post-1.0
  • Needs documentation set
  • Needs tests unset
  • Patch needs improvement set
  • Triage Stage changed from Unreviewed to Design decision needed

Can you modify the files to conform with Django Patch Style?

And I think adding a new backend needs design decision. By patching the existing oracle backend and making pooling an option seems to be better. Making milestone post-1.0 since modifying or adding feature to the current backend is currently out of scope of 1.0 release.

Changed 7 years ago by jbronn

Oracle pooling patch derived from tarball.

Changed 7 years ago by ikelly

Modified patch with print statements removed

comment:2 Changed 7 years ago by ikelly

I'm trying to run this through the test suite, and I'm seeing lots of non-deterministic test failures. When I try to run the full test suite, I get an early error where it's setting up the test database and apparently trying to reset a sequence that doesn't exist. When I try to run just the basic test, the test runs, but lots of queries return dramatically incorrect results. It's not obvious where this is coming from, but it needs to be addressed before this can be committed.

comment:3 Changed 7 years ago by nleschev

  • Cc halturin@… nleschev@… added

We have included all changes in this patch(oracle_pool.3.diff). Also has been added 4 settings.
DATABASE_SESSION_POOL=[True/False]
DATABASE_SESSION_POOL_MIN=1
DATABASE_SESSION_POOL_MAX=3
DATABASE_SESSION_POOL_INCREMENT=1

Changed 7 years ago by nleschev

comment:4 Changed 6 years ago by ikelly

  • Cc ikelly added

comment:5 Changed 6 years ago by mboersma

  • Cc mboersma added

comment:6 Changed 6 years ago by mboersma

  • Keywords oracle session pool added

comment:7 Changed 6 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

Changed 6 years ago by dbergstr@…

Patch against revision 10578 (1.1beta). Use settings.DATABASE_OPTIONS, general code cleanup.

comment:8 Changed 6 years ago by anonymous

  • Cc dbergstr@… added

comment:9 Changed 6 years ago by mboersma

  • milestone set to 1.2
  • Needs tests set
  • Owner changed from nobody to mboersma
  • Status changed from new to assigned
  • Triage Stage changed from Design decision needed to Accepted

I'm still not able to get cx_Oracle's SessionPool to behave correctly for the entire Django test suite. I've tried the 4/16/09 patch here as well as my own implementations, but we quickly get test case failures that I've had a very hard time tracking down.

I have not given up--I think this should offer obvious speed improvements. I'm marking this as

comment:10 Changed 6 years ago by mboersma

...(continued) I'm marking this as needed for the next big release.

comment:11 Changed 6 years ago by dbergstr@…

I've never looked at the test suite, nor do I have a clue how cx_oracle manages connections and transactions, but perhaps problems arise because some of the tests don't do a commit? The connection would then go back into the pool with an open transaction, and when it was next pulled out of the pool, the state in that connection would be different from what is expected. In general, using any pooled resource can expose sloppy practices in the calling code (failure to properly initialize shared memory, db connection leaks, etc.).

Changed 6 years ago by mboersma

Modified patch against trunk [10832] that passes the Django test suite

comment:12 Changed 6 years ago by erny

  • Cc erny@… added

comment:13 Changed 6 years ago by erny

Can we have a bit of feedback about if the patch is supposed to work correctly now and it's effectivity?

comment:14 Changed 6 years ago by ikelly

The patch works as far as we've seen. The issues that were arising in the test suite had to do with the test setup attempting to disconnect, change the connection parameters, and reconnect, which failed because of the pool. For the same reason, I suspect it will take some work to make this compatible with the multidb branch, but otherwise it's usable.

comment:15 Changed 6 years ago by erny

The patch didn't work for me for 1.0.X branch rev10865. I attach al alternative patch for this version.

Changed 6 years ago by erny

Oracle Pool for 1.0.X branch

comment:16 Changed 6 years ago by erny

I found that the used SessionPools getmode parameter may no match everybody's requirements. This should be a parameter. Would be great if this really was a parameter of p.acquire()

comment:17 Changed 6 years ago by erny

Bad news: I get DatabaseError: ORA-03135: connection lost contact with cx_Oracle 4.4.1 which does not drop/release/reconnect the connections. After the all connections are acquired, I get: ORA-24418: Cannot open further sessions. As it's author in the cx_Oracle mailing list suggest, a pool.drop(connection) is not enough, as it raises another exception. The complete pool may be replaced.

comment:18 Changed 5 years ago by edcrewe

I have packaged up a version of this pooling backend, and made it available on pypi

see http://pypi.python.org/pypi/django-oraclepool

This includes some tests, and other extra little bits.
It has also been tested against 1.1 and 1.2

  • Ed Crewe

comment:19 Changed 5 years ago by Alex

  • milestone changed from 1.2 to 1.3

We are past the feature phase of 1.2.

comment:20 Changed 4 years ago by lukeplant

  • Severity set to Normal
  • Type set to New feature

comment:21 Changed 3 years ago by jacob

  • milestone 1.3 deleted

Milestone 1.3 deleted

comment:11 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:12 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:13 Changed 2 years ago by skyl

I have what may be a more simple approach to the problem. I branched off of the current django master on github. I can easily remove the extraneous flake8 changes and squash into one commit for a pull request:

https://github.com/skyl/django/compare/7732-oracle-sessionpool

It appears that the tests will pass against Oracle (takes forever). However, I'm not that familiar with the ins and outs of how database backends work. If someone could look at my patch and let me know if there is something obvious I've missed, I would appreciate it. On a simple test webapp, I'm experiencing a significant speedup with the patch.

comment:14 Changed 2 years ago by akaariai

It seems that allowing the use of the cx_Oracle inbuilt pooler is a good idea.

As for the implementation: is the use of class level pool variable really safe? It seems the pool instance is connection settings dependent, so having just one pool per project seems suspicious.

Also, the close() implementation should probably do a rollback before releasing the connection back to the pool.

comment:15 Changed 2 years ago by skyl

I changed to 1 pool per alias; 1 pool per project was definitely wrong. I also changed to doing a self.connection.rollback() in close before releasing the connection.

comment:16 Changed 2 years ago by erny

I had the following problems in the past: The Oracle pools is a "per process" pool. Each Python Process gets its own pool. Supposing X processes (apache prefork, wsgi, etc.) with each Y min connections we get X * Y connections. So keep your min connections count low. With Oracle 11, there seems to be a server side session pool which should be much more convenient, but I didn't test it.

comment:17 Changed 2 years ago by skyl

Unfortunately, I think there needs to be some error-checking on the connection after it is acquired from the pool. After some hours (I didn't configure the instance I'm running against so I'm not sure how long), I get ORA-02399: exceeded maximum connect time, you are being logged off; then, the pool continues to try to get the same connection, failing every time with, ORA-01012: not logged on. I think there are 2 options then.

1) put a CONN_MAX_AGE parameter in the SESSION_POOL settings dict and drop the connection if it is close enough to that age
2) ping the connection after it is acquired and drop it if it is not usable

(1) Age is not an attribute of the connection that I can see; so, it would be ugly to do our own book-keeping on the age of the connections in the pools we are holding. This does not cover other possible error scenarios.
(2) This would be a hit to performance every time a connection is acquired.

I think (2) would be easy enough to add. Other suggestions?

comment:18 Changed 4 months ago by thedrow

Since I believe that adding pooled backends was rejected from Django shouldn't this issue be closed?

Note: See TracTickets for help on using tickets.
Back to Top