[Checkins] SVN: relstorage/trunk/ Merged changes from the 1.1
branch.
Shane Hathaway
shane at hathawaymix.org
Sat May 10 02:43:24 EDT 2008
Log message for revision 86608:
Merged changes from the 1.1 branch.
This is my first try at merging in Subversion. Is it really this hard?
This is how I did it:
svn merge -r 85842:86602 ../branches/1.1 .
Figuring out those revision numbers was complicated.
With Mercurial this would have been a breeze:
hg pull ../branches/1.1
That command would simply do the right thing. Isn't there an equivalent
for Subversion? Hmph.
Changed:
U relstorage/trunk/CHANGELOG.txt
U relstorage/trunk/notes/migrate-1.0.1.txt
U relstorage/trunk/relstorage/adapters/mysql.py
U relstorage/trunk/relstorage/adapters/postgresql.py
-=-
Modified: relstorage/trunk/CHANGELOG.txt
===================================================================
--- relstorage/trunk/CHANGELOG.txt 2008-05-10 06:34:34 UTC (rev 86607)
+++ relstorage/trunk/CHANGELOG.txt 2008-05-10 06:43:24 UTC (rev 86608)
@@ -1,4 +1,13 @@
+RelStorage 1.1b2
+
+- Made the MySQL locks database-specific rather than server-wide. This is
+ important for multi-database configurations.
+
+- In the PostgreSQL adapter, made the pack lock fall back to table locking
+ rather than advisory locks for PostgreSQL 8.1.
+
+
RelStorage 1.1b1
- Fixed the use of setup.py without setuptools. Thanks to Chris Withers.
Modified: relstorage/trunk/notes/migrate-1.0.1.txt
===================================================================
--- relstorage/trunk/notes/migrate-1.0.1.txt 2008-05-10 06:34:34 UTC (rev 86607)
+++ relstorage/trunk/notes/migrate-1.0.1.txt 2008-05-10 06:43:24 UTC (rev 86608)
@@ -5,8 +5,6 @@
CREATE INDEX object_state_prev_tid ON object_state (prev_tid);
- DROP TABLE pack_lock;
-
DROP INDEX pack_object_keep_zoid;
CREATE INDEX pack_object_keep_false ON pack_object (zoid)
WHERE keep = false;
@@ -17,7 +15,7 @@
CREATE INDEX current_object_tid ON current_object (tid);
- ALTER TABLE object_ref PRIMARY KEY (tid, zoid, to_zoid);
+ ALTER TABLE object_ref ADD PRIMARY KEY (tid, zoid, to_zoid);
DROP INDEX object_ref_from;
DROP INDEX object_ref_tid;
DROP INDEX object_ref_to;
@@ -32,6 +30,17 @@
tid BIGINT NOT NULL PRIMARY KEY
);
+Users of PostgreSQL 8.2 and above should also drop the pack_lock table since
+it has been replaced with an advisory lock:
+
+ DROP TABLE pack_lock;
+
+Users of PostgreSQL 8.1 and below still need the pack_lock table. If you
+have deleted it, please create it again with the following statement:
+
+ CREATE TABLE pack_lock ();
+
+
MySQL:
CREATE INDEX object_state_prev_tid ON object_state (prev_tid);
@@ -55,6 +64,7 @@
tid BIGINT NOT NULL PRIMARY KEY
) ENGINE = MyISAM;
+
Oracle:
CREATE INDEX object_state_prev_tid ON object_state (prev_tid);
Modified: relstorage/trunk/relstorage/adapters/mysql.py
===================================================================
--- relstorage/trunk/relstorage/adapters/mysql.py 2008-05-10 06:34:34 UTC (rev 86607)
+++ relstorage/trunk/relstorage/adapters/mysql.py 2008-05-10 06:43:24 UTC (rev 86608)
@@ -411,12 +411,7 @@
def start_commit(self, cursor):
"""Prepare to commit."""
- # Hold commit_lock to prevent concurrent commits.
- cursor.execute("SELECT GET_LOCK('relstorage.commit', %s)",
- (commit_lock_timeout,))
- locked = cursor.fetchone()[0]
- if not locked:
- raise StorageError("Unable to acquire commit lock")
+ self._hold_commit_lock(cursor)
def get_tid_and_time(self, cursor):
"""Returns the most recent tid and the current database time.
@@ -519,12 +514,12 @@
def commit_phase2(self, cursor, txn):
"""Final transaction commit."""
cursor.connection.commit()
- cursor.execute("SELECT RELEASE_LOCK('relstorage.commit')")
+ self._release_commit_lock(cursor)
def abort(self, cursor, txn=None):
"""Abort the commit. If txn is not None, phase 1 is also aborted."""
cursor.connection.rollback()
- cursor.execute("SELECT RELEASE_LOCK('relstorage.commit')")
+ self._release_commit_lock(cursor)
def new_oid(self, cursor):
"""Return a new, unused OID."""
@@ -543,7 +538,7 @@
Raise an exception if packing or undo is already in progress.
"""
- stmt = "SELECT GET_LOCK('relstorage.pack', 0)"
+ stmt = "SELECT GET_LOCK(CONCAT(DATABASE(), '.pack'), 0)"
cursor.execute(stmt)
res = cursor.fetchone()[0]
if not res:
@@ -552,7 +547,7 @@
def release_pack_lock(self, cursor):
"""Release the pack lock."""
- stmt = "SELECT RELEASE_LOCK('relstorage.pack')"
+ stmt = "SELECT RELEASE_LOCK(CONCAT(DATABASE(), '.pack'))"
cursor.execute(stmt)
@@ -574,11 +569,11 @@
def _hold_commit_lock(self, cursor):
- """Hold the commit lock for packing.
+ """Hold the commit lock.
This overrides the method by the same name in common.Adapter.
"""
- cursor.execute("SELECT GET_LOCK('relstorage.commit', %s)",
+ cursor.execute("SELECT GET_LOCK(CONCAT(DATABASE(), '.commit'), %s)",
(commit_lock_timeout,))
locked = cursor.fetchone()[0]
if not locked:
@@ -586,12 +581,11 @@
def _release_commit_lock(self, cursor):
- """Release the commit lock. This is used during packing.
+ """Release the commit lock.
This overrides the method by the same name in common.Adapter.
"""
- stmt = "SELECT RELEASE_LOCK('relstorage.commit')"
- cursor.execute(stmt)
+ cursor.execute("SELECT RELEASE_LOCK(CONCAT(DATABASE(), '.commit'))")
_poll_query = "SELECT tid FROM transaction ORDER BY tid DESC LIMIT 1"
Modified: relstorage/trunk/relstorage/adapters/postgresql.py
===================================================================
--- relstorage/trunk/relstorage/adapters/postgresql.py 2008-05-10 06:34:34 UTC (rev 86607)
+++ relstorage/trunk/relstorage/adapters/postgresql.py 2008-05-10 06:43:24 UTC (rev 86608)
@@ -16,6 +16,7 @@
from base64 import decodestring, encodestring
import logging
import psycopg2, psycopg2.extensions
+import re
from ZODB.POSException import StorageError
from common import Adapter
@@ -135,7 +136,10 @@
"""
cursor.execute(stmt)
+ if not self._pg_has_advisory_locks(cursor):
+ cursor.execute("CREATE TABLE pack_lock ()")
+
def prepare_schema(self):
"""Create the database schema if it does not already exist."""
conn, cursor = self.open()
@@ -207,6 +211,20 @@
psycopg2.OperationalError):
pass
+ def _pg_version(self, cursor):
+ """Return the (major, minor) version of PostgreSQL"""
+ cursor.execute("SELECT version()")
+ v = cursor.fetchone()[0]
+ m = re.search(r"([0-9]+)[.]([0-9]+)", v)
+ if m is None:
+ raise AssertionError("Unable to detect PostgreSQL version: " + v)
+ else:
+ return int(m.group(1)), int(m.group(2))
+
+ def _pg_has_advisory_locks(self, cursor):
+ """Return true if this version of PostgreSQL supports advisory locks"""
+ return self._pg_version(cursor) >= (8, 2)
+
def open_for_load(self):
"""Open and initialize a connection for loading objects.
@@ -570,21 +588,27 @@
cursor.execute(stmt)
return cursor.fetchone()[0]
-
def hold_pack_lock(self, cursor):
"""Try to acquire the pack lock.
Raise an exception if packing or undo is already in progress.
"""
- stmt = "SELECT pg_try_advisory_lock(1)"
- cursor.execute(stmt)
- locked = cursor.fetchone()[0]
- if not locked:
- raise StorageError('A pack or undo operation is in progress')
+ if self._pg_has_advisory_locks(cursor):
+ cursor.execute("SELECT pg_try_advisory_lock(1)")
+ locked = cursor.fetchone()[0]
+ if not locked:
+ raise StorageError('A pack or undo operation is in progress')
+ else:
+ # b/w compat
+ try:
+ cursor.execute("LOCK pack_lock IN EXCLUSIVE MODE NOWAIT")
+ except psycopg2.DatabaseError:
+ raise StorageError('A pack or undo operation is in progress')
def release_pack_lock(self, cursor):
"""Release the pack lock."""
- stmt = "SELECT pg_advisory_unlock(1)"
- cursor.execute(stmt)
+ if self._pg_has_advisory_locks(cursor):
+ cursor.execute("SELECT pg_advisory_unlock(1)")
+ # else no action needed since the lock will be released at txn commit
_poll_query = "EXECUTE get_latest_tid"
More information about the Checkins
mailing list