Mysql中悲观锁与乐观锁应用介绍
[var]
生活中:锁在我们身边无处不在,比如我出门玩去了需要把门锁上,比如我需要把钱放到保险柜里面,必须上锁以保证我财产的安全。
代码中:比如多个线程需要同时操作修改共享变量,这时需要给变量上把锁(syncronized),保证变量值是对的。
数据库表:当多个用户修改表中同一数据时,我们可以给该行数据上锁(行锁)。
sql脚本
CREATE TABLE `sys_user` (
`id` bigint(20) NOT NULL COMMENT ‘主键ID’,
`name` varchar(30) DEFAULT NULL COMMENT ‘姓名’,
`age` int(11) DEFAULT NULL COMMENT ‘年龄’,
`email` varchar(50) DEFAULT NULL COMMENT ‘邮箱’,
`deleted` tinyint(1) DEFAULT NULL COMMENT ‘是否删除’,
`create_time` datetime DEFAULT NULL COMMENT ‘创建时间’,
`create_id` bigint(20) DEFAULT NULL COMMENT ‘创建人’,
`update_id` bigint(20) DEFAULT NULL COMMENT ‘操作人’,
`update_time` datetime DEFAULT NULL COMMENT ‘更新时间’,
`status` varchar(255) DEFAULT NULL COMMENT ‘状态’,
`dog` text DEFAULT NULL COMMENT ‘狗’,
`version` int(11) DEFAULT NULL COMMENT ‘版本号’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `sys_user`(`id`, `name`, `age`, `email`, `deleted`, `create_time`, `create_id`, `update_id`, `update_time`, `status`, `dog`, `version`) VALUES (1, ‘gukong’, 19, ‘test1@baomidou.com’, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0);
`id` bigint(20) NOT NULL COMMENT ‘主键ID’,
`name` varchar(30) DEFAULT NULL COMMENT ‘姓名’,
`age` int(11) DEFAULT NULL COMMENT ‘年龄’,
`email` varchar(50) DEFAULT NULL COMMENT ‘邮箱’,
`deleted` tinyint(1) DEFAULT NULL COMMENT ‘是否删除’,
`create_time` datetime DEFAULT NULL COMMENT ‘创建时间’,
`create_id` bigint(20) DEFAULT NULL COMMENT ‘创建人’,
`update_id` bigint(20) DEFAULT NULL COMMENT ‘操作人’,
`update_time` datetime DEFAULT NULL COMMENT ‘更新时间’,
`status` varchar(255) DEFAULT NULL COMMENT ‘状态’,
`dog` text DEFAULT NULL COMMENT ‘狗’,
`version` int(11) DEFAULT NULL COMMENT ‘版本号’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `sys_user`(`id`, `name`, `age`, `email`, `deleted`, `create_time`, `create_id`, `update_id`, `update_time`, `status`, `dog`, `version`) VALUES (1, ‘gukong’, 19, ‘test1@baomidou.com’, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0);
[var]
当我们要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发的发生。
为什么叫做悲观锁呢?因为这是一种对数据的修改抱有悲观态度的并发控制方式。我们一般认为数据被并发修改的概率比较大,所以需要在修改之前先加锁。
数据库中的行锁,表锁,读锁,写锁,以及 syncronized 实现的锁均为悲观锁。
mysql开启悲观锁,示例sql语句
–开启事务
BEGIN
–对行加锁
SELECT * FROM `sys_user` where id = 1 for UPDATE
–修改加锁行的数据
update sys_user set name = ‘gukong’,age = 18 where id = 1;
–提交事务
commit;
BEGIN
–对行加锁
SELECT * FROM `sys_user` where id = 1 for UPDATE
–修改加锁行的数据
update sys_user set name = ‘gukong’,age = 18 where id = 1;
–提交事务
commit;
–开启事务
BEGIN
–对行加锁
SELECT * FROM `sys_user` where id = 1 for UPDATE
–修改加锁行的数据
update sys_user set name = ‘kulilin’,age = 20 where id = 1;
–提交事务
commit;
update sys_user set name = ‘kulilin’,age = 20 where id = 1;
BEGIN
–对行加锁
SELECT * FROM `sys_user` where id = 1 for UPDATE
–修改加锁行的数据
update sys_user set name = ‘kulilin’,age = 20 where id = 1;
–提交事务
commit;
update sys_user set name = ‘kulilin’,age = 20 where id = 1;
[var]
乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁,只有到数据提交的时候才通过一种机制来验证数据是否存在冲突。
乐观锁通常是通过在表中增加一个版本(version)或时间戳(timestamp)来实现,其中,版本最为常用。
乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。
乐观锁示例:
— version = 0
SELECT * FROM `sys_user` where id = 1
update sys_user set name=’小明’,version = version+1 and age = 20 where id = 1 and version = 0;
— version = 0 ,而此时version=1,更新失败
SELECT * FROM `sys_user` where id = 1
update sys_user set name = ‘小红’ version = version+1 and age = 25 where id = 1 and version = 0;
SELECT * FROM `sys_user` where id = 1
update sys_user set name=’小明’,version = version+1 and age = 20 where id = 1 and version = 0;
— version = 0 ,而此时version=1,更新失败
SELECT * FROM `sys_user` where id = 1
update sys_user set name = ‘小红’ version = version+1 and age = 25 where id = 1 and version = 0;
[var]
乐观锁适用于读多写少的场景,可以省去频繁加锁、释放锁的开销,提高吞吐量
在写比较多的场景下,乐观锁会因为版本不一致,不断重试更新,产生大量自旋,消耗 CPU,影响性能。这种情况下,适合悲观锁
到此这篇关于Mysql中悲观锁与乐观锁应用介绍的文章就介绍到这了,更多相关Mysql悲观锁与乐观锁内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!