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
|
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
|
1.30_01 Wed 10 Mar 2010
|
||||||
*** CHANGES THAT MAY POSSIBLY BREAK YOUR OLD APPLICATIONS ***
|
*** CHANGES THAT MAY POSSIBLY BREAK YOUR OLD APPLICATIONS ***
|
||||||
- Resolved #54271: Inserting a string with utf-8 flag on
|
- 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->timeout = SQL_TIMEOUT;
|
||||||
imp_dbh->handle_binary_nulls = FALSE;
|
imp_dbh->handle_binary_nulls = FALSE;
|
||||||
imp_dbh->allow_multiple_statements = FALSE;
|
imp_dbh->allow_multiple_statements = FALSE;
|
||||||
|
imp_dbh->use_immediate_transaction = FALSE;
|
||||||
|
|
||||||
sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);
|
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));
|
imp_dbh->allow_multiple_statements = !(! SvTRUE(valuesv));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
if (strEQ(key, "sqlite_use_immediate_transaction")) {
|
||||||
|
imp_dbh->use_immediate_transaction = !(! SvTRUE(valuesv));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (strEQ(key, "sqlite_unicode")) {
|
if (strEQ(key, "sqlite_unicode")) {
|
||||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||||
sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
|
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")) {
|
if (strEQ(key, "sqlite_allow_multiple_statements")) {
|
||||||
return sv_2mortal(newSViv(imp_dbh->allow_multiple_statements ? 1 : 0));
|
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 (strEQ(key, "sqlite_unicode")) {
|
||||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||||
sqlite_trace(dbh, imp_dbh, 3, "Unicode support is disabled for this version of perl.");
|
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)) {
|
else if (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
|
||||||
sqlite_trace(sth, imp_sth, 3, "BEGIN TRAN");
|
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) {
|
if (rc != SQLITE_OK) {
|
||||||
return -2; /* -> undef in SQLite.xsi */
|
return -2; /* -> undef in SQLite.xsi */
|
||||||
}
|
}
|
||||||
|
|
1
dbdimp.h
1
dbdimp.h
|
@ -30,6 +30,7 @@ struct imp_dbh_st {
|
||||||
AV *aggregates;
|
AV *aggregates;
|
||||||
SV *collation_needed_callback;
|
SV *collation_needed_callback;
|
||||||
bool allow_multiple_statements;
|
bool allow_multiple_statements;
|
||||||
|
bool use_immediate_transaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Statement Handle */
|
/* 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>
|
of the internal SQLite library, which always begins by a C<BEGIN>
|
||||||
statement, and ends by a C<COMMIT> or a <ROLLBACK>.
|
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
|
=head2 Processing Multiple Statements At A Time
|
||||||
|
|
||||||
L<DBI>'s statement handle is not supposed to process multiple
|
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
|
statements at one go. This may be handy, but with performance
|
||||||
penalty. See above for details.
|
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
|
=back
|
||||||
|
|
||||||
=head2 Statement Handle Attributes
|
=head2 Statement Handle Attributes
|
||||||
|
|
Loading…
Add table
Reference in a new issue