我应该尽量减少在 Pony ORM 中使用 db_session 吗? db_session 的目的是什么?
Should I minimize the usage of db_session in Pony ORM? What is the purpose of db_session?
我想知道,我是否应该尽量减少 db_session 的使用?让我们考虑这两个等价的例子:
A)
def do_stuff():
with db_session:
task = orm.make_proxy(Task.select().first())
task.mark_started()
...
this_function_might_take_a_long_time(task)
...
with db_session:
task.mark_done()
B)
@db_session
def do_stuff():
task = Task.select().first()
task.mark_started()
commit()
...
this_function_might_take_a_long_time(task)
...
task.mark_done()
通过阅读文档我可以看出 Pony doesn't encourage 微观管理 db_sessions
With this code each of view function you will define will be wrapped with db_session so you should not care about them.
但是,here 这表明打开它可能需要付费(编辑:不需要,请阅读答案)
Before sending the first query, Pony gets a database connection from the connection pool.
我说 B 以外的任何东西都是过早的优化,并且 A 应该只在有限的 DB 连接数场景中考虑吗?
Pony ORM作者Alexander Kozlovsky @metaprogrammer answered this in the Official Pony ORM Telegram chat.
db_session的目的是管理三件事:
数据库连接
Pony 将单独的连接关联到每个线程。如果进程不使用线程,那么只会使用一个连接。当 db_session 结束时,它 returns 它连接到连接池。这意味着连接保持打开状态并保留以备将来使用。接下来 db_session 将使用相同的连接。因此,关于连接使用,单个 db_session 和多个顺序 db_sessions
之间没有区别
交易状态
当db_session结束时,它执行隐式提交。隐式和显式提交之间没有区别,因此如果您有一个带有手动 commit() 调用的 db_session,它与多个顺序 db_session 相同。但是,如果您不使用显式 commit(),那么 long db_session 可能会持有数据库锁并阻止其他进程使用数据库或特定 table 直到执行提交
已加载对象的内存缓存
单个 db_session 和多个顺序 db_session 之间的主要区别在于管理从数据库加载的对象的内存缓存。每个 db_session 都有单独的缓存。缓存中的对象通过关系交叉链接。如果加载一堆 Course、Student 和 Group 对象,它们都通过关系属性相互链接。因此,不可能从缓存中卸载一些对象并保留其余对象。垃圾收集器不能只从缓存中收集一些对象,因为它们都通过循环引用相互指向。所以缓存只有在db_session完成后才能整体删除。
所以,如果你有一个长期存在的db_session,它直到最后才会释放内存。但是几个较小的 db_session 可能需要多次从数据库加载同一个对象。所以有一个memory/performance权衡
P.S。即使 db_session 完成,连接仍将保持,直到程序结束或显式 db.disconnect() 调用。仅当 db_session 中的某些数据库异常导致回滚时,Pony 才会隐式关闭连接。
我想知道,我是否应该尽量减少 db_session 的使用?让我们考虑这两个等价的例子:
A)
def do_stuff():
with db_session:
task = orm.make_proxy(Task.select().first())
task.mark_started()
...
this_function_might_take_a_long_time(task)
...
with db_session:
task.mark_done()
B)
@db_session
def do_stuff():
task = Task.select().first()
task.mark_started()
commit()
...
this_function_might_take_a_long_time(task)
...
task.mark_done()
通过阅读文档我可以看出 Pony doesn't encourage 微观管理 db_sessions
With this code each of view function you will define will be wrapped with db_session so you should not care about them.
但是,here 这表明打开它可能需要付费(编辑:不需要,请阅读答案)
Before sending the first query, Pony gets a database connection from the connection pool.
我说 B 以外的任何东西都是过早的优化,并且 A 应该只在有限的 DB 连接数场景中考虑吗?
Pony ORM作者Alexander Kozlovsky @metaprogrammer answered this in the Official Pony ORM Telegram chat.
db_session的目的是管理三件事:
数据库连接
Pony 将单独的连接关联到每个线程。如果进程不使用线程,那么只会使用一个连接。当 db_session 结束时,它 returns 它连接到连接池。这意味着连接保持打开状态并保留以备将来使用。接下来 db_session 将使用相同的连接。因此,关于连接使用,单个 db_session 和多个顺序 db_sessions
之间没有区别交易状态
当db_session结束时,它执行隐式提交。隐式和显式提交之间没有区别,因此如果您有一个带有手动 commit() 调用的 db_session,它与多个顺序 db_session 相同。但是,如果您不使用显式 commit(),那么 long db_session 可能会持有数据库锁并阻止其他进程使用数据库或特定 table 直到执行提交
已加载对象的内存缓存
单个 db_session 和多个顺序 db_session 之间的主要区别在于管理从数据库加载的对象的内存缓存。每个 db_session 都有单独的缓存。缓存中的对象通过关系交叉链接。如果加载一堆 Course、Student 和 Group 对象,它们都通过关系属性相互链接。因此,不可能从缓存中卸载一些对象并保留其余对象。垃圾收集器不能只从缓存中收集一些对象,因为它们都通过循环引用相互指向。所以缓存只有在db_session完成后才能整体删除。 所以,如果你有一个长期存在的db_session,它直到最后才会释放内存。但是几个较小的 db_session 可能需要多次从数据库加载同一个对象。所以有一个memory/performance权衡
P.S。即使 db_session 完成,连接仍将保持,直到程序结束或显式 db.disconnect() 调用。仅当 db_session 中的某些数据库异常导致回滚时,Pony 才会隐式关闭连接。