You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Supabase-py批量取数时遭遇httpx.ReadTimeout问题求助

问题

Supabase表内有375000条数据,我通过循环调用API批量获取所有数据的ref_id,单次API请求限制为20000条。但获取到约200000条数据后,总会触发httpx.ReadTimeout: The read operation timed out错误,最多仅能获取到240000条数据。已尝试调整循环后的等待时间,修改单次请求的条数(10000、30000、50000),但无论哪种设置,都会在获取到150000-200000条左右时卡住。

代码实现

existing_search_result = supabase.table('vehicles').select('ref_id', count='exact').order('id', desc=False).execute()
existing_items = []
range_step = len(existing_search_result.data)
total_existing_items = existing_search_result.count
print(total_existing_items)
while len(existing_items) < total_existing_items:
    try:
        existing_items += (
            supabase.table(
                'vehicles'
            ).select('ref_id')
            .order('id', desc=False)
            .range(range_start, range_start + range_step)
            .execute()
        ).data
        range_start += range_step
    except Exception as e:
        logging.exception(e)
    print(range_start, len(existing_items))
    time.sleep(0.30)

错误日志

2022-10-23 21:04:14,168:ERROR - The read operation timed out
Traceback (most recent call last):
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_exceptions.py", line 8, in map_exceptions
    yield
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/backends/sync.py", line 26, in read
    return self._sock.recv(max_bytes)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/ssl.py", line 1226, in recv
    return self.read(buflen)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/ssl.py", line 1101, in read
    return self._sslobj.read(len)
socket.timeout: The read operation timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_transports/default.py", line 60, in map_httpcore_exceptions
    yield
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_transports/default.py", line 204, in handle_request
    resp = self._pool.handle_request(req)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/connection_pool.py", line 253, in handle_request
    raise exc
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/connection_pool.py", line 237, in handle_request
    response = connection.handle_request(request)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 90, in handle_request
    return self._connection.handle_request(request)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 102, in handle_request
    raise exc
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 81, in handle_request
    ) = self._receive_response_headers(**kwargs)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 143, in _receive_response_headers
    event = self._receive_event(timeout=timeout)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 172, in _receive_event
    data = self._network_stream.read(
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/backends/sync.py", line 26, in read
    return self._sock.recv(max_bytes)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/contextlib.py", line 135, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc)
httpcore.ReadTimeout: The read operation timed out

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/ak4zh/updater/main.py", line 278, in job
    supabase.table(
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/postgrest/_sync/request_builder.py", line 53, in execute
    r = self.session.request(
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_client.py", line 802, in request
    return self.send(request, auth=auth, follow_redirects=follow_redirects)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_client.py", line 889, in send
    response = self._send_handling_auth(
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_client.py", line 917, in _send_handling_auth
    response = self._send_handling_redirects(
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_client.py", line 954, in _send_handling_redirects
    response = self._send_single_request(request)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_client.py", line 990, in _send_single_request
    response = transport.handle_request(request)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_transports/default.py", line 204, in handle_request
    resp = self._pool.handle_request(req)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/contextlib.py", line 135, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/ak4zh/updater/venv/lib/python3.9/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.ReadTimeout: The read operation timed out
解决方案

1. 调整HTTP客户端超时时间

Supabase的Python客户端基于httpx构建,默认超时可能不足以处理大分页请求。初始化客户端时自定义更长超时:

import httpx
from supabase import create_client, Client

supabase_url = "你的Supabase URL"
supabase_key = "你的Supabase密钥"

# 设置30秒超时,可根据实际情况调整
client_options = {
    "http_client": httpx.Client(timeout=30.0)
}

supabase: Client = create_client(supabase_url, supabase_key, options=client_options)

2. 修复分页逻辑漏洞

原代码中range_start未初始化,且range_step依赖首次请求返回数据量,容易出现分页偏差。建议固定步长并修正range参数(Supabase的range是左闭右闭区间):

existing_search_result = supabase.table('vehicles').select('ref_id', count='exact').execute()
total_existing_items = existing_search_result.count
print(total_existing_items)

existing_items = []
range_step = 20000  # 固定单次请求条数
range_start = 0

while len(existing_items) < total_existing_items:
    try:
        # 计算当前批次结束位置,避免超出总条数
        range_end = min(range_start + range_step, total_existing_items)
        batch_data = (
            supabase.table('vehicles')
            .select('ref_id')
            .order('id', desc=False)
            .range(range_start, range_end - 1)  # 左闭右闭,结束位置减1
            .execute()
        ).data
        existing_items.extend(batch_data)
        range_start = range_end
        print(f"已获取 {len(existing_items)}/{total_existing_items} 条数据")
    except Exception as e:
        logging.exception(e)
        # 超时后不跳过当前批次,等待1秒后重试
        time.sleep(1)
    time.sleep(0.3)

3. 增加指数退避重试机制

针对超时错误,实现重试逻辑,应对临时网络波动或服务端负载高峰:

from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type

# 针对httpx.ReadTimeout重试,最多3次,等待时间指数增长
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10), retry=retry_if_exception_type(httpx.ReadTimeout))
def fetch_batch(range_start, range_end):
    return (
        supabase.table('vehicles')
        .select('ref_id')
        .order('id', desc=False)
        .range(range_start, range_end - 1)
        .execute()
    ).data

# 循环调用带重试的获取函数
while len(existing_items) < total_existing_items:
    try:
        range_end = min(range_start + range_step, total_existing_items)
        batch_data = fetch_batch(range_start, range_end)
        existing_items.extend(batch_data)
        range_start = range_end
        print(f"已获取 {len(existing_items)}/{total_existing_items} 条数据")
    except Exception as e:
        logging.exception("重试3次后仍失败,终止任务")
        break
    time.sleep(0.3)

4. 优化数据库查询性能

  • 确保id字段有索引:如果id不是主键,手动创建索引:
    CREATE INDEX idx_vehicles_id ON vehicles(id);
    
  • 去掉不必要的排序:如果ref_id的顺序不影响后续处理,删除.order('id', desc=False),减少数据库排序开销。

5. 降低单次请求数据量

尝试更小的批次(比如10000条),减少单请求的数据传输量,降低超时概率。

内容的提问来源于stack exchange,提问作者Rawand Ahmed Shaswar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:15:41