Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!ecngs!feeder2.ecngs.de!newsfeed.freenet.ag!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; '(at': 0.04; 'pop': 0.05; 'explicit': 0.07; 'nasty': 0.07; 'postgresql': 0.07; 'remaining': 0.07; 'subject: + ': 0.07; 'table.': 0.07; 'tries': 0.07; 'committing': 0.09; 'ide': 0.09; 'indicates': 0.09; 'level:': 0.09; 'read-only': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'rejected': 0.09; 'restart': 0.09; 'restored': 0.09; 'rows': 0.09; 'subject:into': 0.09; 'tcp/ip': 0.09; 'runs': 0.10; 'python': 0.11; 'changes': 0.15; '"file': 0.16; '"pending"': 0.16; '(there': 0.16; 'adapter': 0.16; 'blocked': 0.16; 'concurrent': 0.16; 'determines': 0.16; 'filesystem': 0.16; 'finds': 0.16; 'in-memory': 0.16; 'increment': 0.16; 'journal,': 0.16; 'lie': 0.16; 'mode,': 0.16; 'nfs.': 0.16; 'phase,': 0.16; 'postgresql)': 0.16; 'query,': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'sqlite': 0.16; 'subject:which': 0.16; 'sync': 0.16; 'underlying': 0.16; 'subject:python': 0.16; 'subject: ?': 0.16; 'trying': 0.19; 'basically': 0.19; 'commit': 0.19; 'normally': 0.19; 'work,': 0.20; 'written': 0.21; 'seems': 0.21; '(the': 0.22; 'command': 0.22; 'example': 0.22; 'pages,': 0.22; 'error': 0.23; 'logical': 0.24; 'tells': 0.24; 'url:home': 0.24; '(or': 0.24; 'query': 0.26; 'second': 0.26; 'least': 0.26; 'gets': 0.27; 'header:X-Complaints- To:1': 0.27; 'chris': 0.29; '(like': 0.30; 'skip:( 20': 0.30; 'code': 0.31; 'submitting': 0.31; 'apparently': 0.31; 'assumes': 0.31; 'crash': 0.31; 'initialized': 0.31; 'os,': 0.31; 'allows': 0.31; 'file': 0.32; 'run': 0.32; 'worked': 0.33; 'table': 0.34; '"the': 0.34; 'connection': 0.35; 'transaction': 0.35; 'something': 0.35; 'operate': 0.35; 'operations': 0.35; 'test': 0.35; 'but': 0.35; 'there': 0.35; 'really': 0.36; 'disk': 0.36; 'sequence': 0.36; 'doing': 0.36; 'charset:us-ascii': 0.36; 'should': 0.36; 'changing': 0.37; 'application': 0.37; 'operating': 0.37; 'two': 0.37; 'level': 0.37; 'step': 0.37; 'connections': 0.38; 'easiest': 0.38; 'window': 0.38; 'writes': 0.38; 'to:addr:python-list': 0.38; 'that,': 0.38; 'little': 0.38; 'does': 0.39; 'itself': 0.39; 'to:addr:python.org': 0.39; 'either': 0.39; 'most': 0.60; 'reserved': 0.61; 'lost': 0.61; 'first': 0.61; 'back': 0.62; 'media': 0.66; 'side': 0.67; 'readers': 0.68; 'overall': 0.69; 'apart': 0.72; 'removal': 0.74; 'other.': 0.75; 'exclusive': 0.81; 'alongside': 0.84; 'condition.': 0.84; 'forced': 0.84; 'jet': 0.84; 'journal': 0.84; 'locked': 0.84; 'nfs': 0.84; 'odds': 0.84; 'persistent': 0.84; 'rolls': 0.84; 'uncertain': 0.84; 'control;': 0.91; 'write:': 0.91; 'received:108': 0.93; 'state.': 0.95; '2013': 0.98 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Dennis Lee Bieber Subject: Re: python-noob - which container is appropriate for later exporting into mySql + matplotlib ? Date: Sat, 13 Apr 2013 16:01:11 -0400 Organization: > Bestiaria Support Staff < References: <5168b87f$0$29977$c3e8da3$5496439d@news.astraweb.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: adsl-108-73-118-117.dsl.klmzmi.sbcglobal.net X-Newsreader: Forte Agent 3.3/32.846 X-No-Archive: YES X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 107 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1365883280 news.xs4all.nl 2613 [2001:888:2000:d::a6]:44175 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:43543 On Sun, 14 Apr 2013 00:03:25 +1000, Chris Angelico declaimed the following in gmane.comp.python.general: > True ACID compliance demands support at every level: > > 1) The application has to operate in logical units of work, which - > apart from with DB2 - requires an explicit "BEGIN" query, or > single-statement transactions. > While SQLite3 normally runs in an auto-commit mode, the Python DB-API spec, in general, requires that auto-commit be turned off. "The Definitive Guide to SQLite" states that the Python adapter scans queries, and will start a transaction if the query is one that will change data (insert/replace/update). Read-only queries stay auto-commit until one of the data change queries is submitted and not committed. > > 3) The operating system and filesystem must support a forced file > synchronization (fsync/fdatasync), so the database engine can wait for > the data to be written to disk. > > 4) The underlying media (hard disk, SSD, USB stick, etc) must respond > to the fsync call by actually writing the content to persistent > storage before returning. > > Failure at any level means the overall system is not ACID compliant. > PostgreSQL has a huge amount of code in it to try to deal with (or at > least recognize) a level-3 failure, but nothing in the database engine > can deal with level 1 or 4 issues. > > You'd have to actually test it. The easiest way is to get two > computers, side by side, and run the database engine on one and a > monitor on the other. To test some SSDs at work, I knocked together a > little program that worked somewhat thus: > > * Connect to the database over TCP/IP (easy, as we were doing this > with PostgreSQL) You don't with SQLite -- or, properly, it is not to an SQLite port... It would be something like an NFS mounted file share -- and we all know how uncertain file locking is over NFS. > * Create a table with a number of rows with an ID and a counter, > initialized to 0 > * Repeatedly, in parallel, perform a transaction: > - Increment the counter on one of the rows (at random) > - Increment a "possible" in-memory counter for that row > - Commit the database transaction > - Increment a "confirmed" in-memory counter for that row > * When an error of "database seems to be down" is detected, wait for > it to come up again, then query the table. The counters must all be at > least their corresponding "possible" value and at most the > "confirmed". > SQLite is a "file server" database (like M$ JET engine [aka: "Access"]). It's locking system is multi-stage. It allows multiple concurrent readers on a "shared" lock state. Only one connection can perform write operations ("reserved" lock) alongside the readers. A second connection attempting to perform a write will be rejected with a database locked condition. Then it really gets nasty -- the writer attempts to commit the update: The first step is to block other connections from even entering the read state (the "pending" lock). However, the writer itself is blocked until all remaining readers have exited; only then does it have exclusive access to and SQLite makes changes to the database file itself (prior to that, the writer connection is changing page images in memory) So in your example above, the first process to submit an update command is going to lock all the others from submitting updates AND will itself be held from committing the update until all the other processes have closed (commit or rollback their "read sessions"). Since the Python adapter basically does auto-commit for all until an update is attempted, the first process to submit the update will get the reserved lock, and the other reading sessions can pop in and out freely. On the attempt to commit, the other sessions will be blocked from even entering a read session, and there should be no other session trying to start a write transaction, so the odds are that the commit goes through (there is a very small window in the locking sequence in which two Python connections that submit update queries might get into the "shared read" state, and one then has to back out when the other gets the "reserved" lock. In the commit phase, SQLite first tries to ensure the rollback journal is flushed to disk -- but that apparently is out of its control; it can submit a sync command to the OS, but has to rely on what the OS tells it about the state of the writes to disk (the book indicates that some IDE drives would lie when queried about sync status, while still having unwritten data in the on-board buffers). After the rollback journal it submits the data to the database. I Crash during journal write: restart finds no journal, that transaction is lost but the database itself is clean Crash after journal during database update, restart finds journal, assumes database is suspect, and rolls back the pages, database is restored to pre-transaction state Crash after database sync during removal of journal, restart either finds journal still there and rolls back the pages restoring to pretransaction state, or the file was removed from the directory and SQLite determines database file is good with the last transaction in place. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/