SSCursor in MySQL

2016-01-19 14-55-49 by Kamushin

There are four kinds of cursors available in MySQL client side programming. In this article, I am going to introduce the difference between Cursor the normal one and SSCursor the server side one and how to use SSCursor.
First, let's see the definitions of those four cursors in MySQLdb source code.

class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn,
             BaseCursor):

    """This is the standard Cursor class that returns rows as tuples
    and stores the result set in the client."""


class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn,
                 BaseCursor):

     """This is a Cursor class that returns rows as dictionaries and
    stores the result set in the client."""


class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn,
               BaseCursor):

    """This is a Cursor class that returns rows as tuples and stores
    the result set in the server."""


class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn,
                   BaseCursor):

    """This is a Cursor class that returns rows as dictionaries and
    stores the result set in the server."""

In fact, there are two orthogonal features of cursors in MySQLdb. CursorDictRowsMixIn/CursorTupleRowsMixIn controls result type and CursorStoreResultMixIn/CursorUseResultMixIn which we will focus on in this article controls the result will be store in server or client.
With the definitions, we know that SSCursor stores result in the server rather than in the client.

server side VS client side

Two simple flows show how they works.

  • client side
  # mysql_store_result
  while(True):
    result = produce_part_result() # find part of results that can be filled into a network package
    fill_network_package(result)
    send_network_package
  • server side
  # mysql_use_result
  while(True):
    result = produce_part_result() # find part of results that can be filled into a network package

    wait_until_the_client_invoke_`mysql_fetch_row()`

    fill_network_package(result)
    send_network_package

In fact, the MySQL server will not store results in server even if a SSCursor is used, it will produce the part of results before fill them into the network packages. So don't worry the memory use of the server when use SSCursor.

how to use SSCursor

  cur = conn.cursor(MySQLdb.cursors.SSCursor)

Here is a trap that commit should be invoked after all of the results have been sent to client. Otherwise, 2014, "Commands out of sync; you can't run this command now" error will be raised.

If you get Commands out of sync; you can't run this command now in your client code, you are calling client functions in the wrong order. This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without calling mysql_use_result() or mysql_store_result() in between.

commit is also a query, or we can say request, so the program should read all of the results then invoke commit.

advantages and disadvantages of using SSCursor

  • Less memory use in the client.
  • Get the first row more quickly.
  • The whole results sending will be slower.

Comments