InnoDB inplace-update加锁流程分析

线上遇到一起死锁问题,一条DELETE语句与一条UPDATE语句产生了死锁,经过和印风的讨论分析找到原因:DELETE语句通过二级索引删除记录,加锁顺序:二级索引(WHERE使用到二级索引)–>主键索引 –> 所有其它二级索引,UPDATE语句的加锁顺序:二级索引(WHERE条件使用二级索引)–>主键索引 –>包含更新字段的其它二级索引,由于DELETE操作更新了UPDATE语句WHERE条件使用到的索引,这导致DELETE与UPDATE加锁顺序相反,导致死锁

为了进一步研究InnoDB update操作加锁流程,进行了下列实验(update操作为inplace-update),关于mysql update的上层调用可以参考: MySQL update语法SQL解析源码分析Oracle/PostgreSQL UPDATE…RETURNING…在MySQL中的实现
[……]

继续阅读

MySQL statement timeout特性

这个特性是twitter开发的,点击查看详情,目前已经backport到AliMySQL中,正在测试中,首先简单介绍一下功能

特性描述:

1)statement timemout特性中,SELECT必须是top-level,不能是子查询或者union中的除第一个SELECT之外的SELECT
2)语句级别:为SELECT增加一个hint: max_statement_time指定查询最大执行时间,当执行时间超过max_statement_time后,查询自动中断(连接不中断)
3)session级别:允许超级用户grant其它用户一个指定的max_statement_time,该用户连接后默认使用该值(用户可在session中临时修改),每个SELECT执行时间都不会超过max_statement_time
4)没有grant max_statement_time或grant max_statement_time 0的用户,除非在query中指定max_statement_time hint,否则查询执行时间不受限制
[……]

继续阅读

一个MySQL子查询与Order By问题分析

问题背景

产品DBA在做日常SQL REVIEW时,遇到一个问题:一个包含子查询的query,使用order by(order by query)竟然比不使用order by(normal query)执行时间更短,而且是在order by无法使用index排序的情况下(使用filesort),这个问题不好解释,只能借助一些工具以及跟踪代码寻找原因

MySQL版本

现象在Percona 5.5.18和Oracle MySQL 5.1.48上都存在,本文数据和分析基于Percona 5.5.18
[……]

继续阅读

MySQL XA限制与修复

背景知识

MySQL的XA分为内部XA和外部XA,采用的协议是经典的2PC(2-Phase-Commit)

MySQL内部XA主要用于多个存储引擎之间的事务处理,由binlog作为Transaction Coordinator,事务提交过程中协调各个参与者(事务存储引擎)prepare,commit/rollback,各个事务存储引擎在prepare阶段基本做完了所有的事情(除了写commit标志,释放资源),对于InnoDB存储引擎,提交一个事务的流程如下:(图片来自登博)

commit
[……]

继续阅读

MySQL 16进制字符串与编码

实验:

a) 系统环境:

$echo $LANG
en_US.UTF-8
CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `str` varchar(128) CHARACTER SET utf8 DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

[……]

继续阅读

MySQL binlog字符编码方式

问题背景

希望根据MySQL binlog回滚已经提交的事务,一个重要的应用场景:回滚误操作,淘宝智胜在这方面做了很多工作,详情参考利用MySQL日志模拟恢复数据变化轨迹, 利用MySQL日志模拟恢复数据变化轨迹II,最近遇到了一些字符集相关问题,回滚失败。这篇文章旨在分析MySQl binlog中与表操作相关的字符集。

实验测试:

a) 系统字符集,保证能够支持中文

$echo $LANG
en_US.UTF-8

[……]

继续阅读

FLUSH TABLES WITH READ LOCK

本分析基于 Percona Server 5.5.18

FLUSH TABLES WITH READ LOCK 作用

1. 对于myisam存储引擎,从数据库外部拷贝.frm,.fyd,.fyi文件后,执行FLUSH TABLES/FLUSH TABLES WITH READ LOCK后,就可以使用新表了,这个功能非常有用,备份变得格外简单
2. mysqldump中从主库中拉出一个副本后通过change master后就可以快速搭建slave,为了获得一个一致性点,一般会使用参数–single-transaction和–master-data,它会使用FLUSH TABLES WITH READ LOCK阻塞事务commit写binlog来获得transaction开始时主库binlog位置
3. 与FLUSH TABLES相似,清空table_cache

除了这几个重要作用外,目前还没有发现其他用处,而且对于InnoDB存储引擎,第一条就没用了
[……]

继续阅读

InnoDB vs. TokuDB 写入性能测试

应用场景:

频繁插入/删除一个表中的数据,没有查询,需要评估InnoDB vs. TokuDB插入性能

TokuDB在开源后获得了大量关注,其采用的fractal tree相对于b+tree有着很好的随机插入性能,而查询性能也不低,How TokuDB Tree Indexes Work中介绍了其基本原理和理论性能公式,感兴趣可以阅读,本文将重点focus在性能数据上。

版本信息

mysql> select @@version;
+-------------------------+
| @@version               |
+-------------------------+
| 5.5.30-tokudb-7.0.1-log |
+-------------------------+
1 row in set (0.00 sec)

测试场景(一)

n个线程并发插入total_records条记录
[……]

继续阅读

Limit innodb dictionary cache size

知识背景

MySQL中每个SELECT/DML/DDL在执行之前需要打开相关的表,执行结束后将它们关闭,为了避免重复打开/关闭的开销,server层提供了table cache和table definition cache用来缓存打开的表信息,在SELECT/DML/DDL执行之前首先从table cache中取空闲表,cache中没有相应表才真正打开表,执行结束后将表置为空闲并放入到table cache中;关于这部分的代码分析可以参考之前写的一篇博客;同时,table cache与MDL一起控制表的并发访问,这部分内容打算之后总结出一篇博客

innodb实现了dict_sys,在内存中缓存了载入过的表信息,包括表的元数据信息(表名,space,列信息,索引,外键等),还包括运行时的信息(有多少handler打开了该表,表上加锁信息,运行时统计信息),具体可以参考数据结构dict_table_struct
[……]

继续阅读

Oracle/PostgreSQL UPDATE…RETURNING…在MySQL中的实现

需求描述

最近开发提了这样一个需求:

BEGIN;
UPDATE products SET quantity=quantity-1 WHERE product_id=123456;
SELECT quantity FROM products WHERE product_id=123456;
COMMIT;

在一个事务中UPDATE之后需要SELECT出更新后的值,希望在MySQL中能只使用一条SQL就能做到,这样既可以方便开发,又可以大大减小事务处理时间,其实这个需求在Oracle/PostgreSQL中已经有相应的语法支持,PostgreSQL UPDATE,实现这个需求还有一个前提:不修改MySQL服务器/客户端协议,能够兼容JDBC
[……]

继续阅读