diff options
author | unknown <monty@donna.mysql.com> | 2000-12-07 14:08:48 +0200 |
---|---|---|
committer | unknown <monty@donna.mysql.com> | 2000-12-07 14:08:48 +0200 |
commit | 42018251893357035befbffa256275c71def9ebc (patch) | |
tree | 8a5c9d678d477bb2c3fa95057c9299dcf9560aab /sql | |
parent | d0643438b647048f74a04d73d5685eb2c80f1d4b (diff) | |
download | mariadb-git-42018251893357035befbffa256275c71def9ebc.tar.gz |
Only write full transactions to binary log
A lot of new functions for BDB tables
Fix for DROP DATABASE on windows
Default server_id variables
Docs/manual.texi:
Update of BDB info + Changes
configure.in:
Added test of readlink
include/mysqld_error.h:
Added new error message
sql/ha_berkeley.cc:
Added storing of status, CHECK, ANALYZE and OPTIMIZE TABLE
sql/ha_berkeley.h:
Added storing of status, CHECK, ANALYZE and OPTIMIZE TABLE
sql/handler.cc:
Only write full transactions to binary log
sql/hostname.cc:
cleanup
sql/log.cc:
Only write full transactions to binary log
sql/log_event.h:
Only write full transactions to binary log
sql/mf_iocache.cc:
Changes to be able to use IO_CACHE to save statements in a transaction
sql/mysql_priv.h:
New variables
sql/mysqld.cc:
Only write full transactions to binary log
Added default values for server_id
Lots of new bdb options
sql/share/czech/errmsg.sys:
Added new error message
sql/share/czech/errmsg.txt:
Added new error message
sql/share/danish/errmsg.sys:
Added new error message
sql/share/danish/errmsg.txt:
Added new error message
sql/share/dutch/errmsg.sys:
Added new error message
sql/share/dutch/errmsg.txt:
Added new error message
sql/share/english/errmsg.sys:
Added new error message
sql/share/english/errmsg.txt:
Added new error message
sql/share/estonian/errmsg.sys:
Added new error message
sql/share/estonian/errmsg.txt:
Added new error message
sql/share/french/errmsg.sys:
Added new error message
sql/share/french/errmsg.txt:
Added new error message
sql/share/german/errmsg.sys:
Added new error message
sql/share/german/errmsg.txt:
Added new error message
sql/share/greek/errmsg.sys:
Added new error message
sql/share/greek/errmsg.txt:
Added new error message
sql/share/hungarian/errmsg.sys:
Added new error message
sql/share/hungarian/errmsg.txt:
Added new error message
sql/share/italian/errmsg.sys:
Added new error message
sql/share/italian/errmsg.txt:
Added new error message
sql/share/japanese/errmsg.sys:
Added new error message
sql/share/japanese/errmsg.txt:
Added new error message
sql/share/korean/errmsg.sys:
Added new error message
sql/share/korean/errmsg.txt:
Added new error message
sql/share/norwegian-ny/errmsg.txt:
Added new error message
sql/share/norwegian/errmsg.txt:
Added new error message
sql/share/polish/errmsg.sys:
Added new error message
sql/share/polish/errmsg.txt:
Added new error message
sql/share/portuguese/errmsg.sys:
Added new error message
sql/share/portuguese/errmsg.txt:
Added new error message
sql/share/romanian/errmsg.txt:
Added new error message
sql/share/russian/errmsg.sys:
Added new error message
sql/share/russian/errmsg.txt:
Added new error message
sql/share/slovak/errmsg.sys:
Added new error message
sql/share/slovak/errmsg.txt:
Added new error message
sql/share/spanish/errmsg.sys:
Added new error message
sql/share/spanish/errmsg.txt:
Added new error message
sql/share/swedish/errmsg.OLD:
Added new error message
sql/share/swedish/errmsg.sys:
Added new error message
sql/share/swedish/errmsg.txt:
Added new error message
sql/sql_base.cc:
cleanup
sql/sql_class.cc:
Only write full transactions to binary log
sql/sql_class.h:
Added error handling of failed writes to logs
sql/sql_db.cc:
Fix for DROP DATABASE on windows
sql/sql_delete.cc:
Only write full transactions to binary log
sql/sql_insert.cc:
Only write full transactions to binary log
sql/sql_load.cc:
Only write full transactions to binary log
sql/sql_parse.cc:
End transaction at DROP, RENAME, CREATE and TRUNCATE
sql/sql_table.cc:
Fixes for ALTER TABLE on BDB tables for windows
sql/sql_update.cc:
Only write full transactions to binary log
sql/sql_yacc.yy:
AGAINST is not anymore a reserved word
support-files/my-huge.cnf.sh:
Changed to use binary log
support-files/my-large.cnf.sh:
Changed to use binary log
support-files/my-medium.cnf.sh:
Changed to use binary log
support-files/my-small.cnf.sh:
Changed to use binary log
Diffstat (limited to 'sql')
60 files changed, 719 insertions, 268 deletions
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index f515b151c8b..35e503751af 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -37,12 +37,15 @@ transaction ?) - When using ALTER TABLE IGNORE, we should not start an transaction, but do everything wthout transactions. + - When we do rollback, we need to subtract the number of changed rows + from the updated tables. Testing of: - - ALTER TABLE - LOCK TABLES - - CHAR keys - BLOBS + - Mark tables that participate in a transaction so that they are not + closed during the transaction. We need to test what happens if + MySQL closes a table that is updated by a not commit transaction. */ @@ -58,19 +61,27 @@ #include <hash.h> #include "ha_berkeley.h" #include "sql_manager.h" +#include <stdarg.h> #define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */ #define HA_BERKELEY_RANGE_COUNT 100 #define HA_BERKELEY_MAX_ROWS 10000000 /* Max rows in table */ +/* extra rows for estimate_number_of_rows() */ +#define HA_BERKELEY_EXTRA_ROWS 100 + +/* Bits for share->status */ +#define STATUS_PRIMARY_KEY_INIT 1 +#define STATUS_ROW_COUNT_INIT 2 +#define STATUS_BDB_ANALYZE 4 const char *ha_berkeley_ext=".db"; -bool berkeley_skip=0; -u_int32_t berkeley_init_flags=0,berkeley_lock_type=DB_LOCK_DEFAULT; +bool berkeley_skip=0,berkeley_shared_data=0; +u_int32_t berkeley_init_flags= DB_PRIVATE, berkeley_lock_type=DB_LOCK_DEFAULT; ulong berkeley_cache_size; char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir; long berkeley_lock_scan_time=0; ulong berkeley_trans_retry=5; -ulong berkeley_lock_max; +ulong berkeley_max_lock; pthread_mutex_t bdb_mutex; static DB_ENV *db_env; @@ -86,11 +97,13 @@ TYPELIB berkeley_lock_typelib= {array_elements(berkeley_lock_names),"", static void berkeley_print_error(const char *db_errpfx, char *buffer); static byte* bdb_get_key(BDB_SHARE *share,uint *length, my_bool not_used __attribute__((unused))); -static BDB_SHARE *get_share(const char *table_name); -static void free_share(BDB_SHARE *share); +static BDB_SHARE *get_share(const char *table_name, TABLE *table); +static void free_share(BDB_SHARE *share, TABLE *table); +static void update_status(BDB_SHARE *share, TABLE *table); static void berkeley_noticecall(DB_ENV *db_env, db_notices notice); + /* General functions */ bool berkeley_init(void) @@ -121,14 +134,14 @@ bool berkeley_init(void) db_env->set_cachesize(db_env, 0, berkeley_cache_size, 0); db_env->set_lk_detect(db_env, berkeley_lock_type); - if (berkeley_lock_max) - db_env->set_lk_max(db_env, berkeley_lock_max); + if (berkeley_max_lock) + db_env->set_lk_max(db_env, berkeley_max_lock); if (db_env->open(db_env, berkeley_home, berkeley_init_flags | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | - DB_CREATE | DB_THREAD | DB_PRIVATE, 0666)) + DB_CREATE | DB_THREAD, 0666)) { db_env->close(db_env,0); db_env=0; @@ -336,7 +349,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length) if (*key != (table->record[0][key_part->null_offset] & key_part->null_bit) ? 0 : 1) return 1; - if (!*key++) // Null value + if (!*key++) // Null value continue; } if ((cmp=key_part->field->pack_cmp(key,key_part->length))) @@ -345,7 +358,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length) key+=length; key_length-=length; } - return 0; + return 0; // Identical keys } @@ -387,7 +400,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) } /* Init table lock structure */ - if (!(share=get_share(name))) + if (!(share=get_share(name,table))) { my_free(rec_buff,MYF(0)); my_free(alloc_ptr,MYF(0)); @@ -397,7 +410,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) if ((error=db_create(&file, db_env, 0))) { - free_share(share); + free_share(share,table); my_free(rec_buff,MYF(0)); my_free(alloc_ptr,MYF(0)); my_errno=error; @@ -413,7 +426,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) 2 | 4), "main", DB_BTREE, open_mode,0)))) { - free_share(share); + free_share(share,table); my_free(rec_buff,MYF(0)); my_free(alloc_ptr,MYF(0)); my_errno=error; @@ -459,7 +472,6 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) } } } - /* Calculate pack_length of primary key */ if (!hidden_primary_key) { @@ -470,12 +482,9 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked) ref_length+= key_part->field->max_packed_col_length(key_part->length); fixed_length_primary_key= (ref_length == table->key_info[primary_key].key_length); + share->status|=STATUS_PRIMARY_KEY_INIT; } - else - { - if (!share->primary_key_inited) - update_auto_primary_key(); - } + get_status(); DBUG_RETURN(0); } @@ -491,7 +500,7 @@ int ha_berkeley::close(void) if (key_file[i] && (error=key_file[i]->close(key_file[i],0))) result=error; } - free_share(share); + free_share(share,table); my_free(rec_buff,MYF(MY_ALLOW_ZERO_PTR)); my_free(alloc_ptr,MYF(MY_ALLOW_ZERO_PTR)); if (result) @@ -632,8 +641,8 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index) This will never fail as the key buffer is pre allocated. */ -DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, - const byte *record) +DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff, + const byte *record, int key_length) { bzero((char*) key,sizeof(*key)); @@ -647,11 +656,11 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, KEY *key_info=table->key_info+keynr; KEY_PART_INFO *key_part=key_info->key_part; KEY_PART_INFO *end=key_part+key_info->key_parts; - DBUG_ENTER("pack_key"); + DBUG_ENTER("create_key"); key->data=buff; - for ( ; key_part != end ; key_part++) + for ( ; key_part != end && key_length > 0; key_part++) { if (key_part->null_bit) { @@ -666,6 +675,7 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, } buff=key_part->field->pack(buff,record + key_part->offset, key_part->length); + key_length-=key_part->length; } key->size= (buff - (char*) key->data); DBUG_DUMP("key",(char*) key->data, key->size); @@ -729,8 +739,8 @@ int ha_berkeley::write_row(byte * record) if (table->keys == 1) { - error=file->put(file, transaction, pack_key(&prim_key, primary_key, - key_buff, record), + error=file->put(file, transaction, create_key(&prim_key, primary_key, + key_buff, record), &row, key_type[primary_key]); } else @@ -742,8 +752,8 @@ int ha_berkeley::write_row(byte * record) if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) break; DBUG_PRINT("trans",("starting subtransaction")); - if (!(error=file->put(file, sub_trans, pack_key(&prim_key, primary_key, - key_buff, record), + if (!(error=file->put(file, sub_trans, create_key(&prim_key, primary_key, + key_buff, record), &row, key_type[primary_key]))) { for (keynr=0 ; keynr < table->keys ; keynr++) @@ -751,8 +761,8 @@ int ha_berkeley::write_row(byte * record) if (keynr == primary_key) continue; if ((error=key_file[keynr]->put(key_file[keynr], sub_trans, - pack_key(&key, keynr, key_buff2, - record), + create_key(&key, keynr, key_buff2, + record), &prim_key, key_type[keynr]))) { last_dup_key=keynr; @@ -783,6 +793,8 @@ int ha_berkeley::write_row(byte * record) } if (error == DB_KEYEXIST) error=HA_ERR_FOUND_DUPP_KEY; + else if (!error) + changed_rows++; DBUG_RETURN(error); } @@ -838,7 +850,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed, { // Primary key changed or we are updating a key that can have duplicates. // Delete the old row and add a new one - pack_key(&old_key, primary_key, key_buff2, old_row); + create_key(&old_key, primary_key, key_buff2, old_row); if ((error=remove_key(trans, primary_key, old_row, (DBT *) 0, &old_key))) DBUG_RETURN(error); // This should always succeed if ((error=pack_row(&row, new_row, 0))) @@ -893,10 +905,10 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row) } else { - pack_key(&prim_key, primary_key, key_buff, new_row); + create_key(&prim_key, primary_key, key_buff, new_row); if ((primary_key_changed=key_cmp(primary_key, old_row, new_row))) - pack_key(&old_prim_key, primary_key, primary_key_buff, old_row); + create_key(&old_prim_key, primary_key, primary_key_buff, old_row); else old_prim_key=prim_key; } @@ -921,7 +933,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row) if ((error=remove_key(sub_trans, keynr, old_row, (DBT*) 0, &old_prim_key)) || (error=key_file[keynr]->put(key_file[keynr], sub_trans, - pack_key(&key, keynr, key_buff2, + create_key(&key, keynr, key_buff2, new_row), &prim_key, key_type[keynr]))) { @@ -980,7 +992,7 @@ int ha_berkeley::remove_key(DB_TXN *sub_trans, uint keynr, const byte *record, error=key_file[keynr]->del(key_file[keynr], sub_trans, keynr == primary_key ? prim_key : - pack_key(&key, keynr, key_buff2, record), + create_key(&key, keynr, key_buff2, record), 0); } else @@ -997,7 +1009,7 @@ int ha_berkeley::remove_key(DB_TXN *sub_trans, uint keynr, const byte *record, if (!(error=cursor->c_get(cursor, (keynr == primary_key ? prim_key : - pack_key(&key, keynr, key_buff2, record)), + create_key(&key, keynr, key_buff2, record)), (keynr == primary_key ? packed_record : prim_key), DB_GET_BOTH))) @@ -1046,7 +1058,7 @@ int ha_berkeley::delete_row(const byte * record) if ((error=pack_row(&row, record, 0))) DBUG_RETURN((error)); - pack_key(&prim_key, primary_key, key_buff, record); + create_key(&prim_key, primary_key, key_buff, record); if (hidden_primary_key) keys|= (key_map) 1 << primary_key; @@ -1078,7 +1090,9 @@ int ha_berkeley::delete_row(const byte * record) if (error != DB_LOCK_DEADLOCK) break; } - DBUG_RETURN(0); + if (!error) + changed_rows--; + DBUG_RETURN(error); } @@ -1090,7 +1104,7 @@ int ha_berkeley::index_init(uint keynr) dbug_assert(cursor == 0); if ((error=file->cursor(key_file[keynr], transaction, &cursor, table->reginfo.lock_type > TL_WRITE_ALLOW_READ ? - 0 : 0))) + DB_RMW : 0))) cursor=0; // Safety bzero((char*) &last_key,sizeof(last_key)); DBUG_RETURN(error); @@ -1336,7 +1350,7 @@ void ha_berkeley::position(const byte *record) memcpy_fixed(ref, (char*) current_ident, BDB_HIDDEN_PRIMARY_KEY_LENGTH); } else - pack_key(&key, primary_key, ref, record); + create_key(&key, primary_key, ref, record); } @@ -1345,9 +1359,18 @@ void ha_berkeley::info(uint flag) DBUG_ENTER("info"); if (flag & HA_STATUS_VARIABLE) { - records = estimate_number_of_rows(); // Just to get optimisations right + records = share->rows; // Just to get optimisations right deleted = 0; } + if ((flag & HA_STATUS_CONST) || version != share->version) + { + version=share->version; + for (uint i=0 ; i < table->keys ; i++) + { + table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]= + share->rec_per_key[i]; + } + } else if (flag & HA_STATUS_ERRKEY) errkey=last_dup_key; DBUG_VOID_RETURN; @@ -1424,6 +1447,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type) } } transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid; + changed_rows=0; } else { @@ -1437,6 +1461,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type) current_row.data=0; } } + thread_safe_add(share->rows, changed_rows, &share->mutex); current_row.data=0; if (!--thd->transaction.bdb_lock_count) { @@ -1607,6 +1632,142 @@ ha_rows ha_berkeley::records_in_range(int keynr, DBUG_RETURN(rows <= 1.0 ? (ha_rows) 1 : (ha_rows) rows); } + +longlong ha_berkeley::get_auto_increment() +{ + longlong nr=1; // Default if error or new key + int error; + (void) ha_berkeley::extra(HA_EXTRA_KEYREAD); + ha_berkeley::index_init(table->next_number_index); + + if (!table->next_number_key_offset) + { // Autoincrement at key-start + error=ha_berkeley::index_last(table->record[1]); + } + else + { + DBT row; + bzero((char*) &row,sizeof(row)); + uint key_len; + KEY *key_info= &table->key_info[active_index]; + + /* Reading next available number for a sub key */ + ha_berkeley::create_key(&last_key, active_index, + key_buff, table->record[0], + table->next_number_key_offset); + /* Store for compare */ + memcpy(key_buff2, key_buff, (key_len=last_key.size)); + key_info->handler.bdb_return_if_eq= -1; + error=read_row(cursor->c_get(cursor, &last_key, &row, DB_SET_RANGE), + table->record[1], active_index, &row, (DBT*) 0, 0); + key_info->handler.bdb_return_if_eq= 0; + if (!error && !berkeley_key_cmp(table, key_info, key_buff2, key_len)) + { + /* + Found matching key; Now search after next key, go one step back + and then we should have found the biggest key with the given + prefix + */ + (void) read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT_NODUP), + table->record[1], active_index, &row, (DBT*) 0, 0); + if (read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV), + table->record[1], active_index, &row, (DBT*) 0, 0) || + berkeley_key_cmp(table, key_info, key_buff2, key_len)) + error=1; // Something went wrong + } + } + nr=(longlong) + table->next_number_field->val_int_offset(table->rec_buff_length)+1; + ha_berkeley::index_end(); + (void) ha_berkeley::extra(HA_EXTRA_NO_KEYREAD); + return nr; +} + + +/**************************************************************************** + Analyzing, checking, and optimizing tables +****************************************************************************/ + + +static void print_msg(THD *thd, const char *table_name, const char *op_name, + const char *msg_type, const char *fmt, ...) +{ + String* packet = &thd->packet; + packet->length(0); + char msgbuf[256]; + msgbuf[0] = 0; + va_list args; + va_start(args,fmt); + + my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia + + DBUG_PRINT(msg_type,("message: %s",msgbuf)); + + net_store_data(packet, table_name); + net_store_data(packet, op_name); + net_store_data(packet, msg_type); + net_store_data(packet, msgbuf); + if (my_net_write(&thd->net, (char*)thd->packet.ptr(), + thd->packet.length())) + thd->killed=1; +} + + +int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) +{ + DB_BTREE_STAT stat; + uint i; + + for (i=0 ; i < table->keys ; i++) + { + file->stat(key_file[i], (void*) &stat, 0, 0); + share->rec_per_key[i]= stat.bt_ndata / stat.bt_nkeys; + } + /* If hidden primary key */ + if (hidden_primary_key) + file->stat(file, (void*) &stat, 0, 0); + pthread_mutex_lock(&share->mutex); + share->rows=stat.bt_ndata; + share->status|=STATUS_BDB_ANALYZE; // Save status on close + share->version++; // Update stat in table + pthread_mutex_unlock(&share->mutex); + update_status(share,table); // Write status to file + return ((share->status & STATUS_BDB_ANALYZE) ? HA_ADMIN_FAILED : + HA_ADMIN_OK); +} + +int ha_berkeley::optimize(THD* thd, HA_CHECK_OPT* check_opt) +{ + return ha_berkeley::analyze(thd,check_opt); +} + + +int ha_berkeley::check(THD* thd, HA_CHECK_OPT* check_opt) +{ + char name_buff[FN_REFLEN]; + int error; + fn_format(name_buff,share->table_name,"", ha_berkeley_ext, 2 | 4); + if ((error=file->verify(file, name_buff, NullS, (FILE*) 0, + hidden_primary_key ? 0 : DB_NOORDERCHK))) + { + print_msg(thd, table->real_name, "check", "error", + "Got error %d checking file structure",error); + return HA_ADMIN_CORRUPT; + } + for (uint i=0 ; i < table->keys ; i++) + { + if ((error=file->verify(key_file[i], name_buff, NullS, (FILE*) 0, + DB_ORDERCHKONLY))) + { + print_msg(thd, table->real_name, "check", "error", + "Key %d was not in order",error); + return HA_ADMIN_CORRUPT; + } + } + return HA_ADMIN_OK; +} + /**************************************************************************** Handling the shared BDB_SHARE structure that is needed to provide table locking. @@ -1619,19 +1780,21 @@ static byte* bdb_get_key(BDB_SHARE *share,uint *length, return (byte*) share->table_name; } -static BDB_SHARE *get_share(const char *table_name) +static BDB_SHARE *get_share(const char *table_name, TABLE *table) { BDB_SHARE *share; pthread_mutex_lock(&bdb_mutex); uint length=(uint) strlen(table_name); if (!(share=(BDB_SHARE*) hash_search(&bdb_open_tables, table_name, length))) { - if ((share=(BDB_SHARE *) my_malloc(sizeof(*share)+length+1, + if ((share=(BDB_SHARE *) my_malloc(sizeof(*share)+length+1 + + sizeof(ha_rows)* table->keys, MYF(MY_WME | MY_ZEROFILL)))) { share->table_name_length=length; share->table_name=(char*) (share+1); strmov(share->table_name,table_name); + share->rec_per_key= (ha_rows*) (share+1); if (hash_insert(&bdb_open_tables, (char*) share)) { pthread_mutex_unlock(&bdb_mutex); @@ -1647,11 +1810,14 @@ static BDB_SHARE *get_share(const char *table_name) return share; } -static void free_share(BDB_SHARE *share) +static void free_share(BDB_SHARE *share, TABLE *table) { pthread_mutex_lock(&bdb_mutex); if (!--share->use_count) { + update_status(share,table); + if (share->status_block) + share->status_block->close(share->status_block,0); hash_delete(&bdb_open_tables, (gptr) share); thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->mutex); @@ -1660,20 +1826,124 @@ static void free_share(BDB_SHARE *share) pthread_mutex_unlock(&bdb_mutex); } +/* + Get status information that is stored in the 'status' sub database + and the max used value for the hidden primary key. +*/ -void ha_berkeley::update_auto_primary_key() +void ha_berkeley::get_status() { - pthread_mutex_lock(&share->mutex); - if (!share->primary_key_inited) + if (!test_all_bits(share->status,(STATUS_PRIMARY_KEY_INIT | + STATUS_ROW_COUNT_INIT))) + { + pthread_mutex_lock(&share->mutex); + if (!(share->status & STATUS_PRIMARY_KEY_INIT)) + { + (void) extra(HA_EXTRA_KEYREAD); + index_init(primary_key); + if (!index_last(table->record[1])) + share->auto_ident=uint5korr(current_ident); + index_end(); + (void) extra(HA_EXTRA_NO_KEYREAD); + } + if (! share->status_block) + { + char name_buff[FN_REFLEN]; + uint open_mode= (((table->db_stat & HA_READ_ONLY) ? DB_RDONLY : 0) + | DB_THREAD); + fn_format(name_buff, share->table_name,"", ha_berkeley_ext, 2 | 4); + if (!db_create(&share->status_block, db_env, 0)) + { + if (!share->status_block->open(share->status_block, name_buff, + "status", DB_BTREE, open_mode, 0)) + { + share->status_block->close(share->status_block, 0); + share->status_block=0; + } + } + } + if (!(share->status & STATUS_ROW_COUNT_INIT) && share->status_block) + { + share->org_rows=share->rows= + table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS; + if (!file->cursor(share->status_block, 0, &cursor, 0)) + { + DBT row; + char rec_buff[64],*pos=rec_buff; + bzero((char*) &row,sizeof(row)); + bzero((char*) &last_key,sizeof(last_key)); + row.data=rec_buff; + row.size=sizeof(rec_buff); + row.flags=DB_DBT_USERMEM; + if (!cursor->c_get(cursor, &last_key, &row, DB_FIRST)) + { + uint i; + share->org_rows=share->rows=uint4korr(pos); pos+=4; + for (i=0 ; i < table->keys ; i++) + { + share->rec_per_key[i]=uint4korr(pos); pos+=4; + } + } + cursor->c_close(cursor); + } + cursor=0; // Safety + } + share->status|= STATUS_PRIMARY_KEY_INIT | STATUS_ROW_COUNT_INIT; + pthread_mutex_unlock(&share->mutex); + } +} + + +static void update_status(BDB_SHARE *share, TABLE *table) +{ + DBUG_ENTER("update_status"); + if (share->rows != share->org_rows || + (share->status & STATUS_BDB_ANALYZE)) { - (void) extra(HA_EXTRA_KEYREAD); - index_init(primary_key); - if (!index_last(table->record[1])) - share->auto_ident=uint5korr(current_ident); - index_end(); - (void) extra(HA_EXTRA_NO_KEYREAD); + pthread_mutex_lock(&share->mutex); + if (!share->status_block) + { + /* + Create sub database 'status' if it doesn't exist from before + (This '*should*' always exist for table created with MySQL) + */ + + char name_buff[FN_REFLEN]; + if (db_create(&share->status_block, db_env, 0)) + goto end; + share->status_block->set_flags(share->status_block,0); + if (share->status_block->open(share->status_block, + fn_format(name_buff,share->table_name,"", + ha_berkeley_ext,2 | 4), + "status", DB_BTREE, + DB_THREAD | DB_CREATE, my_umask)) + goto end; + } + { + uint i; + DBT row,key; + char rec_buff[4+MAX_KEY*sizeof(ulong)], *pos=rec_buff; + const char *key_buff="status"; + + bzero((char*) &row,sizeof(row)); + bzero((char*) &key,sizeof(key)); + row.data=rec_buff; + key.data=(void*) key_buff; + key.size=sizeof(key_buff); + row.flags=key.flags=DB_DBT_USERMEM; + int4store(pos,share->rows); pos+=4; + for (i=0 ; i < table->keys ; i++) + { + int4store(pos,share->rec_per_key[i]); pos+=4; + } + row.size=(uint) (pos-rec_buff); + (void) share->status_block->put(share->status_block, 0, &key, &row, 0); + share->status&= ~STATUS_BDB_ANALYZE; + } +end: + pthread_mutex_unlock(&share->mutex); } - pthread_mutex_unlock(&share->mutex); + DBUG_VOID_RETURN; } /* @@ -1683,14 +1953,7 @@ void ha_berkeley::update_auto_primary_key() ha_rows ha_berkeley::estimate_number_of_rows() { - ulonglong max_ident; - ulonglong max_rows=table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS; - if (!hidden_primary_key) - return (ha_rows) max_rows; - pthread_mutex_lock(&share->mutex); - max_ident=share->auto_ident+EXTRA_RECORDS; - pthread_mutex_unlock(&share->mutex); - return (ha_rows) min(max_ident,max_rows); + return share->rows + HA_BERKELEY_EXTRA_ROWS; } #endif /* HAVE_BERKELEY_DB */ diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 3cfcab82ecf..4ee682664a5 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -27,11 +27,13 @@ typedef struct st_berkeley_share { ulonglong auto_ident; + ha_rows rows, org_rows, *rec_per_key; THR_LOCK lock; pthread_mutex_t mutex; char *table_name; + DB *status_block; uint table_name_length,use_count; - bool primary_key_inited; + uint status,version; } BDB_SHARE; @@ -49,7 +51,8 @@ class ha_berkeley: public handler BDB_SHARE *share; ulong int_option_flag; ulong alloced_rec_buff_length; - uint primary_key,last_dup_key, hidden_primary_key; + ulong changed_rows; + uint primary_key,last_dup_key, hidden_primary_key, version; bool fixed_length_row, fixed_length_primary_key, key_read; bool fix_rec_buff_for_blob(ulong length); byte current_ident[BDB_HIDDEN_PRIMARY_KEY_LENGTH]; @@ -58,7 +61,8 @@ class ha_berkeley: public handler int pack_row(DBT *row,const byte *record, bool new_row); void unpack_row(char *record, DBT *row); void ha_berkeley::unpack_key(char *record, DBT *key, uint index); - DBT *pack_key(DBT *key, uint keynr, char *buff, const byte *record); + DBT *create_key(DBT *key, uint keynr, char *buff, const byte *record, + int key_length = MAX_KEY_LENGTH); DBT *pack_key(DBT *key, uint keynr, char *buff, const byte *key_ptr, uint key_length); int remove_key(DB_TXN *trans, uint keynr, const byte *record, @@ -79,8 +83,9 @@ class ha_berkeley: public handler HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY | HA_BLOB_KEY | HA_NOT_EXACT_COUNT | - HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE), - last_dup_key((uint) -1) + HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE | + HA_AUTO_PART_KEY), + last_dup_key((uint) -1),version(0) { } ~ha_berkeley() {} @@ -123,6 +128,10 @@ class ha_berkeley: public handler int reset(void); int external_lock(THD *thd, int lock_type); void position(byte *record); + int analyze(THD* thd,HA_CHECK_OPT* check_opt); + int optimize(THD* thd, HA_CHECK_OPT* check_opt); + int check(THD* thd, HA_CHECK_OPT* check_opt); + ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len, enum ha_rkey_function start_search_flag, @@ -135,7 +144,7 @@ class ha_berkeley: public handler THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); - void update_auto_primary_key(); + void get_status(); inline void get_auto_primary_key(byte *to) { ulonglong tmp; @@ -144,11 +153,12 @@ class ha_berkeley: public handler int5store(to,share->auto_ident); pthread_mutex_unlock(&share->mutex); } + longlong ha_berkeley::get_auto_increment(); }; -extern bool berkeley_skip; +extern bool berkeley_skip, berkeley_shared_data; extern u_int32_t berkeley_init_flags,berkeley_lock_type,berkeley_lock_types[]; -extern ulong berkeley_cache_size, berkeley_lock_max; +extern ulong berkeley_cache_size, berkeley_max_lock; extern char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir; extern long berkeley_lock_scan_time; extern TYPELIB berkeley_lock_typelib; diff --git a/sql/handler.cc b/sql/handler.cc index 83ab85ebbbd..7c6a3e32ff2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -191,8 +191,7 @@ int ha_autocommit_or_rollback(THD *thd, int error) { DBUG_ENTER("ha_autocommit_or_rollback"); #ifdef USING_TRANSACTIONS - if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) && - !thd->locked_tables) + if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) { if (!error) { @@ -211,6 +210,16 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) { int error=0; DBUG_ENTER("ha_commit"); +#ifdef USING_TRANSACTIONS + /* Update the binary log if we have cached some queries */ + if (trans == &thd->transaction.all && mysql_bin_log.is_open() && + my_b_tell(&thd->transaction.trans_log)) + { + mysql_bin_log.write(&thd->transaction.trans_log); + reinit_io_cache(&thd->transaction.trans_log, + WRITE_CACHE, (my_off_t) 0, 0, 1); + thd->transaction.trans_log.end_of_file= max_binlog_cache_size; + } #ifdef HAVE_BERKELEY_DB if (trans->bdb_tid) { @@ -224,7 +233,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) #endif #ifdef HAVE_INNOBASE_DB { - if ((error=innobase_commit(thd,trans->innobase_tid)) + if ((error=innobase_commit(thd,trans->innobase_tid))) { my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); error=1; @@ -232,6 +241,9 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) trans->innobase_tid=0; } #endif + if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) + sql_print_error("Error: Got error during commit; Binlog is not up to date!"); +#endif DBUG_RETURN(error); } @@ -261,6 +273,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans) trans->innobase_tid=0; } #endif +#ifdef USING_TRANSACTIONS + if (trans == &thd->transaction.all) + reinit_io_cache(&thd->transaction.trans_log, + WRITE_CACHE, (my_off_t) 0, 0, 1); + thd->transaction.trans_log.end_of_file= max_binlog_cache_size; +#endif DBUG_RETURN(error); } diff --git a/sql/hostname.cc b/sql/hostname.cc index 47953020ffb..db8f8349446 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -180,20 +180,21 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) VOID(pthread_mutex_lock(&hostname_cache->lock)); if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET))) { - DBUG_PRINT("error",("gethostbyaddr returned %d",errno)); VOID(pthread_mutex_unlock(&hostname_cache->lock)); - add_wrong_ip(in); - DBUG_RETURN(0); + DBUG_PRINT("error",("gethostbyaddr returned %d",errno)); + goto err; } - if (!hp->h_name[0]) + if (!hp->h_name[0]) // Don't allow empty hostnames { VOID(pthread_mutex_unlock(&hostname_cache->lock)); DBUG_PRINT("error",("Got an empty hostname")); - add_wrong_ip(in); - DBUG_RETURN(0); // Don't allow empty hostnames + goto err; } if (!(name=my_strdup(hp->h_name,MYF(0)))) + { + VOID(pthread_mutex_unlock(&hostname_cache->lock)); DBUG_RETURN(0); // out of memory + } check=gethostbyname(name); VOID(pthread_mutex_unlock(&hostname_cache->lock)); if (!check) @@ -214,8 +215,7 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) { DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'")); my_free(name,MYF(0)); - add_wrong_ip(in); - DBUG_RETURN(0); + goto err; } } @@ -230,6 +230,8 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) } DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname")); my_free(name,MYF(0)); + +err: add_wrong_ip(in); DBUG_RETURN(0); } diff --git a/sql/log.cc b/sql/log.cc index 2dda594ea59..1c377ebc3a5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -16,6 +16,7 @@ /* logging of commands */ +/* TODO: Abort logging when we get an error in reading or writing log files */ #include "mysql_priv.h" #include "sql_acl.h" @@ -523,14 +524,12 @@ void MYSQL_LOG::new_file() } -void MYSQL_LOG::write(THD *thd,enum enum_server_command command, +bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, const char *format,...) { if (is_open() && (what_to_log & (1L << (uint) command))) { - va_list args; - va_start(args,format); - char buff[32]; + int error=0; VOID(pthread_mutex_lock(&LOCK_log)); /* Test if someone closed after the is_open test */ @@ -538,14 +537,17 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, { time_t skr; ulong id; - int error=0; + va_list args; + va_start(args,format); + char buff[32]; + if (thd) { // Normal thread if ((thd->options & OPTION_LOG_OFF) && (thd->master_access & PROCESS_ACL)) { VOID(pthread_mutex_unlock(&LOCK_log)); - return; // No logging + return 0; // No logging } id=thd->thread_id; if (thd->user_time || !(skr=thd->query_start())) @@ -593,115 +595,184 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,error); } + va_end(args); + VOID(pthread_mutex_unlock(&LOCK_log)); } - va_end(args); VOID(pthread_mutex_unlock(&LOCK_log)); + return error != 0; } + return 0; } /* Write to binary log in a format to be used for replication */ -void MYSQL_LOG::write(Query_log_event* event_info) +bool MYSQL_LOG::write(Query_log_event* event_info) { + /* In most cases this is only called if 'is_open()' is true */ + bool error=1; + VOID(pthread_mutex_lock(&LOCK_log)); if (is_open()) { - VOID(pthread_mutex_lock(&LOCK_log)); - if (is_open()) + THD *thd=event_info->thd; + IO_CACHE *file = (event_info->cache_stmt ? &thd->transaction.trans_log : + &log_file); + if ((!(thd->options & OPTION_BIN_LOG) && + thd->master_access & PROCESS_ACL) || + !db_ok(event_info->db, binlog_do_db, binlog_ignore_db)) { - THD *thd=event_info->thd; - if ((!(thd->options & OPTION_BIN_LOG) && - thd->master_access & PROCESS_ACL) || - !db_ok(event_info->db, binlog_do_db, binlog_ignore_db)) - { - VOID(pthread_mutex_unlock(&LOCK_log)); - return; - } + VOID(pthread_mutex_unlock(&LOCK_log)); + return 0; + } - if (thd->last_insert_id_used) - { - Intvar_log_event e((uchar)LAST_INSERT_ID_EVENT, thd->last_insert_id); - if (e.write(&log_file)) - { - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - goto err; - } - } - if (thd->insert_id_used) - { - Intvar_log_event e((uchar)INSERT_ID_EVENT, thd->last_insert_id); - if (e.write(&log_file)) - { - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - goto err; - } - } - if (thd->convert_set) + if (thd->last_insert_id_used) + { + Intvar_log_event e((uchar)LAST_INSERT_ID_EVENT, thd->last_insert_id); + if (e.write(file)) + goto err; + } + if (thd->insert_id_used) + { + Intvar_log_event e((uchar)INSERT_ID_EVENT, thd->last_insert_id); + if (e.write(file)) + goto err; + } + if (thd->convert_set) + { + char buf[1024] = "SET CHARACTER SET "; + char* p = strend(buf); + p = strmov(p, thd->convert_set->name); + int save_query_length = thd->query_length; + // just in case somebody wants it later + thd->query_length = (uint)(p - buf); + Query_log_event e(thd, buf); + if (e.write(file)) + goto err; + thd->query_length = save_query_length; // clean up + } + if (event_info->write(file) || + file == &log_file && flush_io_cache(file)) + goto err; + error=0; + +err: + if (error) + { + if (my_errno == EFBIG) + my_error(ER_TRANS_CACHE_FULL, MYF(0)); + else + my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno); + write_error=1; + } + if (file == &log_file) + VOID(pthread_cond_broadcast(&COND_binlog_update)); + } + else + error=0; + VOID(pthread_mutex_unlock(&LOCK_log)); + return error; +} + +/* + Write a cached log entry to the binary log + We only come here if there is something in the cache. + 'cache' needs to be reinitialized after this functions returns. +*/ + +bool MYSQL_LOG::write(IO_CACHE *cache) +{ + VOID(pthread_mutex_lock(&LOCK_log)); + bool error=1; + if (is_open()) + { + uint length; + my_off_t start_pos=my_b_tell(&log_file); + + if (reinit_io_cache(cache, WRITE_CACHE, 0, 0, 0)) + { + if (!write_error) + sql_print_error(ER(ER_ERROR_ON_WRITE), cache->file_name, errno); + goto err; + } + while ((length=my_b_fill(cache))) + { + if (my_b_write(&log_file, cache->rc_pos, length)) { - char buf[1024] = "SET CHARACTER SET "; - char* p = strend(buf); - p = strmov(p, thd->convert_set->name); - int save_query_length = thd->query_length; - // just in case somebody wants it later - thd->query_length = (uint)(p - buf); - Query_log_event e(thd, buf); - if (e.write(&log_file)) - { + if (!write_error) sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - goto err; - } - thd->query_length = save_query_length; // clean up + goto err; } - if (event_info->write(&log_file) || flush_io_cache(&log_file)) - { + cache->rc_pos=cache->rc_end; // Mark buffer used up + } + if (flush_io_cache(&log_file)) + { + if (!write_error) sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - } - err: - VOID(pthread_cond_broadcast(&COND_binlog_update)); + goto err; + } + if (cache->error) // Error on read + { + if (!write_error) + sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno); + goto err; } - VOID(pthread_mutex_unlock(&LOCK_log)); } + error=0; + +err: + if (error) + write_error=1; + else + VOID(pthread_cond_broadcast(&COND_binlog_update)); + + VOID(pthread_mutex_unlock(&LOCK_log)); + return error; } -void MYSQL_LOG::write(Load_log_event* event_info) + +bool MYSQL_LOG::write(Load_log_event* event_info) { + bool error=0; + VOID(pthread_mutex_lock(&LOCK_log)); if (is_open()) { - VOID(pthread_mutex_lock(&LOCK_log)); - if (is_open()) + THD *thd=event_info->thd; + if ((thd->options & OPTION_BIN_LOG) || + !(thd->master_access & PROCESS_ACL)) { - THD *thd=event_info->thd; - if ((thd->options & OPTION_BIN_LOG) || - !(thd->master_access & PROCESS_ACL)) + if (event_info->write(&log_file) || flush_io_cache(&log_file)) { - if (event_info->write(&log_file) || flush_io_cache(&log_file)) + if (!write_error) sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - VOID(pthread_cond_broadcast(&COND_binlog_update)); + error=write_error=1; } + VOID(pthread_cond_broadcast(&COND_binlog_update)); } - VOID(pthread_mutex_unlock(&LOCK_log)); } + VOID(pthread_mutex_unlock(&LOCK_log)); + return error; } /* Write update log in a format suitable for incremental backup */ -void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, +bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, time_t query_start) { + bool error=0; if (is_open()) { time_t current_time; VOID(pthread_mutex_lock(&LOCK_log)); if (is_open()) { // Safety agains reopen - int error=0; + int tmp_errno=0; char buff[80],*end; end=buff; if (!(thd->options & OPTION_UPDATE_LOG) && (thd->master_access & PROCESS_ACL)) { VOID(pthread_mutex_unlock(&LOCK_log)); - return; + return 0; } if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start) { @@ -722,14 +793,14 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, start->tm_min, start->tm_sec); if (my_b_write(&log_file, (byte*) buff,24)) - error=errno; + tmp_errno=errno; } if (my_b_printf(&log_file, "# User@Host: %s[%s] @ %s [%s]\n", thd->priv_user, thd->user, thd->host ? thd->host : "", thd->ip ? thd->ip : "") == (uint) -1) - error=errno; + tmp_errno=errno; } if (query_start) { @@ -739,12 +810,12 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, (ulong) (current_time - query_start), (ulong) (thd->time_after_lock - query_start), (ulong) thd->sent_row_count) == (uint) -1) - error=errno; + tmp_errno=errno; } if (thd->db && strcmp(thd->db,db)) { // Database changed if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1) - error=errno; + tmp_errno=errno; strmov(db,thd->db); } if (thd->last_insert_id_used) @@ -777,7 +848,7 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, *end=0; if (my_b_write(&log_file, (byte*) "SET ",4) || my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)-1)) - error=errno; + tmp_errno=errno; } if (!query) { @@ -787,29 +858,22 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, if (my_b_write(&log_file, (byte*) query,query_length) || my_b_write(&log_file, (byte*) ";\n",2) || flush_io_cache(&log_file)) - error=errno; - if (error && ! write_error) + tmp_errno=errno; + if (tmp_errno) { - write_error=1; - sql_print_error(ER(ER_ERROR_ON_WRITE),name,error); + error=1; + if (! write_error) + { + write_error=1; + sql_print_error(ER(ER_ERROR_ON_WRITE),name,error); + } } } VOID(pthread_mutex_unlock(&LOCK_log)); } + return error; } -#ifdef TO_BE_REMOVED -void MYSQL_LOG::flush() -{ - if (is_open()) - if (flush_io_cache(log_file) && ! write_error) - { - write_error=1; - sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); - } -} -#endif - void MYSQL_LOG::close(bool exiting) { // One can't set log_type here! diff --git a/sql/log_event.h b/sql/log_event.h index b31d444ad21..3d307000b13 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -118,16 +118,18 @@ public: ulong thread_id; #if !defined(MYSQL_CLIENT) THD* thd; - Query_log_event(THD* thd_arg, const char* query_arg): - Log_event(thd_arg->start_time,0,0,thd_arg->server_id), data_buf(0), + bool cache_stmt; + Query_log_event(THD* thd_arg, const char* query_arg, bool using_trans=0): + Log_event(thd_arg->start_time,0,1,thd_arg->server_id), data_buf(0), query(query_arg), db(thd_arg->db), q_len(thd_arg->query_length), error_code(thd_arg->net.last_errno), - thread_id(thd_arg->thread_id), thd(thd_arg) + thread_id(thd_arg->thread_id), thd(thd_arg), + cache_stmt(using_trans && + (thd_arg->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) { time_t end_time; time(&end_time); exec_time = (ulong) (end_time - thd->start_time); - valid_exec_time = 1; db_len = (db) ? (uint32) strlen(db) : 0; } #endif diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index f723e35ca93..cddacaa820f 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -121,7 +121,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, } /* end_of_file may be changed by user later */ info->end_of_file= ((type == READ_NET || type == READ_FIFO ) ? 0 - : MY_FILEPOS_ERROR); + : ~(my_off_t) 0); info->type=type; info->error=0; info->read_function=(type == READ_NET) ? _my_b_net_read : _my_b_read; /* net | file */ @@ -176,6 +176,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, DBUG_ENTER("reinit_io_cache"); info->seek_not_done= test(info->file >= 0); /* Seek not done */ + + /* If the whole file is in memory, avoid flushing to disk */ if (! clear_cache && seek_offset >= info->pos_in_file && seek_offset <= info->pos_in_file + @@ -186,8 +188,12 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->rc_end=info->rc_pos; info->end_of_file=my_b_tell(info); } - else if (info->type == READ_CACHE && type == WRITE_CACHE) - info->rc_end=info->buffer+info->buffer_length; + else if (type == WRITE_CACHE) + { + if (info->type == READ_CACHE) + info->rc_end=info->buffer+info->buffer_length; + info->end_of_file = ~(my_off_t) 0; + } info->rc_pos=info->rc_request_pos+(seek_offset-info->pos_in_file); #ifdef HAVE_AIOWAIT my_aiowait(&info->aio_result); /* Wait for outstanding req */ @@ -195,11 +201,20 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, } else { + /* + If we change from WRITE_CACHE to READ_CACHE, assume that everything + after the current positions should be ignored + */ if (info->type == WRITE_CACHE && type == READ_CACHE) info->end_of_file=my_b_tell(info); - if (flush_io_cache(info)) + /* No need to flush cache if we want to reuse it */ + if ((type != WRITE_CACHE || !clear_cache) && flush_io_cache(info)) DBUG_RETURN(1); - info->pos_in_file=seek_offset; + if (info->pos_in_file != seek_offset) + { + info->pos_in_file=seek_offset; + info->seek_not_done=1; + } info->rc_request_pos=info->rc_pos=info->buffer; if (type == READ_CACHE || type == READ_NET || type == READ_FIFO) { @@ -210,7 +225,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->rc_end=info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1)); info->end_of_file= ((type == READ_NET || type == READ_FIFO) ? 0 : - MY_FILEPOS_ERROR); + ~(my_off_t) 0); } } info->type=type; @@ -536,6 +551,11 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) Buffer+=rest_length; Count-=rest_length; info->rc_pos+=rest_length; + if (info->pos_in_file+info->buffer_length > info->end_of_file) + { + my_errno=errno=EFBIG; + return info->error = -1; + } if (flush_io_cache(info)) return 1; if (Count >= IO_SIZE) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6dd3c06c236..7c3b1cfadef 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -507,9 +507,9 @@ extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size, net_read_timeout,net_write_timeout, what_to_log,flush_time, max_tmp_tables,max_heap_table_size,query_buff_size, - lower_case_table_names,thread_stack,thread_stack_min; -extern ulong specialflag; -extern ulong current_pid; + lower_case_table_names,thread_stack,thread_stack_min, + binlog_cache_size, max_binlog_cache_size; +extern ulong specialflag, current_pid; extern bool low_priority_updates; extern bool opt_sql_bin_update; extern char language[LIBLEN],reg_ext[FN_EXTLEN],blob_newline; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 143d9267425..1122a770523 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -201,10 +201,10 @@ ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size, query_buff_size, lower_case_table_names, mysqld_net_retry_count, net_interactive_timeout, slow_launch_time = 2L, net_read_timeout,net_write_timeout,slave_open_temp_tables=0; -ulong thread_cache_size=0; +ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0; volatile ulong cached_thread_count=0; -// replication parameters, if master_host is not NULL, we are slaving off the master +// replication parameters, if master_host is not NULL, we are a slave my_string master_user = (char*) "test", master_password = 0, master_host=0, master_info_file = (char*) "master.info"; const char *localhost=LOCAL_HOST; @@ -1496,23 +1496,21 @@ int main(int argc, char **argv) if (opt_update_log) open_log(&mysql_update_log, glob_hostname, opt_update_logname, "", LOG_NEW); + + if (!server_id) + server_id= !master_host ? 1 : 2; if (opt_bin_log) { - if(server_id) - { - if (!opt_bin_logname) - { - char tmp[FN_REFLEN]; - strnmov(tmp,glob_hostname,FN_REFLEN-5); - strmov(strcend(tmp,'.'),"-bin"); - opt_bin_logname=my_strdup(tmp,MYF(MY_WME)); - } - mysql_bin_log.set_index_file_name(opt_binlog_index_name); - open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", - LOG_BIN); - } - else - sql_print_error("Server id is not set - binary logging disabled"); + if (!opt_bin_logname) + { + char tmp[FN_REFLEN]; + strnmov(tmp,glob_hostname,FN_REFLEN-5); + strmov(strcend(tmp,'.'),"-bin"); + opt_bin_logname=my_strdup(tmp,MYF(MY_WME)); + } + mysql_bin_log.set_index_file_name(opt_binlog_index_name); + open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", + LOG_BIN); } if (opt_slow_log) @@ -1620,19 +1618,14 @@ int main(int argc, char **argv) } // slave thread - if(master_host) + if (master_host) { - if(server_id) - { - pthread_t hThread; - if(!opt_skip_slave_start && - pthread_create(&hThread, &connection_attrib, handle_slave, 0)) - sql_print_error("Warning: Can't create thread to handle slave"); - else if(opt_skip_slave_start) - init_master_info(&glob_mi); - } - else - sql_print_error("Server id is not set, slave thread will not be started"); + pthread_t hThread; + if(!opt_skip_slave_start && + pthread_create(&hThread, &connection_attrib, handle_slave, 0)) + sql_print_error("Warning: Can't create thread to handle slave"); + else if(opt_skip_slave_start) + init_master_info(&glob_mi); } printf(ER(ER_READY),my_progname,server_version,""); @@ -2205,7 +2198,8 @@ enum options { OPT_BDB_HOME, OPT_BDB_LOG, OPT_BDB_TMP, OPT_BDB_NOSYNC, OPT_BDB_LOCK, OPT_BDB_SKIP, - OPT_BDB_RECOVER, OPT_MASTER_HOST, + OPT_BDB_RECOVER, OPT_BDB_SHARED, + OPT_MASTER_HOST, OPT_MASTER_USER, OPT_MASTER_PASSWORD, OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY, OPT_SQL_BIN_UPDATE_SAME, @@ -2233,6 +2227,7 @@ static struct option long_options[] = { {"bdb-logdir", required_argument, 0, (int) OPT_BDB_LOG}, {"bdb-recover", no_argument, 0, (int) OPT_BDB_RECOVER}, {"bdb-no-sync", no_argument, 0, (int) OPT_BDB_NOSYNC}, + {"bdb-shared-data", required_argument, 0, (int) OPT_BDB_SHARED}, {"bdb-tmpdir", required_argument, 0, (int) OPT_BDB_TMP}, #endif {"big-tables", no_argument, 0, (int) OPT_BIG_TABLES}, @@ -2323,7 +2318,7 @@ static struct option long_options[] = { (int) OPT_REPLICATE_REWRITE_DB}, {"safe-mode", no_argument, 0, (int) OPT_SAFE}, {"socket", required_argument, 0, (int) OPT_SOCKET}, - {"server-id", required_argument, 0, (int)OPT_SERVER_ID}, + {"server-id", required_argument, 0, (int) OPT_SERVER_ID}, {"set-variable", required_argument, 0, 'O'}, #ifdef HAVE_BERKELEY_DB {"skip-bdb", no_argument, 0, (int) OPT_BDB_SKIP}, @@ -2363,9 +2358,14 @@ CHANGEABLE_VAR changeable_vars[] = { #ifdef HAVE_BERKELEY_DB { "bdb_cache_size", (long*) &berkeley_cache_size, KEY_CACHE_SIZE, 20*1024, (long) ~0, 0, IO_SIZE }, - { "bdb_lock_max", (long*) &berkeley_lock_max, + { "bdb_max_lock", (long*) &berkeley_max_lock, + 1000, 0, (long) ~0, 0, 1 }, + /* QQ: The following should be removed soon! */ + { "bdb_lock_max", (long*) &berkeley_max_lock, 1000, 0, (long) ~0, 0, 1 }, #endif + { "binlog_cache_size", (long*) &binlog_cache_size, + 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE }, { "connect_timeout", (long*) &connect_timeout, CONNECT_TIMEOUT, 2, 65535, 0, 1 }, { "delayed_insert_timeout", (long*) &delayed_insert_timeout, @@ -2390,7 +2390,7 @@ CHANGEABLE_VAR changeable_vars[] = { {"innobase_buffer_pool_size", (long*) &innobase_buffer_pool_size, 8*1024*1024L, 1024*1024L, ~0L, 0, 1024*1024L}, - {"innobase_additional_mem_pool_size_mb", + {"innobase_additional_mem_pool_size", (long*) &innobase_additional_mem_pool_size, 1*1024*1024L, 512*1024L, ~0L, 0, 1024}, {"innobase_file_io_threads", @@ -2408,6 +2408,8 @@ CHANGEABLE_VAR changeable_vars[] = { IF_WIN(1,0), 0, 1, 0, 1 }, { "max_allowed_packet", (long*) &max_allowed_packet, 1024*1024L, 80, 17*1024*1024L, MALLOC_OVERHEAD, 1024 }, + { "max_binlog_cache_size", (long*) &max_binlog_cache_size, + ~0L, IO_SIZE, ~0L, 0, IO_SIZE }, { "max_connections", (long*) &max_connections, 100, 1, 16384, 0, 1 }, { "max_connect_errors", (long*) &max_connect_errors, @@ -2465,10 +2467,12 @@ struct show_var_st init_vars[]= { #ifdef HAVE_BERKELEY_DB {"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONG}, {"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR}, - {"bdb_lock_max", (char*) &berkeley_lock_max, SHOW_LONG}, + {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG}, {"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR}, + {"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL}, {"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR}, #endif + {"binlog_cache_size", (char*) &binlog_cache_size, SHOW_LONG}, {"character_set", default_charset, SHOW_CHAR}, {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR}, {"concurrent_insert", (char*) &myisam_concurrent_insert, SHOW_MY_BOOL}, @@ -2497,6 +2501,7 @@ struct show_var_st init_vars[]= { {"low_priority_updates", (char*) &low_priority_updates, SHOW_BOOL}, {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_LONG}, {"max_allowed_packet", (char*) &max_allowed_packet, SHOW_LONG}, + {"max_binlog_cache_size", (char*) &max_binlog_cache_size, SHOW_LONG}, {"max_connections", (char*) &max_connections, SHOW_LONG}, {"max_connect_errors", (char*) &max_connect_errors, SHOW_LONG}, {"max_delayed_threads", (char*) &max_insert_delayed_threads, SHOW_LONG}, @@ -2711,8 +2716,9 @@ static void usage(void) --bdb-lock-detect=# Berkeley lock detect\n\ (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec)\n\ --bdb-logdir=directory Berkeley DB log file directory\n\ - --bdb-nosync Don't synchronously flush logs\n\ + --bdb-no-sync Don't synchronously flush logs\n\ --bdb-recover Start Berkeley DB in recover mode\n\ + --bdb-shared-data Start Berkeley DB in multi-process mode\n\ --bdb-tmpdir=directory Berkeley DB tempfile name\n\ --skip-bdb Don't use berkeley db (will save memory)\n\ "); @@ -3224,6 +3230,10 @@ static void get_options(int argc,char **argv) } break; } + case OPT_BDB_SHARED: + berkeley_init_flags&= ~(DB_PRIVATE); + berkeley_shared_data=1; + break; case OPT_BDB_SKIP: berkeley_skip=1; break; diff --git a/sql/share/czech/errmsg.sys b/sql/share/czech/errmsg.sys Binary files differindex ebb6e9ba348..68ce82eeb9e 100644 --- a/sql/share/czech/errmsg.sys +++ b/sql/share/czech/errmsg.sys diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 437702240c7..c10d59dc21c 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -207,3 +207,4 @@ "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",-A "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",-A "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/danish/errmsg.sys b/sql/share/danish/errmsg.sys Binary files differindex d55c0ada743..1e358664792 100644 --- a/sql/share/danish/errmsg.sys +++ b/sql/share/danish/errmsg.sys diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index b1faff2fffb..79d7ae5efc4 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -201,3 +201,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/dutch/errmsg.sys b/sql/share/dutch/errmsg.sys Binary files differindex 7a35b102cf1..c00dc0f3c0c 100644 --- a/sql/share/dutch/errmsg.sys +++ b/sql/share/dutch/errmsg.sys diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 18029c32a97..1cfdbee8d43 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/english/errmsg.sys b/sql/share/english/errmsg.sys Binary files differindex 903f2958129..af1b051e1cd 100644 --- a/sql/share/english/errmsg.sys +++ b/sql/share/english/errmsg.sys diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 6395180f4fd..4900e4bd7ad 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/estonian/errmsg.sys b/sql/share/estonian/errmsg.sys Binary files differindex fe9b221ce58..f27359c76e0 100644 --- a/sql/share/estonian/errmsg.sys +++ b/sql/share/estonian/errmsg.sys diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index b90b5d205ec..cb609f66432 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -202,3 +202,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/french/errmsg.sys b/sql/share/french/errmsg.sys Binary files differindex 75c1c8328f1..6bac623b236 100644 --- a/sql/share/french/errmsg.sys +++ b/sql/share/french/errmsg.sys diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index e5d90a93733..0e1b9cf8e01 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/german/errmsg.sys b/sql/share/german/errmsg.sys Binary files differindex 46a68a5ef7f..d9f835e8dbe 100644 --- a/sql/share/german/errmsg.sys +++ b/sql/share/german/errmsg.sys diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 4ebd1ffe751..4d36544fedc 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -201,3 +201,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/greek/errmsg.sys b/sql/share/greek/errmsg.sys Binary files differindex bed966bdab4..d831fac812d 100644 --- a/sql/share/greek/errmsg.sys +++ b/sql/share/greek/errmsg.sys diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index d5ff3d1253f..eb43678ddcf 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/hungarian/errmsg.sys b/sql/share/hungarian/errmsg.sys Binary files differindex da976080e27..6c2d550e7ac 100644 --- a/sql/share/hungarian/errmsg.sys +++ b/sql/share/hungarian/errmsg.sys diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index f864fe7ff0d..eacc8a967a9 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -200,3 +200,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/italian/errmsg.sys b/sql/share/italian/errmsg.sys Binary files differindex 7aea0464d7a..e63175d0230 100644 --- a/sql/share/italian/errmsg.sys +++ b/sql/share/italian/errmsg.sys diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 44dbfd63a7b..f5e333696cf 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -198,3 +198,4 @@ "La tabella '%-.64s' e' segnalata come rovinata e deve essere riparata", "La tabella '%-.64s' e' segnalata come rovinata e l'ultima ricostruzione (automatica?) e' fallita", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/japanese/errmsg.sys b/sql/share/japanese/errmsg.sys Binary files differindex 41618a4ffea..d0d8cfe1c41 100644 --- a/sql/share/japanese/errmsg.sys +++ b/sql/share/japanese/errmsg.sys diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index c2650178002..4b7a3fd30e1 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -200,3 +200,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/korean/errmsg.sys b/sql/share/korean/errmsg.sys Binary files differindex c94649378f4..a47cab2da19 100644 --- a/sql/share/korean/errmsg.sys +++ b/sql/share/korean/errmsg.sys diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index e49eead2210..d772f8c46d5 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 0dd18ba9ecb..d6c29026c0b 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -200,3 +200,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index eb12dafbd6d..4d0c1ef87f0 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -200,3 +200,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/polish/errmsg.sys b/sql/share/polish/errmsg.sys Binary files differindex 551ff4d81a6..6246eac84f9 100644 --- a/sql/share/polish/errmsg.sys +++ b/sql/share/polish/errmsg.sys diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 84991513129..a77f64b8b37 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -202,3 +202,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/portuguese/errmsg.sys b/sql/share/portuguese/errmsg.sys Binary files differindex 5a6e038c1ce..df54263f7d7 100644 --- a/sql/share/portuguese/errmsg.sys +++ b/sql/share/portuguese/errmsg.sys diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index dbb881f21d5..946a64df5d0 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -198,3 +198,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 4b48d4347a9..7c325b9c662 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -202,3 +202,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/russian/errmsg.sys b/sql/share/russian/errmsg.sys Binary files differindex e2497d5e356..e7dbcac4f0e 100644 --- a/sql/share/russian/errmsg.sys +++ b/sql/share/russian/errmsg.sys diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index a759a495c37..7a83573e0ff 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -201,3 +201,4 @@ "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÄÏÌÖÎÁ ÂÙÔØ ÉÓÐÒÁ×ÌÅÎÁ", "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÑÑ ÐÏÐÙÔËÁ ÉÓÐÒÁ×ÌÅÎÉÑ (Á×ÔÏÍÁÔÉÞÅÓËÁÑ?) ÎÅ ÕÄÁÌÁÓØ", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/slovak/errmsg.sys b/sql/share/slovak/errmsg.sys Binary files differindex 8e0c6ab4b79..2a8f977d3ea 100644 --- a/sql/share/slovak/errmsg.sys +++ b/sql/share/slovak/errmsg.sys diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 1ca1632bd57..774047be656 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -206,3 +206,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/spanish/errmsg.sys b/sql/share/spanish/errmsg.sys Binary files differindex bb301f89d3e..d651bd4c555 100644 --- a/sql/share/spanish/errmsg.sys +++ b/sql/share/spanish/errmsg.sys diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 7a76c438bad..0003e435183 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -199,3 +199,4 @@ "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", +"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again', diff --git a/sql/share/swedish/errmsg.OLD b/sql/share/swedish/errmsg.OLD index 78dfa51a806..ea8c2b78e3f 100644 --- a/sql/share/swedish/errmsg.OLD +++ b/sql/share/swedish/errmsg.OLD @@ -198,3 +198,5 @@ "Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", +#ER_TRANS_CACHE_FULL +"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", diff --git a/sql/share/swedish/errmsg.sys b/sql/share/swedish/errmsg.sys Binary files differindex 011968008e8..3cf1b59746a 100644 --- a/sql/share/swedish/errmsg.sys +++ b/sql/share/swedish/errmsg.sys diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 78dfa51a806..ee3d913e51a 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -198,3 +198,4 @@ "Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", +"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 75add1e7a5f..63c17dae740 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -454,15 +454,15 @@ void close_temporary_tables(THD *thd) next=table->next; close_temporary(table); } - if(query && mysql_bin_log.is_open()) - { - uint save_query_len = thd->query_length; - *--p = 0; - thd->query_length = (uint)(p-query); - Query_log_event qinfo(thd, query); - mysql_bin_log.write(&qinfo); - thd->query_length = save_query_len; - } + if (query && mysql_bin_log.is_open()) + { + uint save_query_len = thd->query_length; + *--p = 0; + thd->query_length = (uint)(p-query); + Query_log_event qinfo(thd, query); + mysql_bin_log.write(&qinfo); + thd->query_length = save_query_len; + } thd->temporary_tables=0; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b93b0a5b909..b310d0f44bb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -121,8 +121,10 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), #ifdef USING_TRANSACTIONS bzero((char*) &transaction,sizeof(transaction)); if (open_cached_file(&transaction.trans_log, - mysql_tmpdir,LOG_PREFIX,0,MYF(MY_WME))) + mysql_tmpdir, LOG_PREFIX, binlog_cache_size, + MYF(MY_WME))) killed=1; + transaction.trans_log.end_of_file= max_binlog_cache_size; #endif #ifdef __WIN__ diff --git a/sql/sql_class.h b/sql/sql_class.h index 7e3864fad01..4943e334aa0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -74,12 +74,12 @@ public: void open(const char *log_name,enum_log_type log_type, const char *new_name=0); void new_file(void); - void write(THD *thd, enum enum_server_command command,const char *format,...); - void write(THD *thd, const char *query, uint query_length, + bool write(THD *thd, enum enum_server_command command,const char *format,...); + bool write(THD *thd, const char *query, uint query_length, time_t query_start=0); - void write(Query_log_event* event_info); // binary log write - void write(Load_log_event* event_info); - + bool write(Query_log_event* event_info); // binary log write + bool write(Load_log_event* event_info); + bool write(IO_CACHE *cache); int generate_new_name(char *new_name,const char *old_name); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 4ac78a9853e..89e7faa237c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -158,14 +158,14 @@ exit: are 2 digits (raid directories). */ -static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, - uint level) +static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, + uint level) { long deleted=0; ulong found_other_files=0; char filePath[FN_REFLEN]; DBUG_ENTER("mysql_rm_known_files"); - DBUG_PRINT("enter",("path: %s", path)); + DBUG_PRINT("enter",("path: %s", org_path)); /* remove all files with known extensions */ for (uint idx=2 ; @@ -181,7 +181,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, { char newpath[FN_REFLEN]; MY_DIR *new_dirp; - strxmov(newpath,path,"/",file->name,NullS); + strxmov(newpath,org_path,"/",file->name,NullS); unpack_filename(newpath,newpath); if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) { @@ -199,7 +199,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, found_other_files++; continue; } - strxmov(filePath,path,"/",file->name,NullS); + strxmov(filePath,org_path,"/",file->name,NullS); unpack_filename(filePath,filePath); if (my_delete(filePath,MYF(MY_WME))) { @@ -224,9 +224,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, */ if (!found_other_files) { -#ifdef HAVE_READLINK char tmp_path[FN_REFLEN]; - path=unpack_filename(tmp_path,path); + char *path=unpack_filename(tmp_path,org_path); +#ifdef HAVE_READLINK int linkcount = readlink(path,filePath,sizeof(filePath)-1); if (linkcount > 0) // If the path was a symbolic link { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 807464552a7..dbcd2640dbc 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -126,7 +126,7 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit, SQL_SELECT *select; READ_RECORD info; bool using_limit=limit != HA_POS_ERROR; - bool use_generate_table; + bool use_generate_table,using_transactions; DBUG_ENTER("mysql_delete"); if (!table_list->db) @@ -214,18 +214,20 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit, (void) table->file->extra(HA_EXTRA_READCHECK); if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_NORMAL); - if (deleted) + using_transactions=table->file->has_transactions(); + if (deleted && (error == 0 || !using_transactions)) { mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, using_transactions); + if (mysql_bin_log.write(&qinfo) && using_transactions) + error=1; } - if (!table->file->has_transactions()) + if (!using_transactions) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (ha_autocommit_or_rollback(thd,error >= 0)) + if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0)) error=1; if (thd->lock) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b1ae918a791..baaf65d4197 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -102,6 +102,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, int error; bool log_on= ((thd->options & OPTION_UPDATE_LOG) || !(thd->master_access & PROCESS_ACL)); + bool using_transactions; uint value_count; uint save_time_stamp; ulong counter = 1; @@ -254,18 +255,21 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, thd->insert_id(id); // For update log else if (table->next_number_field) id=table->next_number_field->val_int(); // Return auto_increment value - if (info.copied || info.deleted) + using_transactions=table->file->has_transactions(); + if ((info.copied || info.deleted) && (error == 0 || !using_transactions)) { mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, using_transactions); + if (mysql_bin_log.write(&qinfo) && using_transactions) + error=1; } - if (!table->file->has_transactions()) + if (!using_transactions) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - error=ha_autocommit_or_rollback(thd,error); + if (using_transactions) + error=ha_autocommit_or_rollback(thd,error); if (thd->lock) { mysql_unlock_tables(thd, thd->lock); @@ -1265,7 +1269,8 @@ bool select_insert::send_eof() mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query); + Query_log_event qinfo(thd, thd->query, + table->file->has_transactions()); mysql_bin_log.write(&qinfo); } return 0; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 1cb042537fc..7c2d77ce3fc 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -245,10 +245,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (!table->file->has_transactions()) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; - if (!read_file_from_client) + if (!read_file_from_client && mysql_bin_log.is_open()) { ex->skip_lines = save_skip_lines; - Load_log_event qinfo(thd, ex, table->table_name, fields, handle_duplicates); + Load_log_event qinfo(thd, ex, table->table_name, fields, + handle_duplicates); mysql_bin_log.write(&qinfo); } DBUG_RETURN(0); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 85a1847feab..88a9df7543a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -172,7 +172,7 @@ check_connections(THD *thd) vio_description(net->vio))); if (!thd->host) // If TCP/IP connection { - char ip[17]; + char ip[30]; if (vio_peer_addr(net->vio,ip)) return (ER_BAD_HOST_ERROR); @@ -718,7 +718,7 @@ bool do_command(THD *thd) case COM_DROP_DB: { char *db=thd->strdup(packet+1); - if (check_access(thd,DROP_ACL,db,0,1)) + if (check_access(thd,DROP_ACL,db,0,1) || end_active_trans(thd)) break; mysql_log.write(thd,command,db); mysql_rm_db(thd,db,0); @@ -1136,7 +1136,10 @@ mysql_execute_command(void) goto error; /* purecov: inspected */ if (grant_option && check_grant(thd,INDEX_ACL,tables)) goto error; - res = mysql_create_index(thd, tables, lex->key_list); + if (end_active_trans(thd)) + res= -1; + else + res = mysql_create_index(thd, tables, lex->key_list); break; case SQLCOM_SLAVE_START: @@ -1224,7 +1227,9 @@ mysql_execute_command(void) goto error; } } - if (mysql_rename_tables(thd,tables)) + if (end_active_trans(thd)) + res= -1; + else if (mysql_rename_tables(thd,tables)) res= -1; break; } @@ -1428,7 +1433,10 @@ mysql_execute_command(void) { if (check_table_access(thd,DROP_ACL,tables)) goto error; /* purecov: inspected */ - res = mysql_rm_table(thd,tables,lex->drop_if_exists); + if (end_active_trans(thd)) + res= -1; + else + res = mysql_rm_table(thd,tables,lex->drop_if_exists); } break; case SQLCOM_DROP_INDEX: @@ -1438,7 +1446,10 @@ mysql_execute_command(void) goto error; /* purecov: inspected */ if (grant_option && check_grant(thd,INDEX_ACL,tables)) goto error; - res = mysql_drop_index(thd, tables, lex->drop_list); + if (end_active_trans(thd)) + res= -1; + else + res = mysql_drop_index(thd, tables, lex->drop_list); break; case SQLCOM_SHOW_DATABASES: #if defined(DONT_ALLOW_SHOW_COMMANDS) @@ -1643,7 +1654,8 @@ mysql_execute_command(void) } case SQLCOM_DROP_DB: { - if (check_access(thd,DROP_ACL,lex->name,0,1)) + if (check_access(thd,DROP_ACL,lex->name,0,1) || + end_active_trans(thd)) break; mysql_rm_db(thd,lex->name,lex->drop_if_exists); break; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 804a592b6e1..dc1ceb1112b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1427,6 +1427,17 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->count_cuted_fields=0; /* Don`t calc cuted fields */ new_table->time_stamp=save_time_stamp; +#if defined( __WIN__) || defined( __EMX__) + /* + We must do the COMMIT here so that we can close and rename the + temporary table (as windows can't rename open tables) + */ + if (ha_commit_stmt(thd)) + error=1; + if (ha_commit(thd)) + error=1; +#endif + if (table->tmp_table) { /* We changed a temporary table */ @@ -1544,6 +1555,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } } + +#if !(defined( __WIN__) || defined( __EMX__)) /* The ALTER TABLE is always in it's own transaction */ error = ha_commit_stmt(thd); if (ha_commit(thd)) @@ -1554,6 +1567,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } +#endif thd->proc_info="end"; mysql_update_log.write(thd, thd->query,thd->query_length); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 25e990e9f62..54f85eb2ec7 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -49,7 +49,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, thr_lock_type lock_type) { bool using_limit=limit != HA_POS_ERROR; - bool used_key_is_modified; + bool used_key_is_modified, using_transactions; int error=0; uint save_time_stamp, used_index; key_map old_used_keys; @@ -237,18 +237,20 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields, thd->proc_info="end"; VOID(table->file->extra(HA_EXTRA_READCHECK)); table->time_stamp=save_time_stamp; // Restore auto timestamp pointer - if (updated) + using_transactions=table->file->has_transactions(); + if (updated && (error == 0 || !using_transactions)) { mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, using_transactions); + if (mysql_bin_log.write(&qinfo) && using_transactions) + error=1; } - if (!table->file->has_transactions()) + if (!using_transactions) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (ha_autocommit_or_rollback(thd, error >= 0)) + if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0)) error=1; if (thd->lock) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6735498b8f2..e301c290894 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2451,6 +2451,7 @@ user: keyword: ACTION {} | AFTER_SYM {} + | AGAINST {} | AGGREGATE_SYM {} | AUTOCOMMIT {} | AVG_ROW_LENGTH {} |