Pushing all the Gemini changes above the table handler.
This commit is contained in:
parent
c4beb8321f
commit
ceac5f9227
@ -15,6 +15,10 @@ $make -k clean || true
|
||||
aclocal && autoheader && aclocal && automake && autoconf
|
||||
(cd bdb/dist && sh s_all)
|
||||
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
if [ -d gemini ]
|
||||
then
|
||||
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
fi
|
||||
|
||||
CFLAGS=\"$cflags\" CXX=gcc CXXFLAGS=\"$cxxflags\" $configure"
|
||||
|
||||
|
@ -1 +1 @@
|
||||
mwagner@evoq.mwagner.org
|
||||
mikef@nslinux.bedford.progress.com
|
||||
|
893
Docs/manual.texi
893
Docs/manual.texi
@ -529,10 +529,25 @@ BDB or Berkeley_DB Tables
|
||||
|
||||
GEMINI Tables
|
||||
|
||||
* GEMINI overview::
|
||||
* GEMINI start::
|
||||
* GEMINI features::
|
||||
* GEMINI TODO::
|
||||
* GEMINI Overview::
|
||||
* Using GEMINI Tables::
|
||||
|
||||
GEMINI Overview
|
||||
|
||||
* GEMINI Features::
|
||||
* GEMINI Concepts::
|
||||
* GEMINI Limitations::
|
||||
|
||||
Using GEMINI Tables
|
||||
|
||||
* Startup Options::
|
||||
* Creating GEMINI Tables::
|
||||
* Backing Up GEMINI Tables::
|
||||
* Restoring GEMINI Tables::
|
||||
* Using Auto_Increment Columns With GEMINI Tables::
|
||||
* Performance Considerations::
|
||||
* Sample Configurations::
|
||||
* When To Use GEMINI Tables::
|
||||
|
||||
InnoDB Tables
|
||||
|
||||
@ -10119,7 +10134,7 @@ If you are using BDB (Berkeley DB) tables, you should familiarize
|
||||
yourself with the different BDB specific startup options. @xref{BDB start}.
|
||||
|
||||
If you are using Gemini tables, refer to the Gemini-specific startup options.
|
||||
@xref{GEMINI start}.
|
||||
@xref{Using GEMINI Tables}.
|
||||
|
||||
If you are using InnoDB tables, refer to the InnoDB-specific startup
|
||||
options. @xref{InnoDB start}.
|
||||
@ -18868,7 +18883,7 @@ When you insert a value of @code{NULL} (recommended) or @code{0} into an
|
||||
|
||||
If you delete the row containing the maximum value for an
|
||||
@code{AUTO_INCREMENT} column, the value will be reused with an
|
||||
@code{ISAM}, @code{BDB} or @code{INNODB} table but not with a
|
||||
@code{ISAM}, @code{GEMINI}, @code{BDB} or @code{INNODB} table but not with a
|
||||
@code{MyISAM} table. If you delete all rows in the table with
|
||||
@code{DELETE FROM table_name} (without a @code{WHERE}) in
|
||||
@code{AUTOCOMMIT} mode, the sequence starts over for both table types.
|
||||
@ -24558,87 +24573,849 @@ not in @code{auto_commit} mode, until this problem is fixed (the fix is
|
||||
not trivial).
|
||||
@end itemize
|
||||
|
||||
@cindex tables, @code{GEMINI}
|
||||
@cindex GEMINI tables
|
||||
@node GEMINI, InnoDB, BDB, Table types
|
||||
@section GEMINI Tables
|
||||
|
||||
@cindex GEMINI tables, overview
|
||||
@menu
|
||||
* GEMINI overview::
|
||||
* GEMINI start::
|
||||
* GEMINI features::
|
||||
* GEMINI TODO::
|
||||
* GEMINI Overview::
|
||||
* Using GEMINI Tables::
|
||||
@end menu
|
||||
|
||||
@node GEMINI overview, GEMINI start, GEMINI, GEMINI
|
||||
@subsection Overview of GEMINI tables
|
||||
@node GEMINI Overview, Using GEMINI Tables, GEMINI, GEMINI
|
||||
@subsection GEMINI Overview
|
||||
|
||||
The @code{GEMINI} table type is developed and supported by NuSphere Corporation
|
||||
(@uref{http://www.nusphere.com}). It features row-level locking, transaction
|
||||
support (@code{COMMIT} and @code{ROLLBACK}), and automatic crash recovery.
|
||||
@code{GEMINI} is a transaction-safe table handler for @strong{MySQL}. It
|
||||
provides row-level locking, robust transaction support and reliable
|
||||
crash recovery. It is targeted for databases that need to handle heavy
|
||||
multi-user updates typical of transaction processing applications while
|
||||
still providing excellent performance for read-intensive operations. The
|
||||
@code{GEMINI} table type is developed and supported by NuSphere
|
||||
Corporation (see @url{http://www.nusphere.com}).
|
||||
|
||||
@code{GEMINI} tables will be included in some future @strong{MySQL} 3.23.X
|
||||
source distribution.
|
||||
@code{GEMINI} provides full ACID transaction properties (Atomic,
|
||||
Consistent, Independent, and Durable) with a programming model that
|
||||
includes support for statement atomicity and all four standard isolation
|
||||
levels (Read Uncommitted, Read Committed, Repeatable Read, and
|
||||
Serializable) defined in the SQL standard.
|
||||
|
||||
@node GEMINI start, GEMINI features, GEMINI overview, GEMINI
|
||||
@subsection GEMINI startup options
|
||||
The @code{GEMINI} tables support row-level and table-level locking to
|
||||
increase concurrency in applications and allow reading of tables without
|
||||
locking for maximum concurrency in a heavy update environment. The
|
||||
transaction, locking, and recovery mechanisms are tightly integrated to
|
||||
eliminate unnecessary administration overhead.
|
||||
|
||||
If you are running with @code{AUTOCOMMIT=0} then your changes in @code{GEMINI}
|
||||
tables will not be updated until you execute @code{COMMIT}. Instead of commit
|
||||
you can execute @code{ROLLBACK} to forget your changes. @xref{COMMIT}.
|
||||
In general, if @code{GEMINI} tables are selected for an application, it
|
||||
is recommended that all tables updated in the application be
|
||||
@code{GEMINI} tables to provide well-defined system behavior. If
|
||||
non-@code{GEMINI} tables are mixed into the application then, ACID
|
||||
transaction properties cannot be maintained. While there are clearly
|
||||
cases where mixing table types is appropriate, it should always be done
|
||||
with careful consideration of the impact on transaction consistency and
|
||||
recoverability needs of the application and underlying database.
|
||||
|
||||
If you are running with @code{AUTOCOMMIT=1} (the default), your changes
|
||||
will be committed immediately. You can start an extended transaction with
|
||||
the @code{BEGIN WORK} SQL command, after which your changes will not be
|
||||
committed until you execute @code{COMMIT} (or decide to @code{ROLLBACK}
|
||||
the changes).
|
||||
The @code{GEMINI} table type is derived from a successful commercial
|
||||
database and uses the storage kernel technology tightly integrated with
|
||||
@strong{MySQL} server. The basic @code{GEMINI} technology is in use by
|
||||
millions of users worldwide in production environments today. This
|
||||
maturity allows @code{GEMINI} tables to provide a solution for those
|
||||
users who require transaction-based behavior as part of their
|
||||
applications.
|
||||
|
||||
The following options to @code{mysqld} can be used to change the behavior of
|
||||
GEMINI tables:
|
||||
The @code{GEMINI} table handler supports a configurable data cache that
|
||||
allows a significant portion of any database to be maintained in memory
|
||||
while still allowing durable updates.
|
||||
|
||||
@multitable @columnfractions .30 .70
|
||||
@item @strong{Option} @tab @strong{Meaning}
|
||||
@item @code{--gemini-full-recovery} @tab Default.
|
||||
@item @code{--gemini-no-recovery} @tab Turn off recovery logging. Not recommended.
|
||||
@item @code{--gemini-lazy-commit} @tab Relaxes the flush log at commit rule.
|
||||
@item @code{--gemini-unbuffered-io} @tab All database writes bypass OS cache.
|
||||
@item @code{--skip-gemini} @tab Don't use Gemini.
|
||||
@item @code{--O gemini_db_buffers=#} @tab Number of database buffers in database cache.
|
||||
@item @code{--O gemini_connection_limit=#} @tab Maximum number of connections to Gemini.
|
||||
@item @code{--O gemini_spin_retries=#} @tab Spin lock retries (optimization).
|
||||
@item @code{--O gemini_io_threads=#} @tab Number of background I/O threads.
|
||||
@item @code{--O gemini_lock_table_size=#} @tab Set the maximum number of locks. Default 4096.
|
||||
@cindex GEMINI tables, features
|
||||
@menu
|
||||
* GEMINI Features::
|
||||
* GEMINI Concepts::
|
||||
* GEMINI Limitations::
|
||||
@end menu
|
||||
|
||||
@node GEMINI Features, GEMINI Concepts, GEMINI Overview, GEMINI Overview
|
||||
@subsubsection GEMINI Features
|
||||
|
||||
The following summarizes the major features provided by @code{GEMINI}
|
||||
tables.
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Supports all optimization statistics used by the @strong{MySQL} optimizer
|
||||
including table cardinality, index range estimates and multi-component
|
||||
selectivity to insure optimal query performance.
|
||||
|
||||
@item
|
||||
Maintains exact cardinality information for each table so @code{SELECT
|
||||
COUNT(*) FROM} table-name always returns an answer immediately.
|
||||
|
||||
@item
|
||||
Supports index-only queries; when index data is sufficient to resolve a
|
||||
query no record data is read (for non character types).
|
||||
|
||||
@item
|
||||
@code{GEMINI} uses block based I/O for better performance. There is no
|
||||
performance penalty for using @code{VARCHAR} fields. The maximum record size is
|
||||
currently 32K.
|
||||
|
||||
@item
|
||||
The number of rows in a single @code{GEMINI} table can be 4 quintillion
|
||||
(full use of 64 bits).
|
||||
|
||||
@item
|
||||
Individual tables can be as large as 16 petabytes.
|
||||
|
||||
@item
|
||||
Locking is done at a record or row level rather than at table level
|
||||
unless table locks are explicitly requested. When a row is inserted into
|
||||
a table, other rows can be updated, inserted or deleted without waiting
|
||||
for the inserted row to be committed.
|
||||
|
||||
@item
|
||||
Provides durable transactions backed by a crash recovery mechanism that
|
||||
returns the database to a known consistent state in the event of an
|
||||
unexpected failure.
|
||||
|
||||
@item
|
||||
Support for all isolation levels and statement atomicity defined in the
|
||||
SQL standard.
|
||||
|
||||
@item
|
||||
Reliable Master Replication; the master database can survive system
|
||||
failure and recover all committed transactions.
|
||||
@end itemize
|
||||
|
||||
@cindex GEMINI tables, concepts
|
||||
@node GEMINI Concepts, GEMINI Limitations, GEMINI Features, GEMINI Overview
|
||||
@subsubsection GEMINI Concepts
|
||||
|
||||
This section highlights some of the important concepts behind
|
||||
@code{GEMINI} and the @code{GEMINI} programming model, including:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
ACID Transactions
|
||||
@item
|
||||
Transaction COMMIT/ROLLBACK
|
||||
@item
|
||||
Statement Atomicity
|
||||
@item
|
||||
Recovery
|
||||
@item
|
||||
Isolation Levels
|
||||
@item
|
||||
Row-Level Locking
|
||||
@end itemize
|
||||
|
||||
These features are described below.
|
||||
|
||||
@cindex GEMINI tables, ACID transactions
|
||||
@noindent
|
||||
@strong{ACID Transactions}
|
||||
|
||||
ACID in the context of transactions is an acronym which stands for
|
||||
@emph{Atomicity}, @emph{Consistency}, @emph{Isolation}, @emph{Durability}.
|
||||
|
||||
@multitable @columnfractions .25 .75
|
||||
@item @sc{Attribute} @tab @sc{Description}
|
||||
@item
|
||||
@strong{Atomicity}
|
||||
@tab A transaction allows for the grouping of one or more changes to
|
||||
tables and rows in the database to form an atomic or indivisible
|
||||
operation. That is, either all of the changes occur or none of them
|
||||
do. If for any reason the transaction cannot be completed, everything
|
||||
this transaction changed can be restored to the state it was in prior to
|
||||
the start of the transaction via a rollback operation.
|
||||
|
||||
@item
|
||||
@strong{Consistency}
|
||||
@tab
|
||||
Transactions always operate on a consistent view of the data and when
|
||||
they end always leave the data in a consistent state. Data may be said to
|
||||
be consistent as long as it conforms to a set of invariants, such as no
|
||||
two rows in the customer table have the same customer ID and all orders
|
||||
have an associated customer row. While a transaction executes, these
|
||||
invariants may be violated, but no other transaction will be allowed to
|
||||
see these inconsistencies, and all such inconsistencies will have been
|
||||
eliminated by the time the transaction ends.
|
||||
|
||||
@item
|
||||
@strong{Isolation}
|
||||
@tab To a given transaction, it should appear as though it is running
|
||||
all by itself on the database. The effects of concurrently running
|
||||
transactions are invisible to this transaction, and the effects of this
|
||||
transaction are invisible to others until the transaction is committed.
|
||||
|
||||
@item
|
||||
@strong{Durability}
|
||||
@tab Once a transaction is committed, its effects are guaranteed to
|
||||
persist even in the event of subsequent system failures. Until the
|
||||
transaction commits, not only are any changes made by that transaction
|
||||
not durable, but are guaranteed not to persist in the face of a system
|
||||
failures, as crash recovery will rollback their effects.
|
||||
@end multitable
|
||||
|
||||
If you use @code{--skip-gemini}, @strong{MySQL} will not initialize the
|
||||
Gemini table handler, saving memory; you cannot use Gemini tables if you
|
||||
use @code{--skip-gemini}.
|
||||
@cindex GEMINI tables, COMMIT/ROLLBACK
|
||||
@noindent
|
||||
@strong{Transaction COMMIT/ROLLBACK}
|
||||
|
||||
@node GEMINI features, GEMINI TODO, GEMINI start, GEMINI
|
||||
@subsection Features of @code{GEMINI} tables:
|
||||
As stated above, a transaction is a group of work being done to
|
||||
data. Unless otherwise directed, @strong{MySQL} considers each statement
|
||||
a transaction in itself. Multiple updates can be accomplished by placing
|
||||
them in a single statement, however they are limited to a single table.
|
||||
|
||||
Applications tend to require more robust use of transaction
|
||||
concepts. Take, for example, a system that processes an order: A row may
|
||||
be inserted in an order table, additional rows may be added to an
|
||||
order-line table, updates may be made to inventory tables, etc. It is
|
||||
important that if the order completes, all the changes are made to all
|
||||
the tables involved; likewise if the order fails, none of the changes to
|
||||
the tables must occur. To facilitate this requirement, @strong{MySQL}
|
||||
has syntax to start a transaction called @code{BEGIN WORK}. All
|
||||
statements that occur after the @code{BEGIN WORK} statement are grouped
|
||||
into a single transaction. The end of this transaction occurs when a
|
||||
@code{COMMIT} or @code{ROLLBACK} statement is encountered. After the
|
||||
@code{COMMIT} or @code{ROLLBACK} the system returns back to the behavior
|
||||
before the @code{BEGIN WORK} statement was encountered where every
|
||||
statement is a transaction.
|
||||
|
||||
To permanently turn off the behavior where every statement is a
|
||||
transaction, @strong{MySQL} added a variable called
|
||||
@code{AUTOCOMMIT}. The @code{AUTOCOMMIT} variable can have two values,
|
||||
@code{1} and @code{0}. The mode where every statement is a transaction
|
||||
is when @code{AUTOCOMMIT} is set to @code{1} (@code{AUTOCOMMIT=1}). When
|
||||
@code{AUTOCOMMIT} is set to @code{0} (@code{AUTOCOMMIT=0}), then every
|
||||
statement is part of the same transaction until the transaction end by
|
||||
either @code{COMMIT} or @code{ROLLBACK}. Once a transaction completes, a
|
||||
new transaction is immediately started and the process repeats.
|
||||
|
||||
Here is an example of the SQL statements that you may find in a typical
|
||||
order:
|
||||
|
||||
@example
|
||||
BEGIN WORK;
|
||||
INSERT INTO order VALUES ...;
|
||||
INSERT INTO order-lines VALUES ...;
|
||||
INSERT INTO order-lines VALUES ...;
|
||||
INSERT INTO order-lines VALUES ...;
|
||||
UPDATE inventory WHERE ...;
|
||||
COMMIT;
|
||||
@end example
|
||||
|
||||
This example shows how to use the @code{BEGIN WORK} statement to start a
|
||||
transaction. If the variable @code{AUTOCOMMIT} is set to @code{0}, then
|
||||
a transaction would have been started already. In this case, the
|
||||
@code{BEGIN WORK} commits the current transaction and starts a new one.
|
||||
|
||||
@cindex GEMINI tables, statement atomicity
|
||||
@noindent
|
||||
@strong{Statement Atomicity}
|
||||
|
||||
As mentioned above, when running with @code{AUTOCOMMIT} set to @code{1},
|
||||
each statement executes as a single transaction. When a statement has an
|
||||
error, then all changes make by the statement must be
|
||||
undone. Transactions support this behavior. Non-transaction safe table
|
||||
handlers would have a partial statement update where some of the changes
|
||||
from the statement would be contained in the database and other changes
|
||||
from the statement would not. Work would need to be done to manually
|
||||
recover from the error.
|
||||
|
||||
@cindex GEMINI tables, recovery
|
||||
@noindent
|
||||
@strong{Recovery}
|
||||
|
||||
Transactions are the basis for database recovery. Recovery is what
|
||||
supports the Durability attribute of the ACID transaction.
|
||||
|
||||
@code{GEMINI} uses a separate file called the Recovery Log located in
|
||||
the @code{$DATADIR} directory named @code{gemini.rl}. This file
|
||||
maintains the integrity of all the @code{GEMINI} tables. @code{GEMINI}
|
||||
can not recover any data from non-@code{GEMINI} tables. In addition, the
|
||||
@code{gemini.rl} file is used to rollback transactions in support of the
|
||||
@code{ROLLBACK} statement.
|
||||
|
||||
In the event of a system failure, the next time the @strong{MySQL}
|
||||
server is started, @code{GEMINI} will automatically go through its
|
||||
crash recovery process. The result of crash recovery is that all the
|
||||
@code{GEMINI} tables will contain the latest changes made to them, and
|
||||
all transactions that were open at the time of the crash will have been
|
||||
rolled back.
|
||||
|
||||
The @code{GEMINI} Recovery Log reuses space when it can. Space can be
|
||||
reused when information in the Recovery Log is no longer needed for
|
||||
crash recovery or rollback.
|
||||
|
||||
@cindex GEMINI tables, isolation levels
|
||||
@noindent
|
||||
@strong{Isolation Levels}
|
||||
|
||||
There are four isolation levels supported by @code{GEMINI}:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
If a query result can be resolved solely from the index key, Gemini will
|
||||
not read the actual row stored in the database.
|
||||
READ UNCOMMITTED
|
||||
@item
|
||||
Locking on Gemini tables is done at row level.
|
||||
READ COMMITTED
|
||||
@item
|
||||
@code{SELECT COUNT(*) FROM table_name} is fast; Gemini maintains a count
|
||||
of the number of rows in the table.
|
||||
REPEATABLE READ
|
||||
@item
|
||||
SERIALIZABLE
|
||||
@end itemize
|
||||
|
||||
@node GEMINI TODO, , GEMINI features, GEMINI
|
||||
@subsection Current limitations of @code{GEMINI} tables:
|
||||
These isolation levels apply only to shared locks obtained by select
|
||||
statements, excluding select for update. Statements that get exclusive
|
||||
locks always retain those locks until the transaction commits or rolls
|
||||
back.
|
||||
|
||||
By default, @code{GEMINI} operates at the @code{READ COMMITTED}
|
||||
level. You can override the default using the following command:
|
||||
|
||||
@example
|
||||
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED |
|
||||
READ COMMITTED | REPEATABLE READ | SERIALIZABLE ]
|
||||
@end example
|
||||
|
||||
If the @code{SESSION} qualifier used, the specified isolation level
|
||||
persists for the entire session. If the @code{GLOBAL} qualifier is used,
|
||||
the specified isolation level is applied to all new connections from
|
||||
this point forward. Note that the specified isolation level will not
|
||||
change the behavior for existing connections including the connection
|
||||
that exectues the @code{SET GLOBAL TRANSACTION ISOLATION LEVEL}
|
||||
statement.
|
||||
|
||||
@multitable @columnfractions .30 .70
|
||||
@item @sc{Isolation Level} @tab @sc{Description}
|
||||
|
||||
@item
|
||||
@strong{READ UNCOMMITTED}
|
||||
@tab Does not obtain any locks when reading rows. This means that if a
|
||||
row is locked by another process in a transaction that has a more strict
|
||||
isolation level, the @code{READ UNCOMMITTED} query will not wait until
|
||||
the locks are released before reading the row. You will get an error if
|
||||
attempt any updates while running at this isolation level.
|
||||
|
||||
@item
|
||||
@strong{READ COMMITTED}
|
||||
@tab Locks the requested rows long enough to copy the row from the
|
||||
database block to the client row buffer. If a @code{READ COMMITTED}
|
||||
query finds that a row is locked exclusively by another process, it will
|
||||
wait until either the row has been released, or the lock timeout value
|
||||
has expired.
|
||||
|
||||
@item
|
||||
@strong{REPEATABLE READ}
|
||||
@tab Locks all the rows needed to satisfy the query. These locks are
|
||||
held until the transaction ends (commits or rolls back). If a
|
||||
@code{REPEATABLE READ} query finds that a row is locked exclusively by
|
||||
another process, it will wait until either the row has been released, or
|
||||
the lock timeout value has expired.
|
||||
|
||||
@item
|
||||
@strong{SERIALIZABLE}
|
||||
@tab Locks the table that contains the rows needed to satisfy the
|
||||
query. This lock is held until the transaction ends (commits or rolls
|
||||
back). If a @code{SERIALIZABLE} query finds that a row is exclusively
|
||||
locked by another process, it will wait until either the row has been
|
||||
released, or the lock timeout value has expired.
|
||||
@end multitable
|
||||
|
||||
The statements that get exclusive locks are @code{INSERT},
|
||||
@code{UPDATE}, @code{DELETE} and @code{SELECT ... FOR UPDATE}. Select
|
||||
statements without the @code{FOR UPDATE} qualifier get shared locks
|
||||
which allow other not ''for update'' select statements to read the same
|
||||
rows but block anyone trying to update the row from accessing it. Rows
|
||||
or tables with exclusive locks block all access to the row from other
|
||||
transactions until the transaction ends.
|
||||
|
||||
In general terms, the higher the Isolation level the more likelihood of
|
||||
having concurrent locks and therefore lock conflicts. In such cases,
|
||||
adjust the @code{-O gemini_lock_table_size} accordingly.
|
||||
|
||||
@cindex GEMINI tables, row-level locking
|
||||
@noindent
|
||||
@strong{Row-Level Locking}
|
||||
|
||||
@code{GEMINI} uses row locks, which allows high concurrency for requests
|
||||
on the same table.
|
||||
|
||||
In order to avoid lock table overflow, SQL statements that require
|
||||
applying locks to a large number of rows should either be run at the
|
||||
serializable isolation level or should be covered by a lock table
|
||||
statement.
|
||||
|
||||
Memory must be pre-allocated for the lock table. The mysqld server
|
||||
startup option @code{-0 gemini_lock_table_size} can be used to adjust
|
||||
the number of concurrent locks.
|
||||
|
||||
@cindex GEMINI tables, limitations
|
||||
@node GEMINI Limitations, , GEMINI Concepts, GEMINI Overview
|
||||
@subsubsection GEMINI Limitations
|
||||
|
||||
The following limitations are in effect for the current version of
|
||||
@code{GEMINI}:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
BLOB columns are not supported in @code{GEMINI} tables.
|
||||
@code{DROP DATABASE} does not work with @code{GEMINI} tables; instead,
|
||||
drop all the tables in the database first, then drop the database.
|
||||
|
||||
@item
|
||||
The maximum number of concurrent users accessing @code{GEMINI} tables is
|
||||
limited by @code{gemini_connection_limit}. The default is 100 users.
|
||||
Maximum number of @code{GEMINI} tables is 1012.
|
||||
|
||||
@item
|
||||
Maximum number of @code{GEMINI} files a server can manage is 1012. Each
|
||||
table consumes one file; an additional file is consumed if the table has
|
||||
any indexes defined on it.
|
||||
|
||||
@item
|
||||
Maximum size of BLOBs is 16MB.
|
||||
|
||||
@item
|
||||
@code{FULLTEXT} indexes are not supported with @code{GEMINI} tables.
|
||||
|
||||
@item
|
||||
There is no support for multi-component @code{AUTO_INCREMENT} fields
|
||||
that provide alternating values at the component level. If you try to
|
||||
create such a field, @code{GEMINI} will refuse.
|
||||
|
||||
@item
|
||||
@code{TEMPORARY TABLES} are not supported by @code{GEMINI}. The
|
||||
statement @code{CREATE TEMPORARY TABLE ... TYPE=GEMINI} will generate
|
||||
the response: @code{ERROR 1005: Can't create table '/tmp/#sqlxxxxx'
|
||||
(errno: 0)}.
|
||||
|
||||
@item
|
||||
@code{FLUSH TABLES} has not been implemented with @code{GEMINI} tables.
|
||||
@end itemize
|
||||
|
||||
NuSphere is working on removing these limitations.
|
||||
@cindex GEMINI tables, using
|
||||
@node Using GEMINI Tables, , GEMINI Overview, GEMINI
|
||||
@subsection Using GEMINI Tables
|
||||
|
||||
This section explains the various startup options you can use with
|
||||
@code{GEMINI} tables, how to backup @code{GEMINI} tables, some
|
||||
performance considerations and sample configurations, and a brief
|
||||
discussion of when to use @code{GEMINI} tables.
|
||||
|
||||
Specifically, the topics covered in this section are:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Startup Options
|
||||
@item
|
||||
Creating @code{GEMINI} Tables
|
||||
@item
|
||||
Backing Up @code{GEMINI} Tables
|
||||
@item
|
||||
Using Auto_Increment Columns With @code{GEMINI} Tables
|
||||
@item
|
||||
Performance Considerations
|
||||
@item
|
||||
Sample Configurations
|
||||
@item
|
||||
When To Use @code{GEMINI} Tables
|
||||
@end itemize
|
||||
|
||||
@cindex GEMINI tables, startup options
|
||||
@menu
|
||||
* Startup Options::
|
||||
* Creating GEMINI Tables::
|
||||
* Backing Up GEMINI Tables::
|
||||
* Restoring GEMINI Tables::
|
||||
* Using Auto_Increment Columns With GEMINI Tables::
|
||||
* Performance Considerations::
|
||||
* Sample Configurations::
|
||||
* When To Use GEMINI Tables::
|
||||
@end menu
|
||||
|
||||
@node Startup Options, Creating GEMINI Tables, Using GEMINI Tables, Using GEMINI Tables
|
||||
@subsubsection Startup Options
|
||||
|
||||
The table below lists options to mysqld that can be used to change the
|
||||
behavior of @code{GEMINI} tables.
|
||||
|
||||
@multitable @columnfractions .40 .60
|
||||
@item @sc{Option} @tab @sc{Description}
|
||||
|
||||
@item
|
||||
@code{--default-table-type=gemini}
|
||||
@tab Sets the default table handler to be @code{GEMINI}. All create
|
||||
table statements will create @code{GEMINI} tables unless otherwise
|
||||
specified with @code{TYPE=@var{table-type}}. As noted above, there is
|
||||
currently a limitation with @code{TEMPORARY} tables using @code{GEMINI}.
|
||||
|
||||
@item
|
||||
@code{--gemini-flush-log-at-commit}
|
||||
@tab Forces the recovery log buffers to be flushed after every
|
||||
commit. This can have a serious performance penalty, so use with
|
||||
caution.
|
||||
|
||||
@item
|
||||
@code{--gemini-recovery=FULL | NONE | FORCE}
|
||||
@tab Sets the recovery mode. Default is @code{FULL}. @code{NONE} is
|
||||
useful for performing repeatable batch operations because the updates
|
||||
are not recorded in the recovery log. @code{FORCE} skips crash recovery
|
||||
upon startup; this corrupts the database, and should be used in
|
||||
emergencies only.
|
||||
|
||||
@item
|
||||
@code{--gemini-unbuffered-io}
|
||||
@tab All database writes bypass the OS cache. This can provide a
|
||||
performance boost on heavily updated systems where most of the dataset
|
||||
being worked on is cached in memory with the @code{gemini_buffer_cache}
|
||||
parameter.
|
||||
|
||||
@item
|
||||
@code{--O gemini_buffer_cache=size}
|
||||
@tab Amount of memory to allocate for database buffers, including Index
|
||||
and Record information. It is recommended that this number be 10% of the
|
||||
total size of all @code{GEMINI} tables. Do not exceed amount of memory
|
||||
on the system!
|
||||
|
||||
@item
|
||||
@code{--O gemini_connection_limit=#}
|
||||
@tab Maximum number of connections to @code{GEMINI}; default is
|
||||
@code{100}. Each connection consumes about 1K of memory.
|
||||
|
||||
@item
|
||||
@code{--O gemini_io_threads=#}
|
||||
@tab Number of background I/O threads; default is @code{2}. Increase the
|
||||
number when using @code{--gemini-unbuffered-io}
|
||||
|
||||
@item
|
||||
@code{--O gemini_lock_table_size=#}
|
||||
@tab Sets the maximum number of concurrent locks; default is 4096. Using
|
||||
@code{SET [ GLOBAL | SESSION ] TRANSACTION ISOLATION = ...} will
|
||||
determine how long a program will hold row locks.
|
||||
|
||||
@item
|
||||
@code{--O gemini_lock_wait_timeout=seconds}
|
||||
@tab Number of seconds to wait for record locks when performing queries;
|
||||
default is 10 seconds. Using @code{SET [ GLOBAL | SESSION ] TRANSACTION
|
||||
ISOLATION = ...} will determine how long a program will hold row locks.
|
||||
|
||||
@item
|
||||
@code{--skip-gemini}
|
||||
@tab Do not use @code{GEMINI}. If you use @code{--skip-gemini}, @strong{MySQL}
|
||||
will not initialize the @code{GEMINI} table handler, saving memory; you
|
||||
cannot use @code{GEMINI} tables if you use @code{--skip-gemini}.
|
||||
|
||||
@item
|
||||
@code{--transaction-isolation=READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
|
||||
@tab Sets the GLOBAL transaction isolation level for all users that
|
||||
connect to the server; can be overridden with the SET ISOLATION LEVEL
|
||||
statement.
|
||||
@end multitable
|
||||
|
||||
@cindex GEMINI tables, creating
|
||||
@node Creating GEMINI Tables, Backing Up GEMINI Tables, Startup Options, Using GEMINI Tables
|
||||
@subsubsection Creating GEMINI Tables
|
||||
|
||||
@code{GEMINI} tables can be created by either using the @code{CREATE
|
||||
TABLE} syntax or the @code{ALTER TABLE} syntax.
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
The syntax for creating a @code{GEMINI} table is:
|
||||
|
||||
@example
|
||||
CREATE TABLE @var{table-name} (....) TYPE=GEMINI;
|
||||
@end example
|
||||
|
||||
@item
|
||||
The syntax to convert a table to @code{GEMINI} is:
|
||||
|
||||
@example
|
||||
ALTER TABLE @var{table-name} TYPE=GEMINI;
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
@xref{Tutorial}, for more information on how to create and use
|
||||
@code{MySQL} tables.
|
||||
|
||||
@cindex GEMINI tables, backing up
|
||||
@node Backing Up GEMINI Tables, Restoring GEMINI Tables, Creating GEMINI Tables, Using GEMINI Tables
|
||||
@subsubsection Backing Up GEMINI Tables
|
||||
|
||||
@code{GEMINI} supports both @code{BACKUP TABLE} and @code{RESTORE TABLE}
|
||||
syntax. To learn more about how to use @code{BACKUP} and @code{RESTORE},
|
||||
see @ref{BACKUP TABLE} and @ref{RESTORE TABLE}.
|
||||
|
||||
To backup @code{GEMINI} tables outside of the @code{MySQL} environment,
|
||||
you must first shut down the @code{MySQL} server. Once the server is
|
||||
shut down, you can copy the files associated with @code{GEMINI} to a
|
||||
different location. The files that make up the @code{GEMINI} table
|
||||
handler are:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
All files associated with a table with a @code{.gmd} extention below the
|
||||
@code{$DATADIR} directory. Such files include @code{@var{table}.gmd},
|
||||
@code{@var{table}.gmi}, and @code{@var{table}.frm}
|
||||
@item
|
||||
@code{gemini.db} in the @code{$DATADIR} directory
|
||||
@item
|
||||
@code{gemini.rl} in the @code{$DATADIR} directory
|
||||
@item
|
||||
@code{gemini.lg} in the @code{$DATADIR} directory
|
||||
@end itemize
|
||||
|
||||
All the @code{GEMINI} files must be copied together. You can not copy
|
||||
just the @code{.gmi} and @code{.gmd} files to a different
|
||||
@code{$DATADIR} and have them become part of a new database. You can
|
||||
copy an entire @code{$DATADIR} directory to another location and start a
|
||||
@strong{MySQL} server using the new @code{$DATADIR}.
|
||||
|
||||
@cindex GEMINI tables, restoring
|
||||
@node Restoring GEMINI Tables, Using Auto_Increment Columns With GEMINI Tables, Backing Up GEMINI Tables, Using GEMINI Tables
|
||||
@subsubsection Restoring GEMINI Tables
|
||||
|
||||
To restore @code{GEMINI} tables outside of the @code{MySQL} environment,
|
||||
you must first shut down the @code{MySQL} server. Once the server is
|
||||
shut down, you can remove all @code{GEMINI} files in the target
|
||||
@code{$DATADIR} and then copy the files previously backed up into the
|
||||
@code{$DATADIR} directory.
|
||||
|
||||
As mentioned above, the files that make up the @code{GEMINI} table
|
||||
handler are:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
All files associated with a table with a @code{.gmd} extention below the
|
||||
@code{$DATADIR} directory. Such files include @code{@var{table}.gmd},
|
||||
@code{@var{table}.gmi}, and @code{@var{table}.frm}
|
||||
@item
|
||||
@code{gemini.db} in the @code{$DATADIR} directory
|
||||
@item
|
||||
@code{gemini.rl} in the @code{$DATADIR} directory
|
||||
@item
|
||||
@code{gemini.lg} in the @code{$DATADIR} directory
|
||||
@end itemize
|
||||
|
||||
When restoring a table, all the @code{GEMINI} files must be copied
|
||||
together. You can not restore just the @code{.gmi} and @code{.gmd}
|
||||
files.
|
||||
|
||||
@cindex GEMINI tables, auto_increment
|
||||
@node Using Auto_Increment Columns With GEMINI Tables, Performance Considerations, Restoring GEMINI Tables, Using GEMINI Tables
|
||||
@subsubsection Using Auto_Increment Columns With GEMINI Tables
|
||||
|
||||
As mentioned previously, @code{GEMINI} tables support row-level and
|
||||
table-level locking to increase concurrency in applications and to allow
|
||||
reading of tables without locking for maximum concurrency in heavy
|
||||
update environments. This feature has several implications when working
|
||||
with @code{auto_increment} tables.
|
||||
|
||||
In @code{MySQL}, when a column is defined as an @code{auto_increment}
|
||||
column, and a row is inserted into the table with a @code{NULL} for the
|
||||
column, the @code{auto_increment} column is updated to be 1 higher than
|
||||
the highest value in the column.
|
||||
|
||||
With @code{MyISAM} tables, the @code{auto_increment} function is
|
||||
implemented by looking in the index and finding the highest value and
|
||||
adding 1 to it. This is possible because the entire @code{ISAM} table is
|
||||
locked during the update period and the increment value is therefore
|
||||
guaranteed to not be changing.
|
||||
|
||||
With @code{GEMINI} tables, the @code{auto_increment} function is
|
||||
implemented by maintaining a counter in a separate location from the
|
||||
table data. Instead of looking at the highest value in the table index,
|
||||
@code{GEMINI} tables look at this separately maintained counter. This
|
||||
means that in a transactional model, unlike the bottleneck inherent in
|
||||
the @code{MyISAM} approach, @code{GEMINI} users do @b{not} have to wait
|
||||
until the transaction that added the last value either commits or
|
||||
rollbacks before looking at the value.
|
||||
|
||||
Two side-effects of the @code{GEMINI} implementation are:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
If an insert is done where the column with the @code{auto_increment} is
|
||||
specified, and this specified value is the highest value, @code{MyISAM}
|
||||
uses it as its @code{auto_increment} value, and every subsequent insert
|
||||
is based on this. By contrast, @code{GEMINI} does not use this value,
|
||||
but instead uses the value maintained in the separate @code{GEMINI}
|
||||
counter location.
|
||||
|
||||
@item
|
||||
To set the counter to a specific value, you can use @code{SET
|
||||
insert_id=#} and insert a new row in the table. However, as a general
|
||||
rule, values should not be inserted into an @code{auto_increment}
|
||||
column; the database manager should be maintaining this field, not the
|
||||
application. @code{SET insert_id} is a recovery mechanism that should be
|
||||
used in case of error only.
|
||||
@end itemize
|
||||
|
||||
Note that if you delete the row containing the maximum value for an
|
||||
@code{auto_increment} column, the value will be reused with a
|
||||
@code{GEMINI} table but not with a @code{MyISAM} table.
|
||||
|
||||
See @ref{CREATE TABLE} for more information about creating
|
||||
@code{auto_increment} columns.
|
||||
|
||||
@cindex GEMINI tables, peformance considerations
|
||||
@node Performance Considerations, Sample Configurations, Using Auto_Increment Columns With GEMINI Tables, Using GEMINI Tables
|
||||
@subsubsection Performance Considerations
|
||||
|
||||
In addition to designing the best possible application, configuration of
|
||||
the data and the server startup parameters need to be considered. How
|
||||
the hardware is being used can have a dramatic affect on how fast the
|
||||
system will respond to queries. Disk Drives and Memory must both be
|
||||
considered.
|
||||
|
||||
@noindent
|
||||
@strong{Disk Drives}
|
||||
|
||||
For best performance, you want to spread the data out over as many disks
|
||||
as possible. Using RAID 10 stripes work very well. If there are a lot of
|
||||
updates then the recovery log (@code{gemini.rl}) should be on a
|
||||
relatively quiet disk drive.
|
||||
|
||||
To spread the data out without using RAID 10, you can do the following:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Group all the tables into three categories: Heavy Use, Moderate Use,
|
||||
Light Use.
|
||||
|
||||
@item
|
||||
Take the number of disk drives available and use a round-robin approach
|
||||
to the three categories grouping the tables on a disk drive. The result
|
||||
will be an equal distribution of Heavy/Moderate/Light tables assigned to
|
||||
each disk drive.
|
||||
|
||||
@item
|
||||
Once the tables have been converted to @code{GEMINI} by using the
|
||||
@code{ALTER TABLE <name> TYPE=GEMINI} statements, move (@code{mv}) the
|
||||
@code{.gmd} and @code{.gmi} files to a different disk drive and link
|
||||
(@code{ln -s}) them back to the original directory where the @code{.frm}
|
||||
file resides.
|
||||
|
||||
@item
|
||||
Finally, move the @code{gemini.rl} file to its quiet disk location and link
|
||||
the file back to the @code{$DATADIR} directory.
|
||||
@end itemize
|
||||
|
||||
@noindent
|
||||
@strong{Memory}
|
||||
|
||||
The more data that can be placed in memory the faster the access to the
|
||||
data. Figure out how large the @code{GEMINI} data is by adding up the
|
||||
@code{.gmd} and @code{.gmi} file sizes. If you can, put at least 10% of
|
||||
the data into memory. You allocate memory for the rows and indexes by
|
||||
using the @code{gemini_buffer_cache} startup parameter. For example:
|
||||
|
||||
@example
|
||||
mysqld -O gemini_buffer_cache=800M
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
would allocate 800 MB of memory for the @code{GEMINI} buffer cache.
|
||||
|
||||
@cindex GEMINI tables, sample configurations
|
||||
@node Sample Configurations, When To Use GEMINI Tables, Performance Considerations, Using GEMINI Tables
|
||||
@subsubsection Sample Configurations
|
||||
|
||||
Based on the performance considerations above, we can look at some
|
||||
examples for how to get the best performance out of the system when
|
||||
using @code{GEMINI} tables.
|
||||
|
||||
@multitable @columnfractions .30 .70
|
||||
@item @sc{Hardware} @tab @sc{Configuration}
|
||||
@item
|
||||
One CPU, 128MB memory, one disk drive
|
||||
@tab Allocate 80MB of memory for reading and updating @code{GEMINI}
|
||||
tables by starting the mysqld server with the following option:
|
||||
|
||||
@example
|
||||
-O gemini_buffer_cache=80M
|
||||
@end example
|
||||
|
||||
@item
|
||||
Two CPUs, 512MB memory, four disk drives
|
||||
@tab Use RAID 10 to stripe the data across all available disks, or use
|
||||
the method described in the performance considerations section,
|
||||
above. Allocate 450MB of memory for reading/updating @code{GEMINI}
|
||||
tables:
|
||||
|
||||
@example
|
||||
-O gemini_buffer_cache=450M
|
||||
@end example
|
||||
@end multitable
|
||||
|
||||
@cindex GEMINI tables, when to use
|
||||
@node When To Use GEMINI Tables, , Sample Configurations, Using GEMINI Tables
|
||||
@subsubsection When To Use GEMINI Tables
|
||||
|
||||
Because the @code{GEMINI} table handler provides crash recovery and
|
||||
transaction support, there is extra overhead that is not found in other
|
||||
non-transaction safe table handlers. Here are some general guidelines
|
||||
for when to employ @code{GEMINI} and when to use other non-transaction
|
||||
safe tables (@code{NTST}).
|
||||
|
||||
@multitable @columnfractions .30 .25 .45
|
||||
@item
|
||||
@sc{Access Trends} @tab @sc{Table Type} @tab @sc{Reason}
|
||||
@item
|
||||
Read-only
|
||||
@tab @code{NTST}
|
||||
@tab Less overhead and faster
|
||||
@item
|
||||
Critical data
|
||||
@tab @code{GEMINI}
|
||||
@tab Crash recovery protection
|
||||
@item
|
||||
High concurrency
|
||||
@tab @code{GEMINI}
|
||||
@tab Row-level locking
|
||||
@item
|
||||
Heavy update
|
||||
@tab @code{GEMINI}
|
||||
@tab Row-level locking
|
||||
@end multitable
|
||||
|
||||
The table below shows how a typical application schema could be defined.
|
||||
|
||||
@multitable @columnfractions .15 .30 .25 .30
|
||||
@item
|
||||
@sc{Table} @tab @sc{Contents} @tab @sc{Table Type} @tab @sc{Reason}
|
||||
@item
|
||||
account
|
||||
@tab Customer account data
|
||||
@tab @code{GEMINI}
|
||||
@tab Critical data, heavy update
|
||||
@item
|
||||
order
|
||||
@tab Orders for a customer
|
||||
@tab @code{GEMINI}
|
||||
@tab Critical data, heavy update
|
||||
@item
|
||||
orderline
|
||||
@tab Orderline detail for an order
|
||||
@tab @code{GEMINI}
|
||||
@tab Critical data, heavy update
|
||||
@item
|
||||
invdesc
|
||||
@tab Inventory description
|
||||
@tab @code{NTST}
|
||||
@tab Read-only, frequent access
|
||||
@item
|
||||
salesrep
|
||||
@tab Sales rep information
|
||||
@tab @code{NTST}
|
||||
@tab Infrequent update
|
||||
@item
|
||||
inventory
|
||||
@tab Inventory information
|
||||
@tab @code{GEMINI}
|
||||
@tab High concurrency, critical data
|
||||
@item
|
||||
config
|
||||
@tab System configuration
|
||||
@tab @code{NTST}
|
||||
@tab Read-only
|
||||
@end multitable
|
||||
|
||||
@node InnoDB, , GEMINI, Table types
|
||||
@section InnoDB Tables
|
||||
|
@ -999,10 +999,10 @@ dnl echo "DBG_GEM1: gemini='$gemini'"
|
||||
gemini_includes=
|
||||
gemini_libs=
|
||||
case "$gemini" in
|
||||
no | default | *)
|
||||
no)
|
||||
AC_MSG_RESULT([Not using Gemini DB])
|
||||
;;
|
||||
yes )
|
||||
yes | default | *)
|
||||
have_gemini_db="yes"
|
||||
gemini_includes="-I../gemini/incl -I../gemini"
|
||||
gemini_libs="\
|
||||
|
11
configure.in
11
configure.in
@ -2018,6 +2018,17 @@ EOF
|
||||
echo "END OF INNODB CONFIGURATION"
|
||||
fi
|
||||
|
||||
if test "X$have_gemini_db" = "Xyes"; then
|
||||
sql_server_dirs="gemini $sql_server_dirs"
|
||||
echo "CONFIGURING FOR GEMINI DB"
|
||||
(cd gemini && sh ./configure) \
|
||||
|| AC_MSG_ERROR([could not configure Gemini DB])
|
||||
|
||||
echo "END OF GEMINI DB CONFIGURATION"
|
||||
|
||||
AC_DEFINE(HAVE_GEMINI_DB)
|
||||
fi
|
||||
|
||||
if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
|
||||
then
|
||||
# MIT user level threads
|
||||
|
@ -213,6 +213,7 @@ enum ha_base_keytype {
|
||||
#define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */
|
||||
#define HA_ERR_LOCK_WAIT_TIMEOUT 146
|
||||
#define HA_ERR_LOCK_TABLE_FULL 147
|
||||
#define HA_ERR_READ_ONLY_TRANSACTION 148 /* Updates not allowed */
|
||||
|
||||
/* Other constants */
|
||||
|
||||
|
@ -205,4 +205,7 @@
|
||||
#define ER_SLAVE_THREAD 1202
|
||||
#define ER_TOO_MANY_USER_CONNECTIONS 1203
|
||||
#define ER_SET_CONSTANTS_ONLY 1204
|
||||
#define ER_ERROR_MESSAGES 205
|
||||
#define ER_LOCK_WAIT_TIMEOUT 1205
|
||||
#define ER_LOCK_TABLE_FULL 1206
|
||||
#define ER_READ_ONLY_TRANSACTION 1207
|
||||
#define ER_ERROR_MESSAGES 208
|
||||
|
53
sql/field.cc
53
sql/field.cc
@ -4087,6 +4087,59 @@ const char *Field_blob::unpack(char *to, const char *from)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_GEMINI_DB
|
||||
/* Blobs in Gemini tables are stored separately from the rows which contain
|
||||
** them (except for tiny blobs, which are stored in the row). For all other
|
||||
** blob types (blob, mediumblob, longblob), the row contains the length of
|
||||
** the blob data and a blob id. These methods (pack_id, get_id, and
|
||||
** unpack_id) handle packing and unpacking blob fields in Gemini rows.
|
||||
*/
|
||||
char *Field_blob::pack_id(char *to, const char *from, ulonglong id, uint max_length)
|
||||
{
|
||||
char *save=ptr;
|
||||
ptr=(char*) from;
|
||||
ulong length=get_length(); // Length of from string
|
||||
if (length > max_length)
|
||||
{
|
||||
ptr=to;
|
||||
length=max_length;
|
||||
store_length(length); // Store max length
|
||||
ptr=(char*) from;
|
||||
}
|
||||
else
|
||||
memcpy(to,from,packlength); // Copy length
|
||||
if (length)
|
||||
{
|
||||
int8store(to+packlength, id);
|
||||
}
|
||||
ptr=save; // Restore org row pointer
|
||||
return to+packlength+sizeof(id);
|
||||
}
|
||||
|
||||
|
||||
ulonglong Field_blob::get_id(const char *from)
|
||||
{
|
||||
ulonglong id = 0;
|
||||
ulong length=get_length(from);
|
||||
if (length)
|
||||
longlongget(id, from+packlength);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
const char *Field_blob::unpack_id(char *to, const char *from, const char *bdata)
|
||||
{
|
||||
memcpy(to,from,packlength);
|
||||
ulong length=get_length(from);
|
||||
from+=packlength;
|
||||
if (length)
|
||||
memcpy_fixed(to+packlength, &bdata, sizeof(bdata));
|
||||
else
|
||||
bzero(to+packlength,sizeof(bdata));
|
||||
return from+sizeof(ulonglong);
|
||||
}
|
||||
#endif /* HAVE_GEMINI_DB */
|
||||
|
||||
/* Keys for blobs are like keys on varchars */
|
||||
|
||||
int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
|
||||
|
@ -869,6 +869,13 @@ public:
|
||||
}
|
||||
char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
|
||||
const char *unpack(char *to, const char *from);
|
||||
#ifdef HAVE_GEMINI_DB
|
||||
char *pack_id(char *to, const char *from, ulonglong id,
|
||||
uint max_length= ~(uint) 0);
|
||||
ulonglong get_id(const char *from);
|
||||
const char *unpack_id(char *to, const char *from, const char *bdata);
|
||||
enum_field_types blobtype() { return (packlength == 1 ? FIELD_TYPE_TINY_BLOB : FIELD_TYPE_BLOB);}
|
||||
#endif
|
||||
char *pack_key(char *to, const char *from, uint max_length);
|
||||
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
|
||||
int pack_cmp(const char *a, const char *b, uint key_length);
|
||||
|
1368
sql/ha_gemini.cc
1368
sql/ha_gemini.cc
File diff suppressed because it is too large
Load Diff
@ -19,17 +19,26 @@
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
#include "gem_global.h"
|
||||
#include "dstd.h"
|
||||
#include "dsmpub.h"
|
||||
|
||||
/* class for the the gemini handler */
|
||||
|
||||
enum enum_key_string_options{KEY_CREATE,KEY_DELETE,KEY_CHECK};
|
||||
typedef struct st_gemini_share {
|
||||
ha_rows *rec_per_key;
|
||||
THR_LOCK lock;
|
||||
pthread_mutex_t mutex;
|
||||
char *table_name;
|
||||
uint table_name_length,use_count;
|
||||
} GEM_SHARE;
|
||||
|
||||
#define READ_UNCOMMITED 0
|
||||
#define READ_COMMITED 1
|
||||
#define REPEATABLE_READ 2
|
||||
#define SERIALIZEABLE 3
|
||||
typedef struct gemBlobDesc
|
||||
{
|
||||
dsmBlobId_t blobId;
|
||||
dsmBuffer_t *pBlob;
|
||||
} gemBlobDesc_t;
|
||||
|
||||
class ha_gemini: public handler
|
||||
{
|
||||
@ -38,7 +47,7 @@ class ha_gemini: public handler
|
||||
uint int_option_flag;
|
||||
int tableNumber;
|
||||
dsmIndex_t *pindexNumbers; // dsm object numbers for the indexes on this table
|
||||
unsigned long lastRowid;
|
||||
dsmRecid_t lastRowid;
|
||||
uint last_dup_key;
|
||||
bool fixed_length_row, key_read, using_ignore;
|
||||
byte *rec_buff;
|
||||
@ -46,10 +55,12 @@ class ha_gemini: public handler
|
||||
dsmKey_t *pbracketLimit;
|
||||
dsmKey_t *pfoundKey;
|
||||
dsmMask_t tableStatus; // Crashed/repair status
|
||||
gemBlobDesc_t *pBlobDescs;
|
||||
|
||||
int index_open(char *tableName);
|
||||
int pack_row(byte **prow, int *ppackedLength, const byte *record);
|
||||
void unpack_row(char *record, char *prow);
|
||||
int pack_row(byte **prow, int *ppackedLength, const byte *record,
|
||||
bool update);
|
||||
int unpack_row(char *record, char *prow);
|
||||
int findRow(THD *thd, dsmMask_t findMode, byte *buf);
|
||||
int fetch_row(void *gemini_context, const byte *buf);
|
||||
int handleIndexEntries(const byte * record, dsmRecid_t recid,
|
||||
@ -70,24 +81,28 @@ class ha_gemini: public handler
|
||||
void unpack_key(char *record, dsmKey_t *key, uint index);
|
||||
|
||||
int key_cmp(uint keynr, const byte * old_row,
|
||||
const byte * new_row);
|
||||
const byte * new_row, bool updateStats);
|
||||
|
||||
int saveKeyStats(THD *thd);
|
||||
void get_index_stats(THD *thd);
|
||||
|
||||
short cursorId; /* cursorId of active index cursor if any */
|
||||
dsmMask_t lockMode; /* Shared or exclusive */
|
||||
|
||||
/* FIXFIX Don't know why we need this because I don't know what
|
||||
store_lock method does but we core dump without this */
|
||||
THR_LOCK alock;
|
||||
THR_LOCK_DATA lock;
|
||||
GEM_SHARE *share;
|
||||
|
||||
public:
|
||||
ha_gemini(TABLE *table): handler(table), file(0),
|
||||
int_option_flag(HA_READ_NEXT | HA_READ_PREV |
|
||||
HA_REC_NOT_IN_SEQ |
|
||||
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
|
||||
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
|
||||
HA_NO_BLOBS | HA_NO_TEMP_TABLES |
|
||||
/* HA_BLOB_KEY | */ /*HA_NOT_EXACT_COUNT | */
|
||||
HA_BLOB_KEY |
|
||||
HA_NO_TEMP_TABLES | HA_NO_FULLTEXT_KEY |
|
||||
/*HA_NOT_EXACT_COUNT | */
|
||||
/*HA_KEY_READ_WRONG_STR |*/ HA_DROP_BEFORE_CREATE),
|
||||
pbracketBase(0),pbracketLimit(0),pfoundKey(0),
|
||||
cursorId(0)
|
||||
@ -100,7 +115,7 @@ class ha_gemini: public handler
|
||||
uint max_record_length() const { return MAXRECSZ; }
|
||||
uint max_keys() const { return MAX_KEY-1; }
|
||||
uint max_key_parts() const { return MAX_REF_PARTS; }
|
||||
uint max_key_length() const { return MAXKEYSZ; }
|
||||
uint max_key_length() const { return MAXKEYSZ / 2; }
|
||||
bool fast_key_read() { return 1;}
|
||||
bool has_transactions() { return 1;}
|
||||
|
||||
@ -129,8 +144,12 @@ class ha_gemini: public handler
|
||||
void info(uint);
|
||||
int extra(enum ha_extra_function operation);
|
||||
int reset(void);
|
||||
int analyze(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int check(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int repair(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int restore(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int backup(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
virtual longlong get_auto_increment();
|
||||
void position(byte *record);
|
||||
@ -139,7 +158,7 @@ class ha_gemini: public handler
|
||||
enum ha_rkey_function start_search_flag,
|
||||
const byte *end_key,uint end_key_len,
|
||||
enum ha_rkey_function end_search_flag);
|
||||
|
||||
void update_create_info(HA_CREATE_INFO *create_info);
|
||||
int create(const char *name, register TABLE *form,
|
||||
HA_CREATE_INFO *create_info);
|
||||
int delete_table(const char *name);
|
||||
@ -167,6 +186,7 @@ extern long gemini_locktablesize;
|
||||
extern long gemini_lock_wait_timeout;
|
||||
extern long gemini_spin_retries;
|
||||
extern long gemini_connection_limit;
|
||||
extern char *gemini_basedir;
|
||||
extern TYPELIB gemini_recovery_typelib;
|
||||
extern ulong gemini_recovery_options;
|
||||
|
||||
@ -175,12 +195,13 @@ bool gemini_end(void);
|
||||
bool gemini_flush_logs(void);
|
||||
int gemini_commit(THD *thd);
|
||||
int gemini_rollback(THD *thd);
|
||||
int gemini_recovery_logging(THD *thd, bool on);
|
||||
void gemini_disconnect(THD *thd);
|
||||
int gemini_rollback_to_savepoint(THD *thd);
|
||||
int gemini_parse_table_name(const char *fullname, char *dbname, char *tabname);
|
||||
int gemini_is_vst(const char *pname);
|
||||
int gemini_set_option_long(int optid, long optval);
|
||||
|
||||
const int gemini_blocksize = 8192;
|
||||
const int gemini_recbits = 7;
|
||||
const int gemini_blocksize = BLKSIZE;
|
||||
const int gemini_recbits = DEFAULT_RECBITS;
|
||||
|
||||
|
@ -694,6 +694,15 @@ void handler::print_error(int error, myf errflag)
|
||||
case HA_ERR_RECORD_FILE_FULL:
|
||||
textno=ER_RECORD_FILE_FULL;
|
||||
break;
|
||||
case HA_ERR_LOCK_WAIT_TIMEOUT:
|
||||
textno=ER_LOCK_WAIT_TIMEOUT;
|
||||
break;
|
||||
case HA_ERR_LOCK_TABLE_FULL:
|
||||
textno=ER_LOCK_TABLE_FULL;
|
||||
break;
|
||||
case HA_ERR_READ_ONLY_TRANSACTION:
|
||||
textno=ER_READ_ONLY_TRANSACTION;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
my_error(ER_GET_ERRNO,errflag,error);
|
||||
@ -757,6 +766,25 @@ int ha_commit_rename(THD *thd)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Tell the handler to turn on or off logging to the handler's
|
||||
recovery log
|
||||
*/
|
||||
int ha_recovery_logging(THD *thd, bool on)
|
||||
{
|
||||
int error=0;
|
||||
|
||||
DBUG_ENTER("ha_recovery_logging");
|
||||
#ifdef USING_TRANSACTIONS
|
||||
if (opt_using_transactions)
|
||||
{
|
||||
#ifdef HAVE_GEMINI_DB
|
||||
error = gemini_recovery_logging(thd, on);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int handler::index_next_same(byte *buf, const byte *key, uint keylen)
|
||||
{
|
||||
int error;
|
||||
|
@ -74,6 +74,7 @@
|
||||
#define HA_NOT_DELETE_WITH_CACHE (HA_NOT_READ_AFTER_KEY*2)
|
||||
#define HA_NO_TEMP_TABLES (HA_NOT_DELETE_WITH_CACHE*2)
|
||||
#define HA_NO_PREFIX_CHAR_KEYS (HA_NO_TEMP_TABLES*2)
|
||||
#define HA_NO_FULLTEXT_KEY (HA_NO_PREFIX_CHAR_KEYS*2)
|
||||
|
||||
/* Parameters for open() (in register form->filestat) */
|
||||
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
|
||||
@ -353,3 +354,4 @@ int ha_autocommit_or_rollback(THD *thd, int error);
|
||||
void ha_set_spin_retries(uint retries);
|
||||
bool ha_flush_logs(void);
|
||||
int ha_commit_rename(THD *thd);
|
||||
int ha_recovery_logging(THD *thd, bool on);
|
||||
|
26
sql/lock.cc
26
sql/lock.cc
@ -35,6 +35,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
|
||||
bool unlock, TABLE **write_locked);
|
||||
static int lock_external(TABLE **table,uint count);
|
||||
static int unlock_external(THD *thd, TABLE **table,uint count);
|
||||
static void print_lock_error(int error);
|
||||
|
||||
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
|
||||
@ -154,7 +155,7 @@ static int lock_external(TABLE **tables,uint count)
|
||||
(*tables)->file->external_lock(thd, F_UNLCK);
|
||||
(*tables)->current_lock=F_UNLCK;
|
||||
}
|
||||
my_error(ER_CANT_LOCK,MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG),error);
|
||||
print_lock_error(error);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
else
|
||||
@ -325,7 +326,7 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
|
||||
}
|
||||
}
|
||||
if (error_code)
|
||||
my_error(ER_CANT_LOCK,MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG),error_code);
|
||||
print_lock_error(error_code);
|
||||
DBUG_RETURN(error_code);
|
||||
}
|
||||
|
||||
@ -480,3 +481,24 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
|
||||
}
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
static void print_lock_error(int error)
|
||||
{
|
||||
int textno;
|
||||
DBUG_ENTER("print_lock_error");
|
||||
|
||||
switch (error) {
|
||||
case HA_ERR_LOCK_WAIT_TIMEOUT:
|
||||
textno=ER_LOCK_WAIT_TIMEOUT;
|
||||
break;
|
||||
case HA_ERR_READ_ONLY_TRANSACTION:
|
||||
textno=ER_READ_ONLY_TRANSACTION;
|
||||
break;
|
||||
default:
|
||||
textno=ER_CANT_LOCK;
|
||||
break;
|
||||
}
|
||||
my_error(textno,MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG),error);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -215,3 +215,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -209,3 +209,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -210,3 +210,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -209,3 +209,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -208,3 +208,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -208,3 +208,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -208,3 +208,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -208,3 +208,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -210,3 +210,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -210,3 +210,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -209,3 +209,6 @@
|
||||
"îÅ ÍÏÇÕ ÓÏÚÄÁÔØ ÐÒÏÃÅÓÓ SLAVE, ÐÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -214,3 +214,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -207,3 +207,6 @@
|
||||
"Could not create slave thread, check system resources",
|
||||
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||
"You may only use constant expressions with SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -206,3 +206,6 @@
|
||||
"Kunde inte starta en tråd för replikering",
|
||||
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
|
||||
"Du kan endast använda konstant-uttryck med SET",
|
||||
"Lock wait timeout exceeded",
|
||||
"The total number of locks exceeds the lock table size",
|
||||
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
|
||||
|
@ -1388,11 +1388,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
bool refresh;
|
||||
DBUG_ENTER("open_ltable");
|
||||
|
||||
#ifdef __WIN__
|
||||
/* Win32 can't drop a file that is open */
|
||||
if (lock_type == TL_WRITE_ALLOW_READ)
|
||||
lock_type= TL_WRITE;
|
||||
#endif
|
||||
thd->proc_info="Opening table";
|
||||
while (!(table=open_table(thd,table_list->db ? table_list->db : thd->db,
|
||||
table_list->real_name,table_list->name,
|
||||
@ -1400,6 +1395,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
if (table)
|
||||
{
|
||||
int error;
|
||||
|
||||
#ifdef __WIN__
|
||||
/* Win32 can't drop a file that is open */
|
||||
if (lock_type == TL_WRITE_ALLOW_READ
|
||||
#ifdef HAVE_GEMINI_DB
|
||||
&& table->db_type != DB_TYPE_GEMINI
|
||||
#endif /* HAVE_GEMINI_DB */
|
||||
)
|
||||
{
|
||||
lock_type= TL_WRITE;
|
||||
}
|
||||
#endif /* __WIN__ */
|
||||
|
||||
table_list->table=table;
|
||||
table->grant= table_list->grant;
|
||||
if (thd->locked_tables)
|
||||
|
@ -423,6 +423,13 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
column->field_name);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (key->type == Key::FULLTEXT &&
|
||||
(file->option_flag() & HA_NO_FULLTEXT_KEY))
|
||||
{
|
||||
my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
|
||||
column->field_name);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (f_is_blob(sql_field->pack_flag))
|
||||
{
|
||||
if (!(file->option_flag() & HA_BLOB_KEY))
|
||||
@ -1678,6 +1685,16 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
goto err;
|
||||
};
|
||||
|
||||
/* Turn off recovery logging since rollback of an
|
||||
alter table is to delete the new table so there
|
||||
is no need to log the changes to it. */
|
||||
error = ha_recovery_logging(thd,false);
|
||||
if(error)
|
||||
{
|
||||
error = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
|
||||
if (handle_duplicates == DUP_IGNORE ||
|
||||
handle_duplicates == DUP_REPLACE)
|
||||
@ -1723,6 +1740,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
if (to->file->activate_all_index(thd))
|
||||
error=1;
|
||||
|
||||
tmp_error = ha_recovery_logging(thd,true);
|
||||
/*
|
||||
Ensure that the new table is saved properly to disk so that we
|
||||
can do a rename
|
||||
@ -1734,6 +1752,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
if (to->file->external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
err:
|
||||
tmp_error = ha_recovery_logging(thd,true);
|
||||
free_io_cache(from);
|
||||
*copied= found_count;
|
||||
*deleted=delete_count;
|
||||
|
Loading…
x
Reference in New Issue
Block a user