Right now, Connection.new_oid is DB.new_oid. That is, in Connection.__init__ it does self.new_oid = db.new_oid. DB.new_oid in turn goes through its own storage instance's new_oid method.
For IMVCCStorages, especially native IMVCCStorages like RelStorage, this means that the new_oid is divorced from any particular Connection and its storage's view of the world.
Since OIDs are globally unique to the database, that's not necessarily automatically a bad thing.
However, in the case of RelStorage, this has two important consequences:
-
It forces the DB's storage to open and keep open a connection to the RDBMS. Moreover, it causes that connection to open---and keep open---a transaction (there's nothing to tell new_oid to commit). Long running transactions in general are not a good thing.
-
As a consequence of the former point, the implementation of new_oid has to be extremely careful not to interfere with any actual storage work. It can't take any locks of any kind. In MySQL, this means that the table used to allocate OIDs has to be MyISAM and not InnoDB. MyISAM tables are completely independent of the transaction system and bypass all kinds of journaling, etc, flushing IO immediately to disk. I suspect there's a potential performance issue here.
A smaller consequence is that even though we preallocate a small pool of OIDs in the master, they're not used effectively, and require global locking to access.
I could have new_oid just "know" that it's only called from DB and that it should autocommit its transaction---that involves extra round trips to the RDBMS server, though.
It seems cleaner to me to have Connection delegate new_oid right to its own storage. For non-IMVCCStorage instances, this changes nothing. For IMVCCStorage instances that need to coordinate with the "master" storage, they'd be responsible for handling that in cooperation with the new_instance method---the easy thing to do would be to copy the method, just like what Connection currently does. For RelStorage, it frees up the connection from the master storage and makes things more cleanly transactional.
Thoughts?
Right now, Connection.new_oid is DB.new_oid. That is, in
Connection.__init__it doesself.new_oid = db.new_oid. DB.new_oid in turn goes through its own storage instance'snew_oidmethod.For IMVCCStorages, especially native IMVCCStorages like RelStorage, this means that the new_oid is divorced from any particular Connection and its storage's view of the world.
Since OIDs are globally unique to the database, that's not necessarily automatically a bad thing.
However, in the case of RelStorage, this has two important consequences:
It forces the DB's storage to open and keep open a connection to the RDBMS. Moreover, it causes that connection to open---and keep open---a transaction (there's nothing to tell
new_oidto commit). Long running transactions in general are not a good thing.As a consequence of the former point, the implementation of
new_oidhas to be extremely careful not to interfere with any actual storage work. It can't take any locks of any kind. In MySQL, this means that the table used to allocate OIDs has to be MyISAM and not InnoDB. MyISAM tables are completely independent of the transaction system and bypass all kinds of journaling, etc, flushing IO immediately to disk. I suspect there's a potential performance issue here.A smaller consequence is that even though we preallocate a small pool of OIDs in the master, they're not used effectively, and require global locking to access.
I could have
new_oidjust "know" that it's only called from DB and that it should autocommit its transaction---that involves extra round trips to the RDBMS server, though.It seems cleaner to me to have Connection delegate new_oid right to its own storage. For non-IMVCCStorage instances, this changes nothing. For IMVCCStorage instances that need to coordinate with the "master" storage, they'd be responsible for handling that in cooperation with the
new_instancemethod---the easy thing to do would be to copy the method, just like what Connection currently does. For RelStorage, it frees up the connection from the master storage and makes things more cleanly transactional.Thoughts?