2013-03-30 15 views
9

È possibile accedere al database in un unico processo, creato in un altro? ho provato:Due processi possono accedere contemporaneamente in memoria (: memoria :) al database sqlite?

IDLE # 1

import sqlite3 
conn = sqlite3.connect(':memory:') 
c = conn.cursor() 
c.execute("create table test(testcolumn)") 
c.execute("insert into test values('helloooo')") 
conn.commit() 
conn.close() 

IDLE # 2

import sqlite3 
conn = sqlite3.connect(':memory:') 
c = conn.cursor() 
c.execute("select * from test") 

Errore:

Traceback (most recent call last): 
    File "<pyshell#5>", line 1, in <module> 
    q = c.execute("select * from test") 
sqlite3.OperationalError: no such table: test 
+0

Ogni processo che si connette a ': Memoria:' crea un proprio, unico nel suo genere, banca dati privata, invisibile a tutti gli altri processi. – zwol

risposta

13

No, non possono mai accedere allo stesso database in memoria. Invece, una nuova connessione a :memory:sempre crea un nuovo database.

Dal SQLite documentation:

Every :memory: database is distinct from every other. So, opening two database connections each with the filename ":memory:" will create two independent in-memory databases.

Questo è diverso da un database su disco, in cui la creazione di connessioni multiple con lo stesso stringa di connessione significa che la connessione a un database.

Entro un processo è possibile condividere un database in memoria se si utilizza il file::memory:?cache=shared URI:

conn = sqlite3.connect('file::memory:?cache=shared') 

, ma questo non è ancora accessibile da altri un altro processo.

+0

Grazie per averlo chiarito! – DDC

+0

anche "file :: memoria:? Cache = shared" consente solo connessioni di database separate per condividere lo stesso database in memoria. Ma tutte le connessioni di database che condividono il database in memoria devono essere nello stesso processo. https://www.sqlite.org/inmemorydb.html – corretge

+2

@corretge: il 'file :: memoria :?cache = shared' url è stato introdotto solo pochi mesi prima che scrivessi questo, vedo. Ho aggiunto una menzione, ma come dici tu questo non è utilizzabile in più processi. –

9

ovviamente sono d'accordo con @Martijn perché doc dice così, ma se si sono concentrati sui sistemi Unix-like, allora si può fare uso di memoria condivisa:

Se si crea il file nella cartella /dev/shm, tutti i file creano ci sono mappati direttamente alla RAM, quindi puoi usare per accedere allo stesso database da due processi diversi.

#/bin/bash 
rm -f /dev/shm/test.db 
time bash -c $' 
FILE=/dev/shm/test.db 
sqlite3 $FILE "create table if not exists tab(id int);" 
sqlite3 $FILE "insert into tab values (1),(2)" 
for i in 1 2 3 4; do sqlite3 $FILE "INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5"; done; #inserts at most 2'000'000 records to db. 
sqlite3 $FILE "select count(*) from tab;"' 

ci vuole così tanto tempo:

FILE=/dev/shm/test.db 
real 0m0.927s 
user 0m0.834s 
sys 0m0.092s 

per almeno 2 milioni di dischi, facendo lo stesso su HDD prende (questo è lo stesso comando, ma FILE=/tmp/test.db):

FILE=/tmp/test.db 
real 0m2.309s 
user 0m0.871s 
sys 0m0.138s 

quindi in pratica questo ti consente di accedere agli stessi database da processi diversi (senza perdere velocità R/W):

Ecco demo che dimostra questo ciò di cui sto parlando:

xterm -hold -e 'sqlite3 /dev/shm/testbin "create table tab(id int); insert into tab values (42),(1337);"' & 
xterm -hold -e 'sqlite3 /dev/shm/testbin "insert into tab values (43),(1338); select * from tab;"' & 
; 
+1

Non usare '/ dev/shm' stesso, crea un'altra istanza di' tmpfs', vedi ad esempio https://stackoverflow.com/a/42884337/846250 –

Problemi correlati