zoukankan      html  css  js  c++  java
  • 继续深入数据库 了解一下数据库的锁机制

    下载网站:www.SyncNavigator.CN 
     客服QQ1793040
    ----------------------------------------------------------


    关于HKROnline SyncNavigator 注册机价格的问题

     

    HKROnline SyncNavigator 8.4.1 非破解版 注册机 授权激活教程
     

     

    最近一直在研究数据库同步的问题,在网上查了很多资料,也请教了很多人,找到了一种通过快照复制的方法。研究了一番后发现之前就是用的这个方法,效果不是很好,果断放弃。经过了一番寻觅和他人指点,最后从一位热心网友那里得知一款很好用的软件—— SyncNavigator。

    好东西就要拿出来跟大家分享,所以今天向大家介绍一下这款软件,及其一些使用方法。下面先看看它有什么强大的功能吧!

    SyncNavigator的基本功能:

    自动同步数据/定时同步数据
    无论是实时同步/24小时不间断同步,还是根据计划任务(每小时/每日/每周/等)定时自动同步都能完全胜任。

    完整支持 Microsoft SQL Server
    完整支持 Microsoft SQL Server 2000 2005 2008 数据库类型。并能在不同数据库版本之间相互同步数据。

    支持 MySQL 4.1 以上版本
    支持 MySQL 4.1 5.0 5.1 5.4 5.5。并能在不同数据库版本之间相互同步数据。

    无人值守和故障自动恢复
    当数据库故障或网络故障以后,无需人工干预(或操作)自动恢复同步并确保数据完全准确,可靠。

    同构数据库同步/异构数据库同步
    SQL Server to SQL Server, MySQL to MySQL, SQL Server to MySQL 等都能轻松实现。

    断点续传和增量同步
    当同步完成(或中断)后,再次同步时能继续上一次的位置增量同步,避免每次都需要从头开始的问题。

    我们在高并发的场景下,经常会在异常日志中看到“dead lock(死锁)”的错误信息。想了无数的解决方案,都没有能够最终的解决,到底是什么原因引起了死锁呢?要解决这个问题,我们就必须先了解透彻数据库都有哪些锁?他们的工作机制是什么样的。

    那,让我们开启今天的学习之路吧。

    为什么数据库要加锁?

    继续深入数据库 了解一下数据库的锁机制

    当多条请求并发访问一个数据库资源时,有可能就会导致数据的不一致,因此,就需要一种机制来将数据库的访问顺序化,从而保证数据库数据的一致性,这个我们在

    《数据库常用的事务隔离级别都有哪些?都是什么原理?》也有讲到。事务就是就是一种顺序化的机制,而事务要达到目的,就必须要有所的支持。

    继续深入数据库 了解一下数据库的锁机制

    数据库都有哪些锁?

    由于数据库的种类也不少,每种数据库的锁大致都相同,但是细节上略有不同,因此,我们就选择MySql/InnoDB作为讲解的对象。

    InnoDB按照锁的类型来划分,主要分为了三个大类:共享锁(Shared lock)、排它锁,也叫独占锁(Exclusive Locks)、意向锁(Intent Locks)。其中,意向锁又分为了意向共享和意向排他,因此,严格意义上来说,是有四种分类的锁,分别是:

    1. 共享锁(Shared lock),简称:S锁
    2. 排它锁(Exclusive Locks),简称:X锁
    3. 意向共享锁(Intent Shared lock),简称:IS锁
    4. 意向排他锁(Intent Exclusive Locks),简称:IX锁

    接下来,我们就聊聊这些锁都是怎么工作的。

    继续深入数据库 了解一下数据库的锁机制

    共享锁

    共享锁,顾名思义,就是我虽然锁住了这个资源,但是我并不会独占它,我同样允许其他人使用这个资源。

    继续深入数据库 了解一下数据库的锁机制

    通常情况下,查询就是使用的共享锁。

    例如:

    事务A先执行了一个查询

    1. select * from table; 

    事务A还没有执行完,事务B就执行了另一个查询

    1. select * from table where id = 1; 

    这个时候,事务B是可以优先于事务A完成他的查询的,并不存在必须要事务A结束,才执行事务B的情况,这就是共享锁的作用。

    排它锁

    排它锁,又叫独占锁,顾名思义,我锁住了,这东西就是我一个人的,谁也别想看,别想碰。

    通常情况下,修改操作就是使用的排它锁。

    继续深入数据库 了解一下数据库的锁机制

    例如:

    事务A先执行了一个修改操作

    1. update table set Status = 1; 

    事务B还事务A没有完成时,执行了另一个修改操作

    1. update table set Status = 0 where id =1; 

    这个时候,事务B就只有等着,到事务A执行完成以后,事务B才能够继续,这就是排它锁的作用。

    意向锁

    共享锁、排它锁按照其作用的粒度,可以锁到行级,也可以锁到页级或表级。不过意向锁只作用于表级,主要是用来标记一个事务对于这张表操作的一个意向。

    例如:我有一个事务需要使用表锁,那我就需要知道,这个表是否存在其他的锁,如果有,可能我就需要等待。但是,我如果要排除其他锁,我就需要一个一个记录的遍历,才知道是不是存在行锁。因此,数据库对于行锁就提出另一个机制,就是意向锁,如果你要对这个表进行行锁时,那么先在表上加一个意向锁,方便其他事务查询。

    继续深入数据库 了解一下数据库的锁机制

    因此,意向锁就有了以下协议:

    • 一个事务获得表t中某行的S锁之前,必须先获得t表上的IS锁或者更强类型的锁。
    • 一个事务获得表t中某行的X锁之前, 必须先获得t表上的IX锁。

    现在我们知道了所的类型,接下来我们说说锁的级别。

    继续深入数据库 了解一下数据库的锁机制

    根据锁的颗粒或者级别不同,我们又把所分为了三个级别:表锁(table-level locking)、页锁(page-level locking)、行锁(row-level locking)。

    MyISAM和MEMORY存储引擎采用的是表锁(table-level locking);BDB存储引擎采用的是页锁(page-level locking),但也支持表锁;InnoDB存储引擎既支持行锁(row-level locking),也支持表锁,但默认情况下是采用行锁。

    而行锁又包括了三种行锁的算法,分别是:

    1. 记录锁(Record Lock)
    2. 间隙锁(Gap Lock)
    3. 临键锁(Next-Key Lock)

    这里有个小知识点:InnoDB的行锁只针对索引项使用,也就是说,只有在通过索引检索数据时,InnoDB才使用行锁,其他时候都是使用的表锁。

    记录锁(Record Locks)

    记录锁,顾名思义,就是锁住一条记录。这是Read Committed(读提交)事务级别的默认锁级别。

    记录锁是作用于索引的,所以,当查询不是作用于索引上时,系统会创建一个隐式的聚集索引,然后作用在索引上。

    例如:

    1. select * from table where id = 1 lock in share mode; 

    就是一个共享记录锁,

    1. select * from table for update where id = 1 ; 

    就是一个排他记录锁。

    间隙锁(Gap Lock)

    间隙锁,它不会去锁住索引本身,但是会锁住的是一个索引的范围。启用它有一个前置条件,就是数据库隔离级别必须是Repeatable Read(可重复读),这也是InnoDB的默认隔离级别,假设我们将隔离级别降到Read Committed(读提交),间隙锁将会自动失效。

    间隙锁的使用,能够有效的防止幻读。

    例如:

    如果事务A执行了

    1. select * from table where id between 8 and 15 for update; 

    这是,事务B想在事务A执行期间执行插入一条id是10的记录,就会被阻止。因为这会导致事务A中的多次查询数据不一致。

    临键锁(Next-Key Lock)

    临键锁就是记录锁+间隙锁的组合方式。这是Repeatable Read(可重复读)隔离级别的默认锁级别。使用临键锁有一个好处,就是,假设我们执行执行一个查询

    1. select * from table where id = 100; 

    如果id是唯一索引,那么临键锁就会降级为记录锁,锁住这条记录,而不是去锁住一个范围。

    我们讲完了这些锁,那么就不禁要问了,死锁是怎么产生的呢?

    这就要说到另一个情况,就是锁的升级。

    锁的升级

    继续深入数据库 了解一下数据库的锁机制

    假设,我们先进行了一个查询,找到了目标数据,然后进行修改,在这个事务中,其实不同的阶段,锁的类型是不同的。

    当我们进行查询的时候,我们想数据库先获得了一个共享锁,当我们要对这条数据进行更新的时候,并不是释放共享锁,然后再获取排它锁,而是进行了一个锁的升级操作,直接将共享锁升级成为了排它锁。

    而就是因为这个操作,可能导致了死锁。

    死锁

    继续深入数据库 了解一下数据库的锁机制

    假设:事务A中有一个锁升级操作,也就是先执行

    1. select * from table where id =1 

    再执行

    1. update table set Status = 1 where id =1 

    事务B中,同样存在这样的情况,先执行

    1. select * from table where id =1 

    再执行

    1. update table set Name = '牛' where id =1 

    而执行的顺序恰好是:

    1. 事务A获得了共享锁,执行查询;
    2. 事务B获得了共享锁,执行查询;
    3. 事务A需要升级排它锁,执行修改;
    4. 事务B也需要升级排它锁,不能释放共享锁。

    于是,死锁就发生了。当然,还有一种交叉死锁的情况,更为常见,大家可以自己百度看看了。

    死锁发生时,数据库并不会直接检查到死锁的存在,只有在锁等待超时的时候被发现,然后杀死其中一个请求。如果并发量高时,死锁就会引起大量的线程挂起,占用大量资源。

    怎么预防死锁呢?

    最直接的办法就是,别在update前先select一次。

    但是,这种情况在所难免,很多时候我们update时,都是需要先select一次的,如果所有地方要求不能select,那代码难度势必就几何级的上升。

    还有一种办法就是,加硬件,提高并发能力,这样,出现两次事务同时请求的概率就下降了。不过,这个方式成本太高。

    当然,我们还可以直接在查询时,就申请到最终事务需要的锁级别,避免升级锁的出现,也可以预防死锁,例如查询时就直接写

    1. select * from table for update;  
  • 相关阅读:
    [BZOJ1415]聪聪和可可
    [POJ2096]Collecting Bugs
    开博第一天
    实现CSS样式垂直水平完全居中
    Vue中独立组件之间数据交互
    python Template中substitute()的使用
    eclipse 编辑 python 中文乱码的解决方案
    java Math.random()随机数的产生
    java文件读写的两种方式
    My way on Linux
  • 原文地址:https://www.cnblogs.com/syncnavigator/p/10198301.html
Copyright © 2011-2022 走看看