执行(sql)后调用fetchall()是否会第二次读取数据?
我刚学会使用 MySQLDb 这个 Python 包,并且对从选择语句中获取行数据有了一些了解。
cursor.execute("SELECT movie_list_....")
result = cursor.fetchall()
我注意到,当我运行第一个命令时,它显示的是 123L,这表示受影响的行数。当我运行第二个命令时,数据实际上是被提取出来的。
当我使用 fetchall() 的时候,它是否会再次读取数据库,获取当时的状态呢?
我在意的是这样的情况:我执行了一个选择操作,影响了 30 行数据。我通过 cursor.fetchmany(10) 每次处理 10 行。我把这 10 个数字加起来(这只是个例子!)。前两次的操作进行得很顺利,但在第三次操作之前,表上进行了一个更新,影响了同样的行。然后进行第三次操作。
那么,我的总和会反映出选择查询时的数据库状态吗?还是会是旧值和新值的混合?
我记得在大学里学过一个叫“脏读问题”的东西。但那是在一次性读取所有行的情况下,而不是像 fetchmany() 这样分批读取。
请帮我补充一下关于数据库理论的知识,以解决这个问题。
1 个回答
这要看你是选择“普通”的客户端游标还是服务器端游标。
在内部,客户端游标(CS)使用的是 mysql_store_result()
,而服务器端游标(SS)使用的是 mysql_use_result()
。
通常情况下,客户端游标更受欢迎,因为它在发送查询后会立即获取所有数据。这对服务器来说工作量要小得多,因为表格可以被释放。所以如果你是逐条获取数据,服务器不会察觉,因为所有数据都在本地,你在查询时得到了数据的快照。
如果你有很多数据,或者希望快速看到前面的数据,可以选择服务器端游标。但这样你需要更加小心对数据库的操作,可能还要在一个单独的线程中获取数据,尽快完成这个任务,以减少对数据库的负担,因为表格会一直保持打开状态并被锁定,直到所有数据都发送和获取完毕。因此,在读取数据时不能有数据更改,同时其他数据库用户可能会因为更长的表锁而受到影响。