此处的big sql指的是单条sql的size 超过innodb_log_file_size,通过构造这样的测试,来分析mysql的提交过程。
做这个分析的起因是我不是很明白,既然mysql需要将被执行的数据首先写入到redo log file,如果sql 的size 超过innodb_log_file_size的设定,会发生什么样的行为,mysql是否会拒绝这样的big sql?
首先将答案抛出:mysql能够吃下这样的大SQL,并顺利执行。
1 sql 提交时,mysql服务器首先通过参数max_allowed_packet检查sql的size,如果超出,则直接提示mysql go away.
2 server从存储将需要修改的数据page load到innodb_buffer_pool(受制于innodb_buffer_pool_size)。
3 写data page,同时写redo undo log.(undo log 负责备份未修改前的数据,redo负责备份修改后的数据)
4 如果sql size 超过redo undo log 的buffer设定(innodb_log_buffer_size)则:redo undo log 写入磁盘文件log file,如果此时log file也满,则将部分data写入磁盘,然后清空对应的log file。(猜测)
这样的变化可以通过参数Innodb_log_waits (show global status)观察到。
因此,一般情况下,redo log 先于data 落盘,但是在Big sql这种提交方式下,是数据先落盘,redo log 后落盘,在这个例子中,redo log是没有任何意义的,因为它已经无法完整了(猜测)。
5 当 commit 发生时,一般来说,mysql 会首先提交reod log 到磁盘,但是针对这样的情况,应该首先提交数据更为合理。
一些自己的理解,肯定有不合理的地方,期待更好的解释。
步骤:
1 创建测试表
big 字段类型为longblob,它的最大容量是4G.
CREATE TABLE `tb_cobranding_test` (
`id` int(10) unsigned DEFAULT NULL,
`base64_content_big` longblob
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2 修改mysql配置:
innodb_log_file_size=5M
innodb_log_files_in_group=2
max_allowed_packet=512M
修改innodb_log_file_size 前需要迁移之前的log file 文件.
3 提交big sql:
insert into tb_cobranding_test values (1,'此处为190M的二进制字符串');
mysql <./big.sql