August 2012

[MySQL Bug]Bug#13986705 CRASH IN GET_INTERVAL_VALUE() WITH DATE CALCULATION WITH UTF32 INTERVALS

upstream link: http://bazaar.launchpad.net/~mysql/mysql-server/5.5/revision/3840 test case: select space(date_add(101, INTERVAL (CAST(CHAR(‘1’ USING utf16) AS CHAR(1)))hour_second)) 只影响5.5 根据crash的backtrace Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7ffff4643700 (LWP 5874)] 0x0000000000706602 in get_interval_value (args=0x7fff84004e98, int_type=INTERVAL_HOUR_SECOND, str_value=<value optimized out>, interval=0x7ffff4640c40)     at /u01/project/PS5518/trunk/Percona-Server-5.5.18/sql/item_timefunc.cc:1460 1460        while (str != end && my_isspace(cs,*str)) 在my_isspace(cs,*str)这里crash,my_isspace是一个宏: #define my_isspace(s, c)  (((s)->ctype+1)[(uchar) (c)] […]

[MySQL Bug]bug#66301(Percona Bug#1035225)简析

转载请署名:印风 ——————————— 先跑test case 1.创建测试表 CREATE TABLE t(        id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,        k INT,        c CHAR(1),        UNIQUE KEY(k)) ENGINE=InnoDB; 2.当顺序执行如下SQL时 SQL1–INSERT INTO t(k) VALUES (1), (2), (3) ON DUPLICATE KEY UPDATE c=’1′; SQL2–INSERT INTO t(k) VALUES (2), (4), (5) ON […]

[MySQL Bug]bug#61209简析

转载请署名:印风 ————————————————— MySQL bug#61209,changelog如下,在5.5.23被fix InnoDB: Running concurrent bulk inserts on a server with auto_increment_offset=1,auto_increment_increment greater than 1, and innodb_autoinc_lock_mode=1 could result in intermittent errors like the following, even with the primary key set to auto_increment and omitted from the INSERT statement:   Duplicate entry ‘value’ for key ‘PRIMARY’ The workaround was to set auto_increment_offset=1 or innodb_autoinc_lock_mode=0 (“traditional”). (Bug #13817703, Bug #61209)   之前已经介绍过了innodb 如何处理auto inc的代码流程,现在来看看在innobase_next_autoinc里是如何来计算的。 […]

[MySQL Bug] bug#61579碎碎念

转载请署名:印风 ———————————————- MySQL bug#61579 changelog: InnoDB: For an InnoDB table with a trigger, under the setting innodb_autoinc_lock_mode=1, sometimes auto-increment values could be interleaved when inserting into the table from two sessions concurrently. The sequence of auto-increment values could vary depending on timing, leading to data inconsistency in systems using replication. (Bug #12752572, Bug #61579) 根据changelog的描述,当某个表上存在触发器时,并且innodb_autoinc_lock_mode=1,当两个session并发插入表时,自增列的值可能会产生交错。当使用statement记录时,会导致duplicate key错误,导致复制停止。 把触发器移除掉,则一切正常。 简单的gdb一把可以看出来,对于一条简单的插入语句,在函数handler::update_auto_increment中,当有trigger时,预估值 estimation_rows_to_insert值为0, […]

[MySQL源码] Innodb如何处理auto_inc值

转载请署名:印风 ——————————————————– ha_innobase::write_row是向innodb写入记录的函数,进入函数时自增列的值还没被设置(如何是NULL的话),会调用handler::update_auto_increment来获取并更新自增列,然后再调用row_insert_for_mysql来实际插入记录。我们的精力主要集中在update_auto_increment及其调用的函数上。 先了解下handler的几个跟自增列相关的成员变量(根据注释及gdb推测):  a. ulonglong next_insert_id;   下一个插入自增列的值,当一次插入多行记录时(例如,insert select 操作),第一个没有指定自增列值的记录会从get_auto_increment函数获取的值并赋值给next_insert_id,这样对于剩下的记录就可以直接使用next_insert_id(每次都修改该值)。 b. ulonglong insert_id_for_cur_row;  当前记录的insert id 。第一次成功插入后,这个值被存储到THD::first_successful_insert_id_in_cur_stmt c. Discrete_interval auto_inc_interval_for_cur_row; 从get_auto_increment函数获取的insert id区间。 Discrete_interval 结构体又包含三个值 interval_min  区间的最小值 interval_values 区间内可用自增值的个数 interval_max 最大值 d.  uint auto_inc_intervals_count; 当前插入语句保留的自增区间数 e.  estimation_rows_to_insert 估计将要插入的记录数,在函数handler::ha_start_bulk_insert()中被设置,值为0表示未知。 ////////////////////////////////////////////////////////////////////////////////////////////////////// 下面来分析下handler::update_auto_increment主要流程 1.首先判断自增列是否已经赋值,或者是否不可以为NULL&&sql_mode为MODE_NO_AUTO_VALUE_ON_ZERO时,不做处理 if ((nr= table->next_number_field->val_int()) != 0 ||       (table->auto_increment_field_not_null &&       thd->variables.sql_mode & […]

[MySQL Bug] bug#65111碎碎念

changelog里的描述: InnoDB: In a transaction using the REPEATABLE READ isolation level, an UPDATE or DELETE statement for anInnoDB table could sometimes overlook rows recently committed by other transactions. As explained inSection 14.3.9.2, “Consistent Nonlocking Reads”, DML statements within a REPEATABLE READ transaction apply to rows committed by other transactions, even if a query could not see those rows. (Bug #14007649, Bug #65111) http://bugs.mysql.com/bug.php?id=65111 从bug#65111的描述来看,根据文档http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html中的描述: 有两个以以START […]

[MySQL 源码] 关于bug#65389的碎碎念

[MySQL Bug] bug#65389  MVCC IS BROKEN WITH IMPLICIT LOCK 该bug在5.5.26中被修复,changelog的描述如下: If a row was deleted from an InnoDB table, then another row was re-inserted with the same primary key value, an attempt by a concurrent transaction to lock the row could succeed when it should have waited. This issue occurred if the locking select used […]

[MySQL 源码] innodb如何创建二级索引

以下为分析问题时的随笔。写的很凌乱,仅做记录,以备后用。。。。。。 ////////////////////////////////////////////////////////////// ha_innobase::add_index是innodb创建索引的接口函数。 以下所有的讨论都是基于创建一个非聚集的二级索引。因此一些过程是被省略掉了。 1.获取数据词典信息           indexed_table = dict_table_get(prebuilt->table->name, FALSE); 2.检查索引键是否可用        error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table); 3.检查索引列长度 4. a.创建一个trx对象用于操作innodb数据词典,并创建新的数据词典信息 如果是主键,加LOCK_X,否则加LOCK_S锁 b.加数据词典锁row_mysql_lock_data_dictionary(trx); c.在ibdata的SYS_INDEXES中加载新的数据词典信息 d.trx_commit_for_mysql(trx); 提交刚刚创建的trx e.row_mysql_unlock_data_dictionary(trx) 以上步骤完成了对ibdata数据词典内的更新,在 完成后释放锁,这时候,如果在后续的row_merge_build_indexes时crash掉。trx_rollback_active不会drop掉新索引。 5. 调用函数row_merge_build_indexes实际创建索引,我们的讨论主要集中于此。 row_merge_build_indexes会读取表的聚集索引记录,创建临时表来保存这些记录,并使用合并排序算法进行排序以创建索引 a. 首先初始化merge file相关的数据结构,并初始化 merge_files = mem_alloc(n_indexes * sizeof *merge_files); block_size = 3 * sizeof *block; block = os_mem_alloc_large(&block_size); […]

MySQL 源代码分析

[MySQL源码] 在复制线程事务提交与更新relay-log.info之间crash导致的复制不一致

转载请署名:印风 ——————————————- 最近发现一种情况,在xid event和flush_relay_log_info中间crash,可能会导致数据不一致。 即事务提交了,但relay-log.info文件还没更新,这会造成重启crash recovery后事务被重复执行一次。 幸好,在innodb层记录了这些信息。并且Percona也提供了一个选项来利用这些信息。 1.相关全局变量 在trx/trx0sys.c文件中定义了如下变量 最后一个commit的事务的slave信息: trx_sys_mysql_master_log_name trx_sys_mysql_master_log_pos trx_sys_mysql_relay_log_name trx_sys_mysql_relay_log_pos 最后一个commit的binlog信息: trx_sys_mysql_bin_log_name trx_sys_mysql_bin_log_pos 2.写入信息 那么在什么时候会记录这些信息呢? 在函数mysql_bin_log_commit_pos中,确定写入innodb的binlog位置,backtrace如下 #0  mysql_bin_log_commit_pos #1  0x00000000007c88d4 in innobase_commit_ordered_low #2  0x00000000007cca97 in innobase_commit_ordered #3  0x000000000071efc5 in run_commit_ordered #4  MYSQL_BIN_LOG::trx_group_commit_leader #5  0x000000000071f49d in MYSQL_BIN_LOG::write_transaction_to_binlog_events #6  0x000000000071f681 in MYSQL_BIN_LOG::write_transaction_to_binlog #7  0x000000000071ff6b in binlog_flush_cache #8  binlog_commit_flush_trx_cache #9  MYSQL_BIN_LOG::log_and_order #10 0x000000000068a112 in […]