Path: csiph.com!usenet.pasdenom.info!gegeweb.org!newsfeed0.kamp.net!newsfeed.kamp.net!feeder1.cambriumusenet.nl!feed.tweaknews.nl!194.109.133.83.MISMATCH!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!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.004 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'python.': 0.02; '(at': 0.04; 'anyway.': 0.05; 'true,': 0.05; '(all': 0.07; 'args': 0.07; 'exist,': 0.09; 'msgid': 0.09; 'oh,': 0.09; 'subject:module': 0.09; 'val': 0.09; 'cc:addr:python-list': 0.11; "wouldn't": 0.14; 'argument,': 0.16; 'complained': 0.16; 'confuse': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'integers,': 0.16; 'query,': 0.16; 'sqlite': 0.16; 'subject:access': 0.16; 'subject:python': 0.16; 'wrote:': 0.18; 'commit': 0.19; 'feb': 0.22; 'cc:addr:python.org': 0.22; "aren't": 0.24; '(or': 0.24; 'cc:2**0': 0.24; 'source': 0.25; 'least': 0.26; 'header:In-Reply-To:1': 0.27; 'message-id:@mail.gmail.com': 0.30; 'work.': 0.31; 'code': 0.31; "skip:' 10": 0.31; 'towards': 0.31; 'constant': 0.31; 'correctly.': 0.31; 'though.': 0.31; 'there.': 0.32; 'probably': 0.32; 'open': 0.33; 'running': 0.33; 'table': 0.34; 'subject:the': 0.34; 'common': 0.35; 'connection': 0.35; 'created': 0.35; 'knows': 0.35; 'something': 0.35; 'test': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'doing': 0.36; "didn't": 0.36; 'subject:?': 0.36; 'should': 0.36; 'las': 0.37; 'two': 0.37; 'pm,': 0.38; 'rather': 0.38; 'that,': 0.38; 'extremely': 0.39; 'use.': 0.39; 'skip:u 10': 0.60; 'easy': 0.60; 'simply': 0.61; "you're": 0.61; "you'll": 0.62; 'connecting': 0.64; 'more': 0.64; 'different': 0.65; 'between': 0.67; 'default': 0.69; 'safe': 0.72; 'exclusive': 0.81; '20000': 0.84; 'points,': 0.84; 'right).': 0.84; 'subject:SQL': 0.84; 'subject:recommended': 0.84; 'this;': 0.91; 'to:none': 0.92; 'have.': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=4EG39u8TcATirahm0S19IoI2A2AbOS3bqi7ce7cQ3CY=; b=B7cL2iVYAn5CxFiamYDe3hXdr7+pW8qRGnIbZxLmhZWtcVRnYYP2Lwsvl9R7uNgp3L LYbgA0skW8Y8U6rMtV3w9kgdxtWvMtOWQnTvMqgAbax0MpStyZHkFGAUEdcfUNyRrALc c+hFWdQPH6p5dE1b1EMFEIBwBhDUNTBqRyzO5Ia4uJ5LOINXGO1On2p70y9X/ha3hLQ7 3v5byEbwvbS661oCbqOgujxXI+HKBnRFTEGGOYuVAh+mIEgq4SPxs403lp8jHIIv1eI9 yLupSXefVcjoEYDidlYMRKlKWQpc1XpkXHBA3PnDXMg/xpRVbK7A0pApYhuS3KX3sDuf 1BKg== MIME-Version: 1.0 X-Received: by 10.66.160.2 with SMTP id xg2mr19491888pab.23.1391951690580; Sun, 09 Feb 2014 05:14:50 -0800 (PST) In-Reply-To: References: Date: Mon, 10 Feb 2014 00:14:50 +1100 Subject: Re: What is the recommended python module for SQL database access? From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 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: 49 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1391951699 news.xs4all.nl 2941 [2001:888:2000:d::a6]:47350 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:65755 On Sun, Feb 9, 2014 at 11:47 PM, Asaf Las wrote: > i simply tested running 2 independent processes started at same time in > parallel towards same sqlite database and never get 20000 in that row > though used exclusive lock on DB. might be i did something wrong. The threading locks aren't doing anything, because you don't have multiple threads here; what you need is SQLite locks, which you'll already have. I don't know why it wouldn't work. Unfortunately I wasn't able to test your code directly - SQLite complained that the table didn't exist, despite my having created it (at least, so I thought) in interactive Python. So probably I mucked something up there. Someone who actually knows SQLite might be better able to explain. A few points, though. > c.execute("UPDATE msgid SET val={0} WHERE id = 0".format(tint)) Don't do this; instead, let c.execute() do the interpolation, by giving it extra args rather than using .format(). It makes no difference when you're working with integers, but with strings, it makes the difference between safe and not-safe (or easy and unnecessarily fiddly, if you actually take the time to get your escaping right). Also, you're connecting and disconnecting repeatedly... oh, I see why it didn't work when I tried. You're also using two completely different database names: 'messageid.db' which is named in a constant and in the default argument, and 'example.db' which is what you actually use. Should have a single source of truth, otherwise you confuse the people who might otherwise be able to test your code :) Anyway. This code is extremely inefficient: > conn = sqlite3.connect('example.db', 10.0, True, "EXCLUSIVE") > c = conn.cursor() > c.execute("SELECT val FROM msgid WHERE id = 0") > tint = int(c.fetchone()[0]) + 1 > c.execute("UPDATE msgid SET val={0} WHERE id = 0".format(tint)) > conn.commit() > conn.close() Much more common would be to retain a connection and repeatedly perform queries. Then you won't need to open it EXCLUSIVE, and you can simply query, update, and then commit (all your locks should be released at the commit). Do that, and you should see at least reasonable performance, plus everything should work correctly. ChrisA