MySQL MyISAM和Innodb表生成序列
背景
应用端需要生成依次递增的序列来做流水序号等,方案有1、redis /MySQL SEQUENCE引擎生成序列;2、MySQL中myisam表 replace into方式;3、MySQL中innodb表INSERT ... ON DUPLICATE KEY方式
分析
- redis /MySQL SEQUENCE引擎生成序列,但多个MySQL集群都有生成序列的需求,若出问题,影响范围大;redis /MySQL SEQUENCE中生成序列也增加了研发修改代码的成本,新项目可以使用这种方式
- MySQL中myisam表 replace into 是我们目前使用生成序列的方式(虽然是表锁,每秒生成的序列也满足得了需求),使用方式为
CREATE TABLE `test_sequence` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`val` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `val` (`val`)
) ENGINE=MyISAM;
>replace into test_sequence(val) values(99);
Query OK, 1 row affected (0.00 sec)
>select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 1 |
+------------------+
1 row in set (0.00 sec)
>replace into test_sequence(val) values(99);
Query OK, 2 rows affected (0.00 sec)
>select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
但存在问题:
myisam表非事务存储引擎,备份存在不一致(恢复还原数据有不一致风险);
myisam也不是crash-safe的;
gtid模式下,同一个事务中不能操作myisam表和innodb表为什么不用innodb表replace into方式了?
该方式并发大时,存在发生死锁的风险
- MySQL中事务性 innodb表INSERT ... ON DUPLICATE KEY,是crash-safe ,看起来myisam生成序列的存在的问题它都没有!实际情况了?
使用方式:
CREATE TABLE `test_sequence2` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`val` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `val` (`val`)
) ENGINE=InnoDB;
00>insert into test_sequence2(val) values(99) on duplicate key update id=id+1;
Query OK, 1 row affected (0.00 sec)
39>select id from test_sequence2;
+---------+
| id |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
22>insert into test_sequence2(val) values(99) on duplicate key update id=id+1;
Query OK, 2 rows affected (0.00 sec)
25>select id from test_sequence2;
+---------+
| id |
+---------+
| 2 |
+---------+
1 row in set (0.00 sec)
测试
普通机械磁盘机器
MySQL5.7.16
RR隔离级别
sysbench 自定义sql语句测试tps(每秒生成多少序列)
- myisam replace into 方式
cd /usr/share/sysbench/tests
sysbench ./test_myisam.lua --mysql-host=127.0.0.1 --mysql-port=3701 --mysql-db=test --mysql-user=sysbench --mysql-password=sysbench --tables=1 --threads=10 --time=30 --report-interval=5 run
- innodb INSERT ... ON DUPLICATE KEY UPDATE方式
cd /usr/share/sysbench/tests
sysbench ./test_innodb.lua --mysql-host=127.0.0.1 --mysql-port=3701 --mysql-db=test --mysql-user=sysbench --mysql-password=sysbench --tables=1 --threads=10 --time=30 --report-interval=5 run
| myisam replace into | innodb insert..on duplicate | |
|---|---|---|
| 1并发线程 | 124 tps | 122 tps |
| 10并发线程 | 123 tps | 121 tps |
| 20并发线程 | 125 tps | 104 tps |
| 30并发线程 | 127 tps | 67 tps |
| 40并发线程 | 127 tps | 33 tps |
- 可见myisam随着并发线程数的增加,replace into tps保持不变,原因是myisam是表锁,同一时刻,该表只能写或者只能读
- innodb表随着并发数的上升,insert..on duplicate tps不升反降,行锁之前的争用变大了 造成锁等待
- 本次测试机器配置差,结果有些参考性,线上机器配置更好
注意 mysqlslap 压测innodb表40个并发线程时可能会出现死锁(RC隔离级别也是),死锁详细见最后
为什么sysbench40 并发线程测试没有出现过死锁?难道sysbench并发线程不是同一时刻发出的?_
/usr/local/mysql/bin/mysqlslap -usysbench -h127.0.0.1 -P3701 -p --concurrency=40 --iterations=1 --create-schema=test --query='insert into test_sequence2(val) values(99) on duplicate key update id=id+1;select id from test_sequence2;'
/usr/local/mysql/bin/mysqlslap: Cannot run query insert into test_sequence2(val) values(99) on duplicate key update id=id+1;select id from test_sequence2; ERROR : Deadlock found when trying to get lock; try restarting transaction
结论
- myisam表 replace into生成序列是稳定的方法,不管并发线程数多少,生成序列速度是稳定的,但myisam表存在缺陷问题
- innodb表 inert on duplicate 生成序列适合并发线程数少情况,并发线程数多会出现死锁 生成序列速度下降情况
- 若要求生成序列的速度快,可用redis /MySQL SEQUENCE方式
死锁日志
LATEST DETECTED DEADLOCK
------------------------
2020-02-11 11:03:11 0x7f6a0c643700
*** (1) TRANSACTION:
TRANSACTION 39260727, ACTIVE 1 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 28 lock struct(s), heap size 3520, 26 row lock(s), undo log entries 1
MySQL thread id 460828, OS thread handle 140093451958016, query id 21296424 127.0.0.1 root update
insert into test_sequence2(val) values(99) on duplicate key update id=id+1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 48 page no 4 n bits 72 index val of table `test`.`test_sequence2` trx id 39260727 lock_mode X waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 1; hex e3; asc ;;
1: len 8; hex 000000000000001a; asc ;;
*** (2) TRANSACTION:
TRANSACTION 39260729, ACTIVE 1 sec updating or deleting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
29 lock struct(s), heap size 3520, 27 row lock(s), undo log entries 1
MySQL thread id 460835, OS thread handle 140093451155200, query id 21296425 127.0.0.1 root update
insert into test_sequence2(val) values(99) on duplicate key update id=id+1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 48 page no 4 n bits 72 index val of table `test`.`test_sequence2` trx id 39260729 lock_mode X
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 1; hex e3; asc ;;
1: len 8; hex 000000000000001a; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 48 page no 3 n bits 168 index PRIMARY of table `test`.`test_sequence2` trx id 39260729 lock_mode X waiting
Record lock, heap no 37 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 8; hex 000000000000001b; asc ;;
1: len 6; hex 000002571237; asc W 7;;
2: len 7; hex b6000001680110; asc h ;;
3: len 1; hex e3; asc ;;
*** WE ROLL BACK TRANSACTION (1)
自定义sysbench脚本
less test_myisam/innodb.lua
require("oltp_common")
function thread_init(thread_id)
drv=sysbench.sql.driver()
con=drv:connect()
end
function event(thread_id)
local vid1
local dbprefix
con:query('replace into test_sequence(val) values(99)')
con:query('select last_insert_id()')
##innodb insert..on duplicate 语句
#con:query('insert into test_sequence2(val) values(99) on duplicate key update id=id+1')
#con:query('select id from test_sequence2;')
end
function thread_done()
con:disconnect()
end
MySQL MyISAM和Innodb表生成序列的更多相关文章
- Mysql MyISAM与InnoDB 表锁行锁以及分库分表优化
一. 两种存储引擎:MyISAM与InnoDB 区别与作用 1. count运算上的区别: 因为MyISAM缓存有表meta-data(行数等),因此在做COUNT(*)时对于一个结构很好的查询是不需 ...
- mysql myisam转innodb的2种方法
mysql myisam转innodb的2种方法 mysql中的myisam和innodb有什么区别.一个好比便利店,一个好比大型购物中心,他们是为了适应不同的场合而存在的.当流量比较小,我们可以 ...
- MySQL MyISAM和InNodb备份与恢复技巧
1. 为什么要备份数据库 对数据库来说,最重要也最容易被忽视的就是备份.由于不可预测性,偶然的事件可能会导致非常惨重的损失. 数据越是重要,数据的变化越频繁,备份越发需要经常进行. 备份周期根据不同业 ...
- MySql MyISAM和InnoDB的区别
MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的 顺序访问方法) 的缩写,它是存储记录和文件的标准方法. ...
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点分析
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- MYSQL MyISAM与InnoDB对比
1. 区别: (1)事务处理: MyISAM是非事务安全型的,而InnoDB是事务安全型的(支持事务处理等高级处理): (2)锁机制不同: MyISAM是表级锁,而InnoDB是行级锁: (3)sel ...
- 【mysql】关于InnoDB表text blob大字段的优化
最近在数据库优化的时候,看到一些表在设计上使用了text或者blob的字段,单表的存储空间已经达到了近100G,这种情况再去改变和优化就非常难了 一.简介 为了清楚大字段对性能的影响,我们必须要知道i ...
- MySQL如何判别InnoDB表是独立表空间还是共享表空间
InnoDB采用按表空间(tablespace)的方式进行存储数据, 默认配置情况下会有一个初始大小为10MB, 名字为ibdata1的文件, 该文件就是默认的表空间文件(tablespce file ...
随机推荐
- 微软手机 能靠Surface Phone卷土重来吗?
能靠Surface Phone卷土重来吗?" title="微软手机 能靠Surface Phone卷土重来吗?"> 就算整体大环境再好,就算是站在风口之上,也总是 ...
- Hi3518_SDK
第一章 Hi3518_SDK_Vx.x.x.x版本升级操作说明 如果您是首次安装本SDK,请直接参看第2章. 第二章 首次安装SDK 1.Hi3518 SDK包位置 在"Hi3518_V10 ...
- 2020年JAVA大厂笔经面经
个人简介 Java后台开发方向. 非计算机专业硕士,专业涉及到一些开发. 实验室项目主要是Java Web系统,挖掘小亮点. 无实习经验. 闲话唠嗑 回顾这几个月,宛若梦一场. 一开始心态不好 ...
- 小程序中,设置Sticky定位,距离上面会有一个缝隙
近日,在小程序中使用sticky定位实现吸顶效果,不料入了一个大坑. 定位后,距离有position: relative:的上级元素有个1px大小的缝隙条,透过缝隙,滑动时可看到定位标题下的内容. 此 ...
- 简单的员工管理系统(Mysql+jdbc+Servlet+JSP)
员工管理系统 因为学业要求,需要完成一个过关检测,但是因为检测之前没有做好准备,且想到之前用mysql+jdbc+Struts2+bootstrap做成了一个ATM系统(主要有对数据的增删改查操作), ...
- 安装Kubernetes集群时遇到的问题及解决方法
在搭建Kubernetes集群时遇到一些问题,记录在这里. 搭建过程在另一篇文章:VirtualBox上使用kubeadm安装Kubernetes集群 1. 虚拟机安装完CentOS7登录时遇到war ...
- XXE学习(一)——XML基础
XXE学习(一)——xml基础 一.XML简介 XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据 ...
- 前端每日实战:39# 视频演示如何用纯 CSS 创作一个表达怀念童年心情的条纹彩虹心特效
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/QxbmxJ 可交互视频教程 此视频 ...
- psql的jsonb操作--存储对象/对象数组
1. 建表 create table demo( id serial NOT NULL PRIMARY KEY, name ), info JSONB ); 2.存储对象操作 2.1添加 insert ...
- 研究开源源码之Myrmec
好久没写博客了,自己也弄不清是懒了还是忙了.毕竟白天需要工作,晚上有时候看看资料,有时候陪家人,有时候约朋友......更加累了,可能由于累了就懒得总结了. 今天有同事问我关于代码检查文件类型的问题. ...