mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 14:19:10 -04:00
This commit is contained in:
parent
090bb74e25
commit
80b0265961
4 changed files with 57 additions and 1 deletions
4
Changes
4
Changes
|
@ -1,5 +1,9 @@
|
|||
Changes for Perl extension DBD-SQLite
|
||||
|
||||
1.30_02 to be released
|
||||
- Implemented sqlite_use_immediate_transaction database handle
|
||||
attribute to avoid deadlocks easily (ISHIGAKI)
|
||||
|
||||
1.30_01 Wed 10 Mar 2010
|
||||
*** CHANGES THAT MAY POSSIBLY BREAK YOUR OLD APPLICATIONS ***
|
||||
- Resolved #54271: Inserting a string with utf-8 flag on
|
||||
|
|
14
dbdimp.c
14
dbdimp.c
|
@ -163,6 +163,7 @@ sqlite_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pa
|
|||
imp_dbh->timeout = SQL_TIMEOUT;
|
||||
imp_dbh->handle_binary_nulls = FALSE;
|
||||
imp_dbh->allow_multiple_statements = FALSE;
|
||||
imp_dbh->use_immediate_transaction = FALSE;
|
||||
|
||||
sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);
|
||||
|
||||
|
@ -345,6 +346,10 @@ sqlite_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
|
|||
imp_dbh->allow_multiple_statements = !(! SvTRUE(valuesv));
|
||||
return TRUE;
|
||||
}
|
||||
if (strEQ(key, "sqlite_use_immediate_transaction")) {
|
||||
imp_dbh->use_immediate_transaction = !(! SvTRUE(valuesv));
|
||||
return TRUE;
|
||||
}
|
||||
if (strEQ(key, "sqlite_unicode")) {
|
||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||
sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
|
||||
|
@ -379,6 +384,9 @@ sqlite_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
|
|||
if (strEQ(key, "sqlite_allow_multiple_statements")) {
|
||||
return sv_2mortal(newSViv(imp_dbh->allow_multiple_statements ? 1 : 0));
|
||||
}
|
||||
if (strEQ(key, "sqlite_use_immediate_transaction")) {
|
||||
return sv_2mortal(newSViv(imp_dbh->use_immediate_transaction ? 1 : 0));
|
||||
}
|
||||
if (strEQ(key, "sqlite_unicode")) {
|
||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||
sqlite_trace(dbh, imp_dbh, 3, "Unicode support is disabled for this version of perl.");
|
||||
|
@ -578,7 +586,11 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth)
|
|||
}
|
||||
else if (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
|
||||
sqlite_trace(sth, imp_sth, 3, "BEGIN TRAN");
|
||||
rc = sqlite_exec(sth, "BEGIN TRANSACTION");
|
||||
if (imp_dbh->use_immediate_transaction) {
|
||||
rc = sqlite_exec(sth, "BEGIN IMMEDIATE TRANSACTION");
|
||||
} else {
|
||||
rc = sqlite_exec(sth, "BEGIN TRANSACTION");
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
return -2; /* -> undef in SQLite.xsi */
|
||||
}
|
||||
|
|
1
dbdimp.h
1
dbdimp.h
|
@ -30,6 +30,7 @@ struct imp_dbh_st {
|
|||
AV *aggregates;
|
||||
SV *collation_needed_callback;
|
||||
bool allow_multiple_statements;
|
||||
bool use_immediate_transaction;
|
||||
};
|
||||
|
||||
/* Statement Handle */
|
||||
|
|
|
@ -871,6 +871,39 @@ This C<AutoCommit> mode is independent from the autocommit mode
|
|||
of the internal SQLite library, which always begins by a C<BEGIN>
|
||||
statement, and ends by a C<COMMIT> or a <ROLLBACK>.
|
||||
|
||||
=head2 Transaction and Database Locking
|
||||
|
||||
Transaction by C<AutoCommit> or C<begin_work> is nice and handy, but
|
||||
sometimes you may get an annoying "database is locked" error.
|
||||
This typically happens when someone begins a transaction, and tries
|
||||
to write to a database while other person is reading from the
|
||||
database (in another transaction). You might be surprised but SQLite
|
||||
doesn't lock a database when you just begin a normal (deferred)
|
||||
transaction to maximize concurrency. It reserves a lock when you
|
||||
issue a statement to write, but until you actually try to write
|
||||
with a C<commit> statement, it allows other people to read from
|
||||
the database. However, reading from the database also requires
|
||||
C<shared lock>, and that prevents to give you the C<exclusive lock>
|
||||
you reserved, thus you get the "database is locked" error, and
|
||||
other people will get the same error if they try to write afterwards,
|
||||
as you still have a C<pending> lock. C<busy_timeout> doesn't help
|
||||
in this case.
|
||||
|
||||
To avoid this, set a transaction type explicitly. You can issue a
|
||||
C<begin immediate transaction> (or C<begin exclusive transaction>)
|
||||
for each transaction, or set C<sqlite_use_immediate_transaction>
|
||||
database handle attribute to true (since 1.30_02) to always use
|
||||
an immediate transaction (even when you simply use C<begin_work>
|
||||
or turn off the C<AutoCommit>.).
|
||||
|
||||
my $dbh = DBI->connect("dbi:SQLite::memory:", "", "", {
|
||||
sqlite_use_immediate_transaction => 1,
|
||||
});
|
||||
|
||||
Note that this works only when all of the connections use the same
|
||||
(non-deferred) transaction. See L<http://sqlite.org/lockingv3.html>
|
||||
for locking details.
|
||||
|
||||
=head2 Processing Multiple Statements At A Time
|
||||
|
||||
L<DBI>'s statement handle is not supposed to process multiple
|
||||
|
@ -972,6 +1005,12 @@ If you set this to true, C<do> method will process multiple
|
|||
statements at one go. This may be handy, but with performance
|
||||
penalty. See above for details.
|
||||
|
||||
=item sqlite_use_immediate_transaction
|
||||
|
||||
If you set this to true, DBD::SQLite tries to issue a C<begin
|
||||
immediate transaction> (instead of C<begin transaction>) when
|
||||
necessary. See above for details.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Statement Handle Attributes
|
||||
|
|
Loading…
Add table
Reference in a new issue