Below is the list of changes that have just been committed into a local
5.1 repository of kostja. When kostja does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-05-10 16:32:39+04:00, kostja@vajra.(none) +8 -0
Merge vajra.(none):/opt/local/work/mysql-5.0-21483
into vajra.(none):/opt/local/work/mysql-5.1-runtime
MERGE: 1.1810.2897.4
mysql-test/r/query_cache.result@stripped, 2007-05-10 16:27:52+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.65.1.15
mysql-test/t/sp.test@stripped, 2007-05-10 16:27:53+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.174.28.13
sql/item.cc@stripped, 2007-05-10 16:27:53+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.113.1.153
sql/item_func.cc@stripped, 2007-05-10 16:27:53+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.270.1.67
sql/mysql_priv.h@stripped, 2007-05-10 16:27:53+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.290.1.159
sql/sql_insert.cc@stripped, 2007-05-10 16:32:35+04:00, kostja@vajra.(none) +13 -2
Manual merge.
MERGE: 1.146.1.85
sql/sql_lex.cc@stripped, 2007-05-10 16:27:54+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.142.1.78
sql/sql_parse.cc@stripped, 2007-05-10 16:27:54+04:00, kostja@vajra.(none) +0 -0
Auto merged
MERGE: 1.426.1.193
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: kostja
# Host: vajra.(none)
# Root: /opt/local/work/mysql-5.1-runtime/RESYNC
--- 1.261/sql/sql_insert.cc 2007-04-20 12:46:43 +04:00
+++ 1.262/sql/sql_insert.cc 2007-05-10 16:32:35 +04:00
@@ -384,6 +384,88 @@
}
+/**
+ Upgrade table-level lock of INSERT statement to TL_WRITE if
+ a more concurrent lock is infeasible for some reason. This is
+ necessary for engines without internal locking support (MyISAM).
+ An engine with internal locking implementation might later
+ downgrade the lock in handler::store_lock() method.
+*/
+
+void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
+ enum_duplicates duplic,
+ bool is_multi_insert)
+{
+ if (duplic == DUP_UPDATE ||
+ duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT)
+ {
+ *lock_type= TL_WRITE;
+ return;
+ }
+
+ if (*lock_type == TL_WRITE_DELAYED)
+ {
+#ifdef EMBEDDED_LIBRARY
+ /* No auxiliary threads in the embedded server. */
+ *lock_type= TL_WRITE;
+ return;
+#else
+ /*
+ We do not use delayed threads if:
+ - we're running in the safe mode or skip-new - the feature
+ is disabled in these modes
+ - we're running this query in statement level replication,
+ on a replication slave - because we must ensure serial
+ execution of queries on the slave
+ - it is INSERT .. ON DUPLICATE KEY UPDATE - in this case the
+ insert cannot be concurrent
+ */
+ if (specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE) ||
+ thd->slave_thread ||
+ thd->variables.max_insert_delayed_threads == 0)
+ {
+ *lock_type= TL_WRITE;
+ return;
+ }
+#endif
+ bool log_on= (thd->options & OPTION_BIN_LOG ||
+ ! (thd->security_ctx->master_access & SUPER_ACL));
+ if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT &&
+ log_on && mysql_bin_log.is_open() && is_multi_insert)
+ {
+ /*
+ Statement-based binary logging does not work in this case, because:
+ a) two concurrent statements may have their rows intermixed in the
+ queue, leading to autoincrement replication problems on slave (because
+ the values generated used for one statement don't depend only on the
+ value generated for the first row of this statement, so are not
+ replicable)
+ b) if first row of the statement has an error the full statement is
+ not binlogged, while next rows of the statement may be inserted.
+ c) if first row succeeds, statement is binlogged immediately with a
+ zero error code (i.e. "no error"), if then second row fails, query
+ will fail on slave too and slave will stop (wrongly believing that the
+ master got no error).
+ So we fallback to non-delayed INSERT.
+ Note that to be fully correct, we should test the "binlog format which
+ the delayed thread is going to use for this row". But in the common case
+ where the global binlog format is not changed and the session binlog
+ format may be changed, that is equal to the global binlog format.
+ We test it without mutex for speed reasons (condition rarely true), and
+ in the common case (global not changed) it is as good as without mutex;
+ if global value is changed, anyway there is uncertainty as the delayed
+ thread may be old and use the before-the-change value.
+ */
+ *lock_type= TL_WRITE;
+ }
+ }
+}
+
+
+/**
+ INSERT statement implementation
+*/
+
bool mysql_insert(THD *thd,TABLE_LIST *table_list,
List<Item> &fields,
List<List_item> &values_list,
@@ -419,67 +501,31 @@
DBUG_ENTER("mysql_insert");
/*
- in safe mode or with skip-new change delayed insert to be regular
- if we are told to replace duplicates, the insert cannot be concurrent
- delayed insert changed to regular in slave thread
- */
-#ifdef EMBEDDED_LIBRARY
- if (lock_type == TL_WRITE_DELAYED)
- lock_type=TL_WRITE;
-#else
- if ((lock_type == TL_WRITE_DELAYED &&
- ((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) ||
- thd->slave_thread || !thd->variables.max_insert_delayed_threads)) ||
- (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) ||
- (duplic == DUP_UPDATE))
- lock_type=TL_WRITE;
-#endif
- if ((lock_type == TL_WRITE_DELAYED) &&
- (global_system_variables.binlog_format == BINLOG_FORMAT_STMT) &&
- log_on && mysql_bin_log.is_open() &&
- (values_list.elements > 1))
+ Upgrade lock type if the requested lock is incompatible with
+ the current connection mode or table operation.
+ */
+ upgrade_lock_type(thd, &table_list->lock_type, duplic,
+ values_list.elements > 1);
+ lock_type= table_list->lock_type;
+
+ /*
+ We can't write-delayed into a table locked with LOCK TABLES:
+ this will lead to a deadlock, since the delayed thread will
+ never be able to get a lock on the table. QQQ: why not
+ upgrade the lock here instead?
+ */
+ if (lock_type == TL_WRITE_DELAYED && thd->locked_tables &&
+ find_locked_table(thd, table_list->db, table_list->table_name))
{
- /*
- Statement-based binary logging does not work in this case, because:
- a) two concurrent statements may have their rows intermixed in the
- queue, leading to autoincrement replication problems on slave (because
- the values generated used for one statement don't depend only on the
- value generated for the first row of this statement, so are not
- replicable)
- b) if first row of the statement has an error the full statement is
- not binlogged, while next rows of the statement may be inserted.
- c) if first row succeeds, statement is binlogged immediately with a
- zero error code (i.e. "no error"), if then second row fails, query
- will fail on slave too and slave will stop (wrongly believing that the
- master got no error).
- So we fallback to non-delayed INSERT.
- Note that to be fully correct, we should test the "binlog format which
- the delayed thread is going to use for this row". But in the common case
- where the global binlog format is not changed and the session binlog
- format may be changed, that is equal to the global binlog format.
- We test it without mutex for speed reasons (condition rarely true), and
- in the common case (global not changed) it is as good as without mutex;
- if global value is changed, anyway there is uncertainty as the delayed
- thread may be old and use the before-the-change value.
- */
- lock_type= TL_WRITE;
+ my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
+ table_list->table_name);
+ DBUG_RETURN(TRUE);
}
- table_list->lock_type= lock_type;
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
res= 1;
- if (thd->locked_tables)
- {
- DBUG_ASSERT(table_list->db); /* Must be set in the parser */
- if (find_locked_table(thd, table_list->db, table_list->table_name))
- {
- my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
- table_list->table_name);
- DBUG_RETURN(TRUE);
- }
- }
if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
{
/*
@@ -1502,6 +1548,12 @@
}
};
+/**
+ delayed_insert - context of a thread responsible for delayed insert
+ into one table. When processing delayed inserts, we create an own
+ thread for every distinct table. Later on all delayed inserts directed
+ into that table are handled by a dedicated thread.
+*/
class delayed_insert :public ilink {
uint locks_in_memory;
@@ -1598,6 +1650,12 @@
I_List<delayed_insert> delayed_threads;
+/**
+ Return an instance of delayed insert thread that can handle
+ inserts into a given table, if it exists. Otherwise return NULL.
+*/
+
+static
delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
{
thd->proc_info="waiting for delay_list";
@@ -1618,6 +1676,18 @@
}
+/**
+ Attempt to find or create a delayed insert thread to handle inserts
+ into this table.
+
+ @return Return an instance of the table in the delayed thread
+ @retval NULL too many delayed threads OR
+ this thread ran out of resources OR
+ a newly created delayed insert thread ran out of resources OR
+ the delayed insert thread failed to open the table.
+ In the last three cases an error is set in THD.
+*/
+
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
{
int error;
@@ -1726,11 +1796,17 @@
}
-/*
- As we can't let many threads modify the same TABLE structure, we create
- an own structure for each tread. This includes a row buffer to save the
- column values and new fields that points to the new row buffer.
- The memory is allocated in the client thread and is freed automaticly.
+/**
+ As we can't let many client threads modify the same TABLE
+ structure of the dedicated delayed insert thread, we create an
+ own structure for each client thread. This includes a row
+ buffer to save the column values and new fields that point to
+ the new row buffer. The memory is allocated in the client
+ thread and is freed automatically.
+
+ @pre This function is called from the client thread. Delayed
+ insert thread mutex must be acquired before invoking this
+ function.
*/
TABLE *delayed_insert::get_local_table(THD* client_thd)
| Thread |
|---|
| • bk commit into 5.1 tree (kostja:1.2510) | konstantin | 10 May |