[freetds] One row good, two rows "memory exhausted"

James K. Lowden jklowden at freetds.org
Sun Sep 14 00:51:11 EDT 2008


Mark Bird wrote:
> Then, apparently as it tries to read the second record, [i]t appears to
> get into some kind of endless loop until it finally runs out of memory.

Yup.  From what I see though, it appears the application is using db-lib
incorrectly.  

First question: how did buffering get turned on to start with?  It's not a
commonly used db-lib option, and I didn't know PHP used it.  

Here's what the log says:  

> buffering.h:231:buffer_transfer_bound_data(0x5555644c41b0 4040 -1
> 0x5555644c41a0 1)

	a successful fetched

> dblib.c:2030:leaving dbnextrow() returning REG_ROW/MORE_ROWS
> dblib.c:6884:dblastrow(0x5555644c41a0)
> dblib.c:2698:dbclrbuf(0x5555644c41a0, 0)
                                        ^ probably wrong
	"If n is less than 1, the function call is ignored."
http://manuals.sybase.com:80/onlinebooks/group-cnarc/cng1110e/dblib/@Generic__BookTextView/9916;pt=24261#X

DBLASTROW() and dbclrbuf() are db-lib buffering functions.  Somewhere
earlier in the log you should see a call to dbsetopt() in which the second
argument is 14 (DBBUFFER) and the last argument is the number of rows to
buffer.  My guess is that last argument is 1.  

When dbnextrow() returns BUF_FULL, the application attempts to clear the
buffer, but does so incorrectly, causing the call to be ignored and the
row buffer to remain full.  And so it goes.  

The last time Frediano linked our db-lib buffering unit test to Sybase's
library -- and the code hasn't changed since -- our unit test worked fine
with our library, but not with Sybase's.  That is, our buffering
implementation differs somehow from theirs.  I haven't looked into it
further because it's not clear anyone cares.  

--jkl



More information about the FreeTDS mailing list