mysql 用存储过程和函数分别模拟序列
在其他大部分DBMS里都有序列的概念,即Sequence或Generator。
而mysql里没有,但有时真的很有用。下面分别用存储过程和函数来模拟序列,并用程序模拟并发场景来测试原子性和完整性,是否能达到预期。
序列表定义如下:
CREATE TABLE `seq` (
`id` BIGINT(20) NOT NULL,
`busi` VARCHAR(50) NULL DEFAULT NULL,
`val` BIGINT(20) NULL DEFAULT NULL,
`remark` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
先把模拟调用程序放这里,因为它是不变的:
for (int j = ; j < ; j++)
{
Thread t1 = new Thread(() =>
{
for (int i = ; i < ; i++)
{
using (var db = new DbCtxt())
{
//long val = db.Sql("select nextval();").QuerySingle<long>();
long val = db.Sql("call nextval();").QuerySingle<long>();
Console.WriteLine(val+" = "+Thread.CurrentThread.ManagedThreadId);
}
}
});
t1.Start();
}
1、假设存储过程不加事务,读取时不for update
declare v bigint ;
-- start transaction;
set v = (select val from seq where busi = 'mat');
set v = v + 1;
update seq set val = v where busi = 'mat';
-- commit;
select v;
测试结果:会出现并发读和写数据,现象就是预期序列增加1000,实际每次测试都是增加700~800不定。
2、假设存储过程不加事务,读取时加for update
declare v bigint ;
-- start transaction;
set v = (select val from seq where busi = 'mat' for update);
set v = v + 1;
update seq set val = v where busi = 'mat';
-- commit;
select v;
测试结果:会出现并发读和写数据,现象就是预期序列增加1000,实际每次测试都是增加700~800不定。
3、假设存储过程加事务,读取时不加for update
declare v bigint ;
start transaction;
set v = (select val from seq where busi = 'mat' );
set v = v + 1;
update seq set val = v where busi = 'mat';
commit;
select v;
测试结果:每次测试都会出现 Deadlock死锁,并且是很快(val增加不到100)就出现死锁。
4、假设存储过程加事务,读取时也加for update
declare v bigint ;
start transaction;
set v = (select val from seq where busi = 'mat' for update);
set v = v + 1;
update seq set val = v where busi = 'mat';
commit;
select v;
测试结果:多线程读取,预期序列增加1000,实际每次测试都增加1000,符合预期。
5、用函数模拟,函数不允许显示或隐式的开启事务,先测试读取时不加for update
declare v bigint ;
-- start transaction;
set v = (select val from seq where busi = 'mat' );
set v = v + 1;
update seq set val = v where busi = 'mat';
-- commit;
return v;
测试结果:多线程读取,预期序列增加1000,实际每次测试都增加1000,符合预期。
6、用函数模拟,测试读取时加for update
declare v bigint ;
-- start transaction;
set v = (select val from seq where busi = 'mat' for update);
set v = v + 1;
update seq set val = v where busi = 'mat';
-- commit;
return v;
测试结果:多线程读取,预期序列增加1000,实际每次测试都增加1000,符合预期。
总结:若用函数模拟最为简单,不用考虑是否锁定行for update,调用方式 select nextval();
若用存储过程模拟,必须要考虑锁定行for update,且多sql前后要加事务管理,调用方式 call nextval();
mysql 用存储过程和函数分别模拟序列的更多相关文章
- MySQL:存储过程和函数
存储过程和函数 一.创建存储过程和函数 1.创建存储过程 语法: CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic . ...
- MYSQL的存储过程和函数简单写法
存储过程 MySQL中,创建存储过程的基本形式如下: CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] ro ...
- Mysql中存储过程和函数的写法
MySQL中,创建存储过程的基本形式如下: CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine ...
- MySQL之存储过程和函数
存储过程和函数: 1.创建存储过程和函数: 存储过程: delimiter $$ create procedure proc_name() BEGIN 查询语句; // 记得加分号 END $$ de ...
- mysql的存储过程,函数,事件,权限,触发器,事务,锁,视图,导入导出
1.创建过程 1.1 简单创建 -- 创建员工表 DROP TABLE IF EXISTS employee; CREATE TABLE employee( id int auto_increment ...
- mySQL查看存储过程、函数、视图、触发器
一.查看存储过程 1.show procedure status; //查看所有的 2.show create procedure proc_AllUser[proc_name]; 查看proc_Al ...
- navicat 给mysql 添加存储过程(函数)
BEGIN DECLARE i INT default 0; DECLARE num int default 0; DECLARE count1 int default 0; DECLARE coun ...
- 我的MYSQL学习心得(十) 自定义存储过程和函数
我的MYSQL学习心得(十) 自定义存储过程和函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心 ...
- MySQL 存储过程和函数
概述 一提到存储过程可能就会引出另一个话题就是存储过程的优缺点,这里也不做讨论,一般别人问我我就这样回答你觉得它好你就用它.因为mysql中存储过程和函数的语法非常接近所以就放在一起,主要区别就是函数 ...
随机推荐
- Redis Sentinel基本介绍(翻译以及总结)
目录 Redis Sentinel介绍 分布式的Redis Sentinel 快速开始 获取Sentinel 启动Sentinel 部署Sentinel的基本要求 配置Sentinel 其他的Sent ...
- MySql数据库远程连接失败问题解决
例如,你想myuser使用mypassword从任何主机连接到mysql服务器的话. GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY ...
- WebAPI开发中的定时处理
https://blog.csdn.net/lordwish/article/details/77931897
- asp.net mvc5 分析器错误消息: 未能加载类型“XXX.MvcApplication”
描述 今天忽然碰到一个这个错误: “/”应用程序中的服务器错误. 分析器错误 说明: 在分析向此请求提供服务所需资源时出错.请检查下列特定分析错误详细信息并适当地修改源文件. 分析器错误消息: 未能加 ...
- 命名空间“Microsoft”中不存在类型或命名空间名“Reporting”(是否缺少程序集引用?)
IDE升级到VS2017之后,出现了如题所示的报错,重新引用DLL的方法如下: 1.右键引用,选择添加引用. 2.左侧选择浏览,下面点击浏览按钮. 3.分别添加Microsoft.ReportView ...
- 在ASP.NET MVC中使用区域来方便管理controller和view
在ASP.NET MVC中使用区域来方便管理controller和view 在mvc架构中,一般在controllers和views中写所有控制器和视图, 太多控制器时候,为了方便管理,想要将关于pe ...
- 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之三(配置文件读取)
干了一天的活,还有点时间,给兄弟们写点东西吧. 大家有没有发现一个问题?那就是在.Net Core的MVC项目里面,没有.config文件了!!!同志们,没有config文件了啊,这样搞,我以后要做些 ...
- JVM中的对象生命周期
在JVM运行空间中,对象的整个生命周期大致可以分为七个阶段:创建阶段(Creation).应用阶段(Using).不可视阶段(Invisible).不可到达阶段( Unreachable).可收集阶段 ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- 使用BeanUitls提高对象拷贝效率
首先来创建两个bean 注:一定要有set/get方法,成员变量必须要同名 public class User1 { String name; String password; String phon ...