📄 ndb.hpp
字号:
NdbTransaction::execute() also must be called before any locks are released; see @ref secScanLocks for more information. <h4>Features Specific to Index Scans</h4> When performing an index scan, it is possible to scan only a subset of a table using @ref NdbIndexScanOperation::setBound(). In addition, result sets can be sorted in either ascending or descending order, using @ref NdbIndexScanOperation::readTuples(). Note that rows are returned unordered by default, that is, unless <var>sorted</var> is set to <b>true</b>. It is also important to note that, when using NdbIndexScanOperation::BoundEQ on a partition key, only fragments containing rows will actually be scanned. @note When performing a sorted scan, any value passed as the NdbIndexScanOperation::readTuples() method's <code>parallel</code> argument will be ignored and maximum parallelism will be used instead. In other words, all fragments which it is possible to scan will be scanned simultaneously and in parallel in such cases. @subsection secScanLocks Lock handling with scans Performing scans on either a tables or an index has the potential return a great many records; however, Ndb will lock only a predetermined number of rows per fragment at a time. How many rows will be locked per fragment is controlled by the <var>batch</var> parameter passed to NdbScanOperation::readTuples(). In order to allow the application to handle how locks are released, NdbScanOperation::nextResult() has a Boolean parameter <var>fetch_allow</var>. If NdbScanOperation::nextResult() is called with <var>fetch_allow</var> equal to <b>false</b>, then no locks may be released as result of the function call. Otherwise the locks for the current batch may be released. This next example shows a scan delete that handle locks in an efficient manner. For the sake of brevity, we omit error-handling. @code int check; // Outer loop for each batch of rows while((check = MyScanOperation->nextResult(true)) == 0) { do { // Inner loop for each row within batch MyScanOperation->deleteCurrentTuple(); } while((check = MyScanOperation->nextResult(false)) == 0); // When no more rows in batch, exeute all defined deletes MyTransaction->execute(NoCommit); } @endcode See @ref ndbapi_scan.cpp for a more complete example of a scan. @section secError Error Handling Errors can occur either when operations making up a transaction are being defined, or when the transaction is actually being executed. Catching and handling either sort of error requires testing the value returned by NdbTransaction::execute(), and then, if an error is indicated (that is, if this value is equal to -1), using the following two methods in order to identify the error's type and location: - NdbTransaction::getNdbErrorOperation() returns a reference to the operation causing the most recent error. - NdbTransaction::getNdbErrorLine() yields the method number of the erroneous method in the operation. This short example illustrates how to detect an error and to use these two methods to identify it: @code theTransaction = theNdb->startTransaction(); theOperation = theTransaction->getNdbOperation("TEST_TABLE"); if (theOperation == NULL) goto error; theOperation->readTuple(NdbOperation::LM_Read); theOperation->setValue("ATTR_1", at1); theOperation->setValue("ATTR_2", at1); // Error occurs here theOperation->setValue("ATTR_3", at1); theOperation->setValue("ATTR_4", at1); if (theTransaction->execute(Commit) == -1) { errorLine = theTransaction->getNdbErrorLine(); errorOperation = theTransaction->getNdbErrorOperation(); } @endcode Here <code>errorLine</code> will be 3, as the error occurred in the third method called on the NdbOperation object (in this case, <code>theOperation</code>); if the result of NdbTransaction::getNdbErrorLine() is 0, this means that the error occurred when the operations were executed. In this example, <code>errorOperation</code> will be a pointer to the <code>theOperation</code> object. The NdbTransaction::getNdbError() method returns an NdbError object providing information about the error. @note Transactions are <b>not</b> automatically closed when an error occurs. Call Ndb::closeTransaction() to close the transaction. One recommended way to handle a transaction failure (i.e. an error is reported) is to: -# Rollback transaction (call NdbTransaction::execute() with a special parameter) -# Close transaction (call NdbTransaction::closeTransaction()) -# If the error was temporary, attempt to restart the transaction Several errors can occur when a transaction contains multiple operations which are simultaneously executed. In this case the application has to go through all operations and query their NdbError objects to find out what really happened. It is also important to note that errors can occur even when a commit is reported as successful. In order to handle such situations, the NDB API provides an additional NdbTransaction::commitStatus() method to check the transactions's commit status.******************************************************************************//** * @page ndbapi_simple.cpp ndbapi_simple.cpp * @include ndbapi_simple.cpp */#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL/** * @page ndbapi_async.cpp ndbapi_async.cpp * @include ndbapi_async.cpp *//** * @page ndbapi_async1.cpp ndbapi_async1.cpp * @include ndbapi_async1.cpp */#endif/** * @page ndbapi_retries.cpp ndbapi_retries.cpp * @include ndbapi_retries.cpp *//** * @page ndbapi_simple_index.cpp ndbapi_simple_index.cpp * @include ndbapi_simple_index.cpp *//** * @page ndbapi_scan.cpp ndbapi_scan.cpp * @include ndbapi_scan.cpp *//** * @page ndbapi_event.cpp ndbapi_event.cpp * @include ndbapi_event.cpp *//** @page secAdapt Adaptive Send Algorithm At the time of "sending" a transaction (using NdbTransaction::execute()), the transactions are in reality <em>not</em> immediately transfered to the NDB Kernel. Instead, the "sent" transactions are only kept in a special send list (buffer) in the Ndb object to which they belong. The adaptive send algorithm decides when transactions should actually be transferred to the NDB kernel. The NDB API is designed as a multi-threaded interface and so it is often desirable to transfer database operations from more than one thread at a time. The NDB API keeps track of which Ndb objects are active in transferring information to the NDB kernel and the expected amount of threads to interact with the NDB kernel. Note that a given instance of Ndb should be used in at most one thread; different threads should <em>not</em> use the same Ndb object. There are four conditions leading to the transfer of database operations from Ndb object buffers to the NDB kernel: -# The NDB Transporter (TCP/IP, OSE, SCI or shared memory) decides that a buffer is full and sends it off. The buffer size is implementation-dependent and may change between MySQL Cluster releases. On TCP/IP the buffer size is usually around 64 KB; on OSE/Delta it is usually less than 2000 bytes. Since each Ndb object provides a single buffer per storage node, the notion of a "full" buffer is local to this storage node. -# The accumulation of statistical data on transferred information may force sending of buffers to all storage nodes. -# Every 10 ms, a special transmission thread checks whether or not any send activity has occurred. If not, then the thread will force transmission to all nodes. This means that 20 ms is the maximum time database operations are kept waiting before being sent off. The 10-millisecond limit is likely to become a configuration parameter in future releases of MySQL Cluster; however, for checks that are more frequent than each 10 ms, additional support from the operating system is required. -# For methods that are affected by the adaptive send alorithm (such as NdbTransaction::execute()), there is a <var>force</var> parameter that overrides its default behaviour in this regard and forces immediate transmission to all nodes. See the inidvidual NDB API class listings for more information. @note The conditions listed above are subject to change in future releases of MySQL Cluster.*/#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL/** For each of these "sent" transactions, there are three possible states: -# Waiting to be transferred to NDB Kernel. -# Has been transferred to the NDB Kernel and is currently being processed. -# Has been transferred to the NDB Kernel and has finished processing. Now it is waiting for a call to a poll method. (When the poll method is invoked, then the transaction callback method will be executed.) The poll method invoked (either Ndb::pollNdb() or Ndb::sendPollNdb()) will return when: -# at least 'minNoOfEventsToWakeup' of the transactions in the send list have transitioned to state 3 as described above, and -# all of these transactions have executed their callback methods.*/#endif/** @page secConcepts MySQL Cluster Concepts The <em>NDB Kernel</em> is the collection of storage nodes belonging to a MySQL Cluster. The application programmer can for most purposes view the set of all storage nodes as a single entity. Each storage node is made up of three main components: - TC : The transaction co-ordinator - ACC : Index storage component - TUP : Data storage component When an application program executes a transaction, it connects to one transaction co-ordinator on one storage node. Usually, the programmer does not need to specify which TC should be used, but in some cases when performance is important, the programmer can provide "hints" to use a certain TC. (If the node with the desired transaction co-ordinator is down, then another TC will automatically take over the work.) Every storage node has an ACC and a TUP which store the indexes and data portions of the database table fragment. Even though one TC is responsible for the transaction, several ACCs and TUPs on other storage nodes might be involved in the execution of the transaction. @section secNdbKernelConnection Selecting a Transaction Co-ordinator The default method is to select the transaction co-ordinator (TC) determined to be the "closest" storage node, using a heuristic for proximity based on the type of transporter connection. In order of closest to most distant, these are - SCI - SHM - TCP/IP (localhost) - TCP/IP (remote host) If there are several connections available with the same proximity, they will each be selected in a round robin fashion for every transaction. Optionally one may set the method for TC selection to round-robin mode, where each new set of transactions is placed on the next DB node. The pool of connections from which this selection is made consists of all available connections. As noted previously, the application programmer can provide hints to the NDB API as to which transaction co-ordinator it should use. This is done by providing a <em>table</em> and <em>partition key</em> (usually the primary key). By using the primary key as the partition key, the transaction will be placed on the node where the primary replica of that record resides. Note that this is only a hint; the system can be reconfigured at any time, in which case the NDB API will choose a transaction co-ordinator without using the hint. For more information, see NdbDictionary::Column::getPartitionKey() and Ndb::startTransaction(). The application programmer can specify the partition key from SQL by using the construct, <code>CREATE TABLE ... ENGINE=NDB PARTITION BY KEY (<var>attribute-list</var>);</code>. @section secRecordStruct NDB Record Structure The NDB Cluster engine used by MySQL Cluster is a relational database engine storing records in tables just as with any other RDBMS. Table rows represent records as tuples of relational data. When a new table is created, its attribute schema is specified for the table as a whole, and thus each record of the table has the same structure. Again, this is typical of relational databases, and NDB is no different in this regard. @subsection secKeys Primary Keys Each record has from 1 up to 32 attributes which belong to the primary key of the table. @section secTrans Transactions Transactions are committed first to main memory, and then to disk after a global checkpoint (GCP) is issued. Since all data is (in most NDB Cluster configurations) synchronously replicated and stored on multiple NDB nodes, the system can still handle processor failures without loss of data. However, in the case of a system failure (e.g. the whole system goes down), then all (committed or not) transactions occurring since the latest GCP are lost. @subsection secConcur Concurrency Control NDB Cluster uses pessimistic concurrency control based on locking. If a requested lock (implicit and depending on database operation) cannot be attained within a specified time, then a timeout error occurs. Concurrent transactions as requested by parallel application programs and thread-based applications can sometimes deadlock when they try to access the same information simultaneously. Thus, applications need to be written in a manner so that timeout errors occurring due to such deadlocks are handled gracefully. This generally means that the transaction encountering a timeout should be rolled back
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -