mysql锁

来源:互联网 发布:网络拓扑管理 编辑:程序博客网 时间:2024/05/07 19:58

mysql 锁,这个相信很多人的有听到过,但是没有具体去了解它,我自己也是在学习阶段,一边学习一边总结了一下

①,mysql 锁是什么

   简单说,就是lock table,不让别人动

②,mysql 有哪些锁 

     共享锁(写锁)时,别人能读,不能改变量表数据

    排它锁(读锁)时,别人既不能读,也不能改表数据

    表锁:直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果你是写锁,则其它进程则读也不允许

    行锁(InnoDBInnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!)

 :仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作

    页锁(BDB) :表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。

     ②-① 行锁和表锁优点对比 

行级锁定的优点(不是事务):
·         当在许多线程中访问不同的行时只存在少量锁定冲突。
·         回滚时只有少量的更改。
·         可以长时间锁定单一的行。

行级锁定的缺点(不是事务)
·         比页级或表级锁定占用更多的内存。
·         当在表的大部分中使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。
·         如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多。
·         用高级别锁定,通过支持不同的类型锁定,你也可以很容易地调节应用程序,因为其锁成本小于行级锁定。

行级锁的优点有(事务):
在很多线程请求不同记录时减少冲突锁。
  事务回滚时减少改变数据。
  使长时间对单独的一行记录加锁成为可能。

行级锁的缺点有:
  比页级锁和表级锁消耗更多的内存。
  锁是计算机协调多个进程或线程并发访问某一资源的机制,不同的数据库的锁机制大同小异。由于数据库资源是一种供许多用户共享的资源,所以如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。了解锁机制不仅可以使我们更有效的开发利用数据库资源,也使我们能够更好地维护数据库,从而提高数据库的性能。 

③,使用锁的优缺点

      好处就是,保证数据的原子性,完整性,一致性。 只有加锁者释放了锁,别人才能改变数据。

     缺点就是,增加了系统开销,有可能产生锁等待,造成数据库运行异常。这都是不正常的使用锁

④,mysql 锁并发控制

   我们可以同悲观锁和乐观锁来实现,
    悲观锁:取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结才能继续 

    乐观锁:取数据,更新时检查是否数据已被更新,如果是取消当前更新,一般在悲观锁的等待时间过长而不能接受才会选择乐观锁 

   悲观锁的实现:

使用场景举例:以MySQL InnoDB为例

商品goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。

 

1如果不采用锁,那么操作方法如下:

//1.查询出商品信息

select status from t_goods where id=1;

//2.根据商品信息生成订单

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status为2

update t_goods set status=2;

 

上面这种场景在高并发访问的情况下很可能会出现问题。

前面已经提到,只有当goods status为1时才能对该商品下单,上面第一步操作中,查询出来的商品status为1。但是当我们执行第三步Update操作的时 候,有可能出现其他人先一步对商品下单把goods status修改为2了,但是我们并不知道数据已经被修改了,这样就可能造成同一个商品被下单2次,使得数据不一致。所以说这种方式是不安全的。

 

2使用悲观锁来实现:

在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。

 

注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。

 

我们可以使用命令设置MySQL为非autocommit模式:

set autocommit=0;

 

设置完autocommit后,我们就可以执行我们的正常业务了。具体如下:

//0.开始事务

begin;/begin work;/start transaction; (三者选一就可以)

//1.查询出商品信息

select status from t_goods where id=1 for update;

//2.根据商品信息生成订单

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status为2

update t_goods set status=2;

//4.提交事务

commit;/commit work;

 

注:上面的begin/commit为事务的开始和结束,因为在前一步我们关闭了mysql的autocommit,所以需要手动控制事务的提交,在这里就不细表了。


观锁的实现:

还是拿之前的实例来举:商品goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。

下单操作包括3步骤:

1.查询出商品信息

select (status,status,version) from t_goods where id=#{id}

2.根据商品信息生成订单

3.修改商品status为2

update t_goods 

set status=2,version=version+1

where id=#{id} and version=#{version};


那么为了使用乐观锁,我们首先修改t_goods表,增加一个version字段,数据默认version值为1。


 

原创粉丝点击