von unserer iSeries bin ich es gewohnt, auf einer Connection beliebig viele
Statements ausführen zu können.
Dieses wollte ich jetzt für einen SQL Server 2008 adaptieren. Ich greife auf
diesen mittels eines SQLDriverConnect mit DRIVER={SQL Server} zu. Hole mir
dann 2 Statement-Handles und prepare diese. Den ersten Statement führe ich
nach den BindCol und BindParameter aus und fetche den ersten Datensatz. Jetzt
soll das zweite Statement executet werden, woraufhin ich die Fehlermeldung:
"HY000 - Die Verbindung ist mit Ergebnissen von einem anderen hstmt belegt"
bekomme.
In dem Sinne hat der Fehler ja Recht. Die Frage ist: Kann der Treiber zum
SQL Server keine mehreren ResultSets verarbeiten? Kann dieses wie beim .Net
Treiber mittels "MultipleActiveResultSets=TRUE" aktiviert werden? Oder bin
ich gezwungen mehrere Connections aufzubauen?
Gruß Björn
Hier mein Programmcode:
if (SQLAllocHandle (SQL_HANDLE_STMT, gl_SqlServerDbc, &hstmt1) == SQL_SUCCESS)
{
if (SQLAllocHandle (SQL_HANDLE_STMT, gl_SqlServerDbc, &hstmt2) ==
SQL_SUCCESS)
{
sqlreturn = SQLPrepare (hstmt1, (SQLCHAR *) szSQLString1, SQL_NTS);
if (sqlreturn == SQL_SUCCESS || sqlreturn == SQL_SUCCESS_WITH_INFO)
{
sqlreturn = SQLPrepare (hstmt2, (SQLCHAR *) szSQLString2, SQL_NTS);
if (sqlreturn == SQL_SUCCESS || sqlreturn == SQL_SUCCESS_WITH_INFO)
{
... Binds ...
sqlreturnQSData = SQLExecute (hstmt1);
if (sqlreturnQSData == SQL_SUCCESS || sqlreturnQSData ==
SQL_SUCCESS_WITH_INFO)
{
do
{
sqlreturnQSData = SQLFetch (hstmt1);
if (sqlreturnQSData == SQL_SUCCESS || sqlreturnQSData ==
SQL_SUCCESS_WITH_INFO)
{
sqlreturn = SQLExecute (hstmt2); // <- FEHLER
Hallo Björn,
Björn Dehmel schrieb:
> von unserer iSeries bin ich es gewohnt, auf einer Connection beliebig viele
> Statements ausführen zu können.
Beim SQL Server ging das traditionell bis SQL Server 2005 nicht,
auch weil es im Regelfall ineffiziente Programme bedeutet.
> In dem Sinne hat der Fehler ja Recht. Die Frage ist: Kann der Treiber zum
> SQL Server keine mehreren ResultSets verarbeiten?
Der ursprüngliche SQL Server Treiber (DRIVER=SQLSRV32) kann dies
nicht, da er für SQL Server 2000 und früher gedacht ist, wo das
nicht ging.
> Kann dieses wie beim .Net
> Treiber mittels "MultipleActiveResultSets=TRUE" aktiviert werden?
Aktivieren kannst Du das beim SQL Server Native Client:
<URL:http://msdn.microsoft.com/de-de/library/ms131686.aspx>
"Verwenden von Multiple Active Result Sets (MARS)."
> Hier mein Programmcode:
Günstiger ist es allerdings auf das Feature zu verzichten.
Effiziente Programme rufen die Daten von einem Cursor so schnell
wie möglich ab, um die Zeit die Daten gesperrt werden zu minimieren.
Zum einen degeneriert MARS bei mehr vielen (10) aktiven Statements
Und in Verbindung mit Transaktionen gibt es schnell Probleme,
wie Blockierungen und Deadlocks. Dem man dann zwar wiederum
mit Snapshot Isolierungen entgegenwirken kann. Aber am Ende
wird alles nur komplizierter, nicht einfacher.
Auch wenn es mit puren C etwas mühsamer ist als in .NET
Daten in Listen zu verwalten. Willst Du effizienter programmieren
verwende gleich .NET (da gibts alles das) oder C++ mit Templates.
BTW: SQLPrepare bringt bei SQL Server 2008 nichts, und kann
sich sogar negativ auf die Leistung auswirken:
<URL:http://msdn.microsoft.com/de-de/library/ms131667.aspx>
Gruß Elmar
Es wirft aber gleich ein paar Fragen mehr auf:
> Beim SQL Server ging das traditionell bis SQL Server 2005 nicht,
(mehrere Statements auf einer Connection)
> auch weil es im Regelfall ineffiziente Programme bedeutet.
Wie ist das denn mit Positioned Updates, sollte man da auch 2 Connections
benutzen?
> Aktivieren kannst Du das beim SQL Server Native Client:
Durch was wird dieser Treiber denn installiert? Ich habe mich für den
Standardtreiber entscheiden, da dieser mit jeder Windows-Installation mit
MDAC aufgespielt wird. Den Native Client habe ich auf meinem Rechner auch
drauf, aber ich musste auch das SQL Server Management Studio installieren.
Gibt es eine Möglichkeit den Native Client über WSUS nachträglich zu
verteilen? Da wir hierbei noch in Kinderschuhen stecken, haben wir noch die
volle Entscheidungsfreiheit, welchen Treiber wir nutzen wollen. Bedingung ist
nur, dass der Treiber auch vorhanden ist.
> Effiziente Programme rufen die Daten von einem Cursor so schnell
> wie möglich ab, um die Zeit die Daten gesperrt werden zu minimieren.
Auf unserer iSeries arbeiten wir ohne Transaktionen und lesen mit sofortigem
Commit. Wir benutzen auch keinerlei Isolation Levels, es sei denn SQL macht
das von alleine, zB durch FOR UPDATE.
Auf dem SQL Server wollte ich nichts anderes. Sperrt der SQL Server denn den
Satz, wenn der Cursor eines Selects da drauf steht? Kann man durch ein Tool
sehen, welche Tabellen, Zeilen wie durch wen gesperrt sind?
> Auch wenn es mit puren C etwas mühsamer ist als in .NET
> Daten in Listen zu verwalten. Willst Du effizienter programmieren
> verwende gleich .NET (da gibts alles das) oder C++ mit Templates.
Wäre schön, aber ich habe nicht die Zeit, das aus DOS Zeiten entstandene
Programm komplett neu zu schreiben...
Gruß Björn
Björn Dehmel schrieb:
> Es wirft aber gleich ein paar Fragen mehr auf:
>
>> Beim SQL Server ging das traditionell bis SQL Server 2005 nicht,
>> (mehrere Statements auf einer Connection)
>> auch weil es im Regelfall ineffiziente Programme bedeutet.
>
> Wie ist das denn mit Positioned Updates, sollte man da auch 2 Connections
> benutzen?
Idealerweise arbeitet man nur mit einer Verbindung.
Denn zwei Verbindung sind vom Transaktionskontext her getrennt,
und werden quasi behandelt wie zwei Programme, die parallel
auf die Daten zugreifen.
>> Aktivieren kannst Du das beim SQL Server Native Client:
> Durch was wird dieser Treiber denn installiert?
Das Feature Pack hast Du ja anscheinend bereits gefunden,
die Link auf die aktuellste Version (April 2009):
http://www.microsoft.com/downloads/details.aspx?FamilyID=b33d2c78-1059-4ce2-b80d-2343c099bcb4&displaylang=de
Feature Pack für Microsoft SQL Server 2008, April 2009
>> Effiziente Programme rufen die Daten von einem Cursor so schnell
>> wie möglich ab, um die Zeit die Daten gesperrt werden zu minimieren.
> Auf unserer iSeries arbeiten wir ohne Transaktionen und lesen mit sofortigem
> Commit. Wir benutzen auch keinerlei Isolation Levels, es sei denn SQL macht
> das von alleine, zB durch FOR UPDATE.
Vorsicht! Den SQL Server an der Stelle mit einer iSeries Datenbank
oder irgendeiner anderen zu vergleichen und das gleiche
Programmiermodell zu verwenden ist sehr, sehr riskant.
Der Sql Server arbeitet nicht mit impliziten Transaktionenm sondern
in der Voreinstellung im Autocommit Modus und Transaktionen werden
ansonsten explizit angestoßen:
http://msdn.microsoft.com/de-de/library/ms190612.aspx
"Transaktionen"
Zudem hat der SQL Server ein ausgefeiltes Cursor Modell -
Siehe DECLARE CURSOR und auch die Programmierreferenz für ODBC.
http://msdn.microsoft.com/de-de/library/ms191179.aspx
"Cursor (Datenbankmodul)"
> Sperrt der SQL Server denn den Satz, wenn der Cursor eines Selects
> da drauf steht?
Das hängt vom Cursortyp und der Isolationsstufe ab.
Grundsätzlich wird jede Datenzeile für den Zugriff gesperrt.
Wobei die Sperren sehr granular sind, beim reinen Lesen wird
zunächst nur eine Lesesperre gesetzt und diese ggf. hochgestuft.
http://msdn.microsoft.com/de-de/library/ms187101.aspx
"Sperren und Zeilenversionsverwaltung"
> Kann man durch ein Tool sehen, welche Tabellen, Zeilen
> wie durch wen gesperrt sind?
Die Informationen kannst Du über das SSMS abrufen.
die Anzeige erfolgt über Prozeduren wie "sp_lock"
oder Sichten wie "sys.dm_tran_locks".
>> Auch wenn es mit puren C etwas mühsamer ist als in .NET
>> Daten in Listen zu verwalten. Willst Du effizienter programmieren
>> verwende gleich .NET (da gibts alles das) oder C++ mit Templates.
> Wäre schön, aber ich habe nicht die Zeit, das aus DOS Zeiten entstandene
> Programm komplett neu zu schreiben...
Mit der Zeit haben wir wohl alle ein Problem.
Auf Sicht mag sich das aber doch lohnen.
Denn mit der Anzahl Zeilen, in dem Du in Deinem Beispielschnippsel
gerade mal die Cursor eröffnet hast, hat man z. B. in .NET schon die
Daten verändert und ist (fast) fertig.
Auch wenn im Hintergrund sehr viel mehr Code steht,
aber den muß man selbst nicht mehr schreiben ;-).
Nur ein Beispiel - der C# Codeteil sollte für Dich als
C Programmierer interpretierbar sein:
http://msdn.microsoft.com/de-de/library/33y2221y.aspx
Gruß Elmar
Hallo Bjᅵrn,
Bjᅵrn Dehmel schrieb:
> Es wirft aber gleich ein paar Fragen mehr auf:
>
>> Beim SQL Server ging das traditionell bis SQL Server 2005 nicht,
>> (mehrere Statements auf einer Connection)
>> auch weil es im Regelfall ineffiziente Programme bedeutet.
>
> Wie ist das denn mit Positioned Updates, sollte man da auch 2 Connections benutzen?
Idealerweise arbeitet man nur mit einer Verbindung.
Denn zwei Verbindung sind vom Transaktionskontext her getrennt,
und werden quasi behandelt wie zwei Programme, die parallel
auf die Daten zugreifen.
>> Aktivieren kannst Du das beim SQL Server Native Client:
> Durch was wird dieser Treiber denn installiert?
Das Feature Pack hast Du ja anscheinend bereits gefunden,
die Link auf die aktuellste Version (April 2009):
http://www.microsoft.com/downloads/details.aspx?FamilyID=b33d2c78-1059-4ce2-b80d-2343c099bcb4&displaylang=de
Feature Pack fᅵr Microsoft SQL Server 2008, April 2009
>> Effiziente Programme rufen die Daten von einem Cursor so schnell
>> wie mᅵglich ab, um die Zeit die Daten gesperrt werden zu minimieren.
> Auf unserer iSeries arbeiten wir ohne Transaktionen und lesen mit sofortigem Commit. Wir benutzen auch keinerlei Isolation
Levels, es sei denn SQL macht das von alleine, zB durch FOR UPDATE.
Vorsicht! Den SQL Server an der Stelle mit einer iSeries Datenbank
oder irgendeiner anderen zu vergleichen und das gleiche
Programmiermodell zu verwenden ist sehr, sehr riskant.
Der Sql Server arbeitet nicht mit impliziten Transaktionenm sondern
in der Voreinstellung im Autocommit Modus und Transaktionen werden
ansonsten explizit angestoᅵen:
http://msdn.microsoft.com/de-de/library/ms190612.aspx
"Transaktionen"
Zudem hat der SQL Server ein ausgefeiltes Cursor Modell -
Siehe DECLARE CURSOR und auch die Programmierreferenz fᅵr ODBC.
http://msdn.microsoft.com/de-de/library/ms191179.aspx
"Cursor (Datenbankmodul)"
> Sperrt der SQL Server denn den Satz, wenn der Cursor eines Selects
> da drauf steht?
Das hᅵngt vom Cursortyp und der Isolationsstufe ab.
Grundsᅵtzlich wird jede Datenzeile fᅵr den Zugriff gesperrt.
Wobei die Sperren sehr granular sind, beim reinen Lesen wird
zunᅵchst nur eine Lesesperre gesetzt und diese ggf. hochgestuft.
http://msdn.microsoft.com/de-de/library/ms187101.aspx
"Sperren und Zeilenversionsverwaltung"
> Kann man durch ein Tool sehen, welche Tabellen, Zeilen
> wie durch wen gesperrt sind?
Die Informationen kannst Du ᅵber das SSMS abrufen.
die Anzeige erfolgt ᅵber Prozeduren wie "sp_lock"
oder Sichten wie "sys.dm_tran_locks".
>> Auch wenn es mit puren C etwas mᅵhsamer ist als in .NET
>> Daten in Listen zu verwalten. Willst Du effizienter programmieren
>> verwende gleich .NET (da gibts alles das) oder C++ mit Templates.
> Wᅵre schᅵn, aber ich habe nicht die Zeit, das aus DOS Zeiten entstandene Programm komplett neu zu schreiben...
Mit der Zeit haben wir wohl alle ein Problem.
Auf Sicht mag sich das aber doch lohnen.
Denn mit der Anzahl Zeilen, in dem Du in Deinem Beispielschnippsel
gerade mal die Cursor erᅵffnet hast, hat man z. B. in .NET schon die
Daten verᅵndert und ist (fast) fertig.
Auch wenn im Hintergrund sehr viel mehr Code steht,
aber den muᅵ man selbst nicht mehr schreiben ;-) .
Nur ein Beispiel - der C# Codeteil sollte fᅵr Dich als
C Programmierer interpretierbar sein:
http://msdn.microsoft.com/de-de/library/33y2221y.aspx
Gruᅵ Elmar