首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是mysql缓冲游标w.r.t python mysql连接器

什么是mysql缓冲游标w.r.t python mysql连接器
EN

Stack Overflow用户
提问于 2017-10-11 07:13:59
回答 1查看 12.1K关注 0票数 19

有人能举个例子来理解这一点吗?

执行查询后,MySQLCursorBuffered游标从服务器获取整个结果集并缓冲行。对于使用缓冲游标执行的查询,行取取方法(如set ())从缓冲行集返回行。对于非缓冲游标,在调用行取方法之前,不会从服务器获取行。在这种情况下,必须确保在同一连接上执行任何其他语句之前获取结果集的所有行,否则将引发InternalError (未读取结果发现)异常。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-27 01:24:25

我认为这两种类型的Cursor是不同的。

第一种方法是,如果使用缓冲游标执行查询,则可以通过检查MySQLCursorBuffered.rowcount获得返回的行数。但是,未缓冲游标的rowcount属性在调用execute方法后立即返回execute。这基本上意味着尚未从服务器获取整个结果集。此外,当您从非缓冲游标中提取行时,它的rowcount属性会增加,而缓冲游标的rowcount属性在从它获取行时保持不变。

下面的代码片段试图说明上面提出的要点:

代码语言:javascript
复制
import mysql.connector


conn = mysql.connector.connect(database='db',
                               user='username',
                               password='pass',
                               host='localhost',
                               port=3306)

buffered_cursor = conn.cursor(buffered=True)
unbuffered_cursor = conn.cursor(buffered=False)

create_query = """
drop table if exists people;
create table if not exists people (
    personid int(10) unsigned auto_increment,
    firstname varchar(255),
    lastname varchar(255),
    primary key (personid)
);
insert into people (firstname, lastname)
values ('Jon', 'Bon Jovi'),
('David', 'Bryan'),
('Tico', 'Torres'),
('Phil', 'Xenidis'),
('Hugh', 'McDonald')
"""

# Create and populate a table
results = buffered_cursor.execute(create_query, multi=True)
conn.commit()

buffered_cursor.execute("select * from people")
print("Row count from a buffer cursor:", buffered_cursor.rowcount)
unbuffered_cursor.execute("select * from people")
print("Row count from an unbuffered cursor:", unbuffered_cursor.rowcount)

print()
print("Fetching rows from a buffered cursor: ")

while True:
    try:
        row = next(buffered_cursor)
        print("Row:", row)
        print("Row count:", buffered_cursor.rowcount)
    except StopIteration:
        break

print()
print("Fetching rows from an unbuffered cursor: ")

while True:
    try:
        row = next(unbuffered_cursor)
        print("Row:", row)
        print("Row count:", unbuffered_cursor.rowcount)
    except StopIteration:
        break

上面的片段应该返回如下内容:

代码语言:javascript
复制
Row count from a buffered reader:  5
Row count from an unbuffered reader:  -1

Fetching rows from a buffered cursor:
Row: (1, 'Jon', 'Bon Jovi')
Row count: 5
Row: (2, 'David', 'Bryan')
Row count: 5
Row: (3, 'Tico', 'Torres')
Row count: 5
Row: (4, 'Phil', 'Xenidis')
Row count: 5
Row: (5, 'Hugh', 'McDonald')
Row: 5

Fetching rows from an unbuffered cursor:
Row: (1, 'Jon', 'Bon Jovi')
Row count: 1
Row: (2, 'David', 'Bryan')
Row count: 2
Row: (3, 'Tico', 'Torres')
Row count: 3
Row: (4, 'Phil', 'Xenidis')
Row count: 4
Row: (5, 'Hugh', 'McDonald')
Row count: 5

如您所见,未缓冲游标的rowcount属性从-1开始,并在循环其生成的结果时增加。缓冲游标的情况并非如此。

区分区别的第二种方法是注意两个(在相同连接下)execute的第一个。如果从执行未完全获取行的未缓冲游标开始,然后尝试使用缓冲游标执行查询,则会引发InternalError异常,并将要求您使用或丢弃未缓冲游标返回的内容。下面是一个例子:

代码语言:javascript
复制
import mysql.connector


conn = mysql.connector.connect(database='db',
                               user='username',
                               password='pass',
                               host='localhost',
                               port=3306)

buffered_cursor = conn.cursor(buffered=True)
unbuffered_cursor = conn.cursor(buffered=False)

create_query = """
drop table if exists people;
create table if not exists people (
    personid int(10) unsigned auto_increment,
    firstname varchar(255),
    lastname varchar(255),
    primary key (personid)
);
insert into people (firstname, lastname)
values ('Jon', 'Bon Jovi'),
('David', 'Bryan'),
('Tico', 'Torres'),
('Phil', 'Xenidis'),
('Hugh', 'McDonald')
"""

# Create and populate a table
results = buffered_cursor.execute(create_query, multi=True)
conn.commit()

unbuffered_cursor.execute("select * from people")
unbuffered_cursor.fetchone()
buffered_cursor.execute("select * from people")

上面的代码段将引发一个InternalError异常,其中包含一条消息,指示有一些未读结果。它的基本意思是,在可以在同一连接下使用任何游标执行另一个查询之前,需要完全使用未缓冲游标返回的结果。如果用unbuffered_cursor.fetchone()更改unbuffered_cursor.fetchall(),错误将消失。

还有其他不太明显的差别,比如内存消耗。缓冲游标可能会消耗更多内存,因为它们可以从服务器获取结果集并缓冲行。

我希望这证明是有用的。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46682012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档