简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别_m序列的产生方法

简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别_m序列的产生方法[toc] 背景 应用端需要生成依次递增的序列来做流水序号等,方案有1、redis /MySQL SEQUENCE引擎生成序列;2、MySQL中myisam表 replace into方式;3、MyS

MySQL MyISAM和Innodb表生成序列 - Jia


背景

应用端需要生成依次递增的序列来做流水序号等,方案有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)

代码100分

但存在问题:
myisam表非事务存储引擎,备份存在不一致(恢复还原数据有不一致风险);
myisam也不是crash-safe的;
gtid模式下,同一个事务中不能操作myisam表和innodb表

为什么不用innodb表replace into方式了?
该方式并发大时,存在发生死锁的风险


  • MySQL中事务性 innodb表INSERT … ON DUPLICATE KEY,是crash-safe ,看起来myisam生成序列的存在的问题它都没有!实际情况了?
    使用方式:
代码100分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方式
代码100分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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/9236.html

(0)
上一篇 2023-02-12
下一篇 2023-02-12

相关推荐

  • 使用Pycharm进行Python编程

    使用Pycharm进行Python编程Pycharm是一款被广泛应用于Python编程的集成开发环境,其提供了一系列丰富的工具和功能来提高我们的工作效率和代码质量。无论是从初学者到专业开发者,都能从Pycharm中获得巨大的好处。本文将会探讨Pycharm的重要特性以及如何利用这些特性来提高我们的Python编程能力。

    2024-04-10
    82
  • 紫金云大数据_数据架构设计

    紫金云大数据_数据架构设计一、总体设计 初来公司时,公司还没有大数据,我是作为大数据架构师招入的,结合公司的线上和线下业务,制定了如下的大数据架构路线图。 二、大数据任务开发和调度平台架构设计 在设计完总体架构后,并且搭建完h

    2023-02-17
    142
  • Python实现访问数据库的API接口设计

    Python实现访问数据库的API接口设计SQLAlchemy是一个Python SQL工具和对象关系映射器(ORM),可以方便地实现访问数据库的API接口,适用于多种关系型数据库。它提供了一种简单的方式来定义数据模型,并将其映射到数据库模式。相比于直接使用SQL语句,SQLAlchemy可以轻松地修改数据库模型而不用修改SQL语句。此外,SQLAlchemy还提供了一些高级功能,例如连接池、事务、数据库迁移等,使得访问数据库变得更加方便和可靠。

    2023-12-05
    117
  • Redis系列(九):Redis的事务机制

    Redis系列(九):Redis的事务机制Redis的事务机制。

    2023-03-29
    144
  • 了解Python Charm

    了解Python CharmPython被誉为一种高级编程语言,而Python Charm(以下简称Charm),是一款为Python语言特别设计的集成开发环境(Integrated Development Environment,IDE)。就像当初Ruby on Rails环境以Ruby为核心一样,Charm在Python开发领域也取得了广泛的认可。

    2024-07-07
    56
  • mysql的游标怎么建立循环_游标角度尺的读数方法图解

    mysql的游标怎么建立循环_游标角度尺的读数方法图解一、游标简介 1、游标简介 游标是一个存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句检索出来的结果集。有了游标可以方便的对该结果集进行逐行处理。 游标的设计是一种数据…

    2023-03-08
    158
  • mysql5.7.32解压版安装_mysql5.7安装教程

    mysql5.7.32解压版安装_mysql5.7安装教程下载 mysql 的 解压版安装文件mysql-5.7.25-winx64.zip D:mysqlmaster D:mysqlsalve 分别新建 data 和 binlog 目录,以及配置文件 m…

    2023-02-12
    146
  • Python Tkinter Radiobuttons: 界面选项的交互性控制

    Python Tkinter Radiobuttons: 界面选项的交互性控制Radiobuttons 是Tkinter库中的一个可用控件,用于创建多个互斥的选项。每个选项是一个圆形按钮,用户只能选择其中的一个选项。Radiobuttons控件非常有用,可以用来设计交互性很强的用户界面。

    2024-03-09
    85

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注