我能想到这两种Cursors 不同的两种方式。
第一种方法是,如果使用缓冲游标执行查询,则可以通过检查MySQLCursorBuffered.rowcount 来获取返回的行数。但是,无缓冲游标的rowcount 属性在调用execute 方法后立即返回-1。这基本上意味着尚未从服务器获取整个结果集。此外,无缓冲游标的rowcount 属性随着您从中获取行而增加,而缓冲游标的rowcount 属性在您从中获取行时保持不变。
下面的 sn-p 代码试图说明以上几点:
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
上面的 sn-p 应该返回如下内容:
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 开始,并随着我们循环遍历它生成的结果而增加。缓冲游标不是这种情况。
第二种区分的方法是首先注意两者中的哪一个(在同一连接下)executes。如果您从执行未完全获取行的非缓冲游标开始,然后尝试使用缓冲游标执行查询,则会引发 InternalError 异常,并且您将被要求使用或丢弃由无缓冲游标。下图为:
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")
上面的 sn-p 将引发 InternalError 异常,并显示一条消息,指示有一些未读结果。它的基本意思是,在您可以使用同一连接下的任何游标执行另一个查询之前,需要完全消耗无缓冲游标返回的结果。如果你把unbuffered_cursor.fetchone()改成unbuffered_cursor.fetchall(),错误就会消失。
还有其他不太明显的差异,例如内存消耗。缓冲游标可能会消耗更多内存,因为它们可能从服务器获取结果集并缓冲行。
我希望这证明有用。