Mer hjälp med SQL

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Nerre
Inlägg: 27188
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Mer hjälp med SQL

Inlägg av Nerre »

Det du beskriver (repeatble read) är ju precis det jag menar, sen att jag inte är så insatt i rätt terminologi är en annan femma.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

> Det du beskriver (repeatble read) är ju precis det jag menar,

Ja, jo. Men det är *servern* som avgör det, inte klienten.

Om man gör en "start transaction isolation level read commited"
innan loopen med SELECT så finns det ingen garanti att man får
samma resultat tillbaka varje gång. Man "ser" nya data som är
commitade sedan förra selecten.

Klinten kan inte, bara för att selecten ser likadan ut, anta att det
kommer att bli samma svar.

Hur som helst, det är kanske något helt annat här som spökar.

> Du behöver tala om för klienten att den måste göra ett nytt anrop till
> servern och uppdatera select-resultatet.

Det normala är att man commitar och startar en ny transaktion. Då ser man
datat så som det ser ut "nu".

> Exakt hur man gör detta vet jag inte om det är definierat i SQL som sådant...

Transaktionshanteringen är fullt ut standardiserat i SQL.
Start transaction, commit och rollback. Plus lite tillägg.

Sen så kan ju olika verktyg bygga in det hela för att förenkla för användaren
(t.ex. en programmerare), men det underlättar kanske inte förståelsen av hur
databasen i sig fungerar. :-) Microsofts "recordset" motsvarar väl i princip
det som normalt kallas "cursors".
RoPa
Inlägg: 630
Blev medlem: 13 januari 2006, 10:32:06

Re: Mer hjälp med SQL

Inlägg av RoPa »

@nerre, " en refresh eller nåt liknande." är precis vad jag är ute efter.
Jag förstår att jag jobbar mot en snappshot när jag gör fetch mot en select men att göra en ny select trodde jag gjorde en ny slagning mot databasen.

Insert processen gör connect, insert, commit, insert, comit insert commit...

Så när jag läser med en enkel process som gör connect, select, fetch, close och jag kör den igen så får jag ut senaste data så skriv processens commit verkar räcka för att databasen ska ha blivit uppdaterad och läsbar.

Frågan är vad man måste göra för att i samma connect kunna göra fler select och få med ändringar som har skett i mellantiden. Där av frågan om någon form av " en refresh eller nåt liknande.", för inte gör man väl commit på en select??? eller ???
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

> ...för inte gör man väl commit på en select??? eller ???

Självklart gör man det! Databasen struntar i om man skriver eller läser.
(Bortsätt då från annat som låshantering och så vidare...)
Varför skulle man inte göra det !? Det är ju väldigt intressant för
databasen att få veta att man har "läst klart", så att säga... :-)

Transaktion som transaktion. Och det är databasens upgift att leverera
samma "bild" av databasen (oavsett uppdateringar) så länge som man
inte commitar (eller kör isolation level "read commited"...).

Tänkt dig t.ex att du vill summera ett visst data på 4 olika sätt med
olika delsummor. Då vill man ju inte att dessa 4 olika SELECT ska
ge olika resultat (d.v.s olika totalsumma på "the bottom line"), utan
de ska summera utifrån exakt samma underlag, även om det sker
uppdateringar under tiden. Det är det som "repeatable read" betyder.

Om man vill se databasen utifrån en annan tidpunkt så gör man
commit och startar om en *ny* transaktion.

> Insert processen gör connect, insert, commit, insert, comit insert commit...

Då startar du alltså en default transaktion utifrån vad som är konfigureret i databsen.
För mer egen kontroll så brukar man göra:
connect, start transaction, insert, commit, start transaction, insert, commit, o.s.v...

Det är även bra om man gör "start transaction read only" ifall man vet att man
enbart kommer att läsa. Det hjälper MySQL att göra lite extra optimeringar, alltså:
connect, start transaction read only, select, commit, start transaction read only, select, commit, o.s.v...

Notera att "read write" är default ifall man inte har ändrat det i konfigurationen...
http://dev.mysql.com/doc/refman/5.6/en/commit.html
http://dev.mysql.com/doc/refman/5.6/en/ ... o-txn.html
Användarvisningsbild
pbgp
Inlägg: 1450
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala

Re: Mer hjälp med SQL

Inlägg av pbgp »

sodjan är på helt rätt spår. Du behöver stänga din transaktion.

Sen är jag skeptisk till att återanvända cursor-objektet, det är nog inte rekommenderat i alla API:er. Men jag vet ju inte vilket API som körs här.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

Ja, vi använder alltid start trans och commit (eller rollback) för allt som görs mot databasen.
Det sista man villa ha är en programmiss som t.ex glömmer att commita och som får
en hel fabrik att tvärnita... :-)
RoPa
Inlägg: 630
Blev medlem: 13 januari 2006, 10:32:06

Re: Mer hjälp med SQL

Inlägg av RoPa »

@sodjan, @pgpb, Då provar jag med att gör en commit mellan select.
Om jag inte kan använda samma cursor objectet måste jag stänga förbindelsen (cursor objectet är ett resultat av connecten) och det känns lite väl omständligt bara för att kunna läsa igen, det behövs ju inte för att kunna skriva igen.
Eftersom jag bara gör en sak (insert eller select) så har jag inte brytt mig om transaction, men det kanske får komma om jag behöver optimera prestanda och göra det lättare för databasen att optimera.
Ska se vad read commited betyder då det låter lite som vad jag vill ha.

Tack för tipsen, nu har jag lite att prova.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

https://dev.mysql.com/doc/refman/5.0/en ... ction.html
https://dev.mysql.com/doc/refman/5.0/en ... -read.html

Texten är inte jättetydlig, men på andra länken står det bl.a:

"If the transaction isolation level is REPEATABLE READ (the default level), all consistent
reads within the same transaction read the snapshot established by the first such read
in that transaction. You can get a fresher snapshot for your queries by committing the
current transaction and after that issuing new queries."

"With READ COMMITTED isolation level, each consistent read within a transaction sets
and reads its own fresh snapshot..."
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

En anna sak... :-)

Antag att du har en process som skriver nya poster då och då.
Dina "läsare" hämtar alltid den senaste posten, eller hur?

Vad händer om läs processen har stannat medans den som skiver
fortsätter att skriva nya poster? Kommer du då inte enbart att se den
senaste och kanske missa ett antal poster? Eller spelar det ingen roll?
RoPa
Inlägg: 630
Blev medlem: 13 januari 2006, 10:32:06

Re: Mer hjälp med SQL

Inlägg av RoPa »

@Sodjan, tack för hjälpen med att read committed inte är en väg framåt. Jag går på select med commit.
Det spelar ingen roll om läsarna missar några poster för det är bara den senaste som är intressant för dem att visa.
Att alla hamnar i databasen är för att jag vill kunna ta ut listningar på olika typer av indikatorer men det behöver inte göras med realtidsdata utan mer som en rapport.

Lite dimensionerande fakta: loop tiden för läsning kommer troligen att läggas på 100-200ms och antalet läsare kommer sällan vara fler än två samtidigt, så det borde inte bli så ansträngande för databasen om select satsen kan skrivas bra. Sensorernas uppdateringshastighet ligger på ca max 50 ms så antalet skrivningar blir aldrig mer än 20 per sekund.
Nerre
Inlägg: 27188
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Mer hjälp med SQL

Inlägg av Nerre »

I princip kan man likna funktionen vid displayer som ska visa ett värde "i realtid", d.v.s. de ska visa det senaste från databasen och skulle de råka missa några så gör det inte direkt nåt?
RoPa
Inlägg: 630
Blev medlem: 13 januari 2006, 10:32:06

Re: Mer hjälp med SQL

Inlägg av RoPa »

@Nerre, precis!

Det fungerade med att göra commit och att återanvända cursor objektet.
Kompletterade select satsen med WHERE ind_id = (SELECT MAX(ind_id) FROM indicators).

Så nu fungerar det.

Kod: Markera allt

try:
   while True:
      # read data from database        
      try:
         cursor.execute("SELECT * FROM indicators WHERE ind_id = (SELECT MAX(ind_id) FROM indicators)")
         row = cursor.fetchone()
         if (row["ind_stored"] != old):
            print "New data: ", row["ind_status"], row["ind_stored"], row["ind_id"]
            old = row["ind_stored"]
         db.commit()
            
      except:
         print "Could not read data"
         break
finally:
   # disconnect from server
   db.close()
Belastningsläget, kanske ska lägga in en sleep :roll:

Kod: Markera allt

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2730 mysql     20   0  309m  37m 9132 S  58,4  8,6  64:25.91 mysqld
11732 pi        20   0 24224 9064 5700 S  37,3  2,0   5:31.17 PyDbReadLastDat
11748 pi        20   0  6376 2564 2136 S   2,2  0,6   0:01.21 top
EDIT: Nu med 100mS sleep

Kod: Markera allt

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2730 mysql     20   0  310m  37m 9132 S   2,9  8,6  91:50.54 mysqld
11817 pi        20   0 24232 8884 5540 S   1,6  2,0   0:01.17 PyDbReadLastDat
11819 pi        20   0  6388 2452 2052 R   1,3  0,6   0:00.22 top
Stort tack för all hjälp
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Mer hjälp med SQL

Inlägg av sodjan »

Bara ett par småsaker... :-)

Generellt så bör man undvia "select star" i programkod. Det är ju
en praktiskt "shorthand" när man gör saker för hand, men i kod
är det inte snyggt. Ange vilka fält du behöver istället. Det kan
undvika extrajobb om man lägger till fält i tabellen.

Nu så är ju Python väldikt dynamiskt till sin natur, så den lär anpassa
sig efter tabellen, men om man har andra spåk med "embedded SQL",
där strukturer för returdatat kompileras in i koden, så kan det bli problem.

Som jag skrev tidigare, och som även MySQL sidorna säger, så får man en del
extra optimeringar i MySQL om man specifikt startar en read-only transaktion.
Default (eftersom du saknar "start transaction...") är väl read-write (?).

Har du ett index på ind_id?
thebolt
Inlägg: 248
Blev medlem: 10 februari 2008, 17:41:40
Ort: Taipei Taiwan

Re: Mer hjälp med SQL

Inlägg av thebolt »

Dessutom bör det vara något mer effektivt att köra

Kod: Markera allt

SELECT ind_id, ind_stored, ind_status FROM indicators ORDER BY ind_id DESC LIMIT 1
En ritkigt bra query-optimizer kanske kan förstå att den nästade frågan är ekvivalent, men tveksamt. Vill du verkligen veta så har ju mysql en inbyggd query profiler som kan säga vilket som är bäst.
danielr112
Inlägg: 8092
Blev medlem: 18 januari 2009, 00:48:24
Ort: Alvesta, Småland

Re: Mer hjälp med SQL

Inlägg av danielr112 »

Ja snabbaste i mysql är "order by limit n" istället för att köra en subselect. Den jag gav innan var bara för att få ut senaste idt.

Kod: Markera allt

mysql> explain select * from temps order by dt desc limit 1;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | temps | index | NULL          | dt   | 4       | NULL |    1 |       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------+
vs

Kod: Markera allt

mysql> explain select * from temps where dt = (select max(dt) from temps);
+----+-------------+-------+------+---------------+------+---------+-------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+-------+------+------------------------------+
|  1 | PRIMARY     | temps | ref  | dt            | dt   | 4       | const |    6 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL  | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+-------+------+------------------------------+
2 rows in set (0.00 sec)

Edit: Är just nu 5miljoner rader i den tabellen.
Skriv svar