Django 的异步 ORM 有 a 前缀的方法和 async for,看起来什么都能 await 了。这篇列出还不能做的事:懒加载、事务;并且在 PostgreSQL 上量一下「并发查询」是不是真的并发。
post.author (没有 select_related) → SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_a
select_related("author") 之后 post.author: ann
遍历 author.post_set.all() → SynchronousOnlyOperation
async for 遍历 author.post_set.all(): ['p1']async 里 with transaction.atomic() → SynchronousOnlyOperation async with transaction.atomic() → TypeError: 'django.db.transaction.Atomic' object does not support the a 把事务放进 sync_to_async 包起来的同步函数里 → 成功,Author 数 2
事件循环所在线程: MainThread acount() / aget() 执行 SQL 的线程: ['ThreadPoolExecutor-0_0', 'ThreadPoolExecutor-0_0']
a 前缀方法本身是 async,但查询仍是同步的数据库驱动调用,被放到线程里执行。所以它的好处是「不阻塞事件循环」,不是「数据库查询并行」。
10 个 async 查询(默认 thread_sensitive)总耗时 2030 ms;此刻正在执行 pg_sleep 的连接数: 1 10 个 thread_sensitive=False 的同步查询总耗时 227 ms;此刻正在执行 pg_sleep 的连接数: 10 (每个线程各开自己的连接)
要真正并发地跑多个数据库查询,只能用 thread_sensitive=False 把它们放到不同线程——但每个线程会自己开连接,要自己负责关闭(实验里用 connection.close()),连接数会随并发数增长。(用 pg_sleep 模拟的是「慢查询」,没有测真实业务查询。)