当前位置: 首页 > news >正文

深圳个性化网站建设公司电话创意平面设计公司简介

深圳个性化网站建设公司电话,创意平面设计公司简介,珠海在线网站建设,手机装wordpress一.什么是死锁 要想知道MYSQL死锁产生的原因,就要知道什么是死锁?在了解什么是死锁之前,先来看一个概念:线程安全问题 1.线程安全问题 1.1什么是线程安全问题 线程安全问题#xff0c;指的是在多线程环境当中#xff0c;线程并发访问某个资源#xff0c;从而导致的原子性指的是在多线程环境当中线程并发访问某个资源从而导致的原子性内存可见性顺序性问题,以上这三个问题会导致程序在执行的过程当中出现了超出预期的结果 1.2 线程安全问题产生的原因是什么 根本原因是在于各个线程是由操作系统随机进行调度并且各个线程是抢占式执行的.在多线程的环境当中存在线程共享的数据,并且 当其中多个线程尝试修改共享变量的值就有可能引发线程安全问题如果单个线程仅仅读但是不修改共享的变量就不会存在线程安全问题如果多个线程串行化”排好队,挨个修改变量的值就不会引发线程安全问题 下面就上面列举的三种情况作出说明 (1).修改的操作的原子性问题 如果修改操作是原子的那也不存在线程安全问题但是大部分的修改都是非原子性的,如何理解修改操作的原子性呢举个例子说明,见下面代码以及图示: static class Counter{int count;public void add(){count;}} ​ 如图所示此时方法add就是尝试对成员变量count进行修改修改为count1,这个看似“原子”的操作站在编译器底层也就是汇编代码的角度实际上是非原子的分为以下三个步骤 ①把count的值从内存当中读取出来;(load)②执行count;(add)③把自增操作之后的count返回到内存当中。(save) 假设count的值为0,这三个操作当中如果有一个线程(Thread1)执行到load指令然后被操作系统调度离开了CPU,接着另外一个线程(Thread2)被调度到CPU内核上面执行连续执行load,add,save指令此时save的到内存当中的值为1。 这个时候Thread1右被重新调度到CPU内核上面执行由于线程调度是有上下文的因此Thread1会继续在刚刚load的值的基础上面进行add,save操作。 那么此时Thread1 save的值仍然为1.与原先期待的两次操作之后值为2的期待不一样,如果把load,add,save这三个操作变成原子的不可以在中间细分开,那么就会达到预计的两次操作后值为2 总结:         所谓的原子性问题就是当线程进入一段代码块还没有执行完毕的时候允许其他线程进入这一段代码块,执行代码中的操作 (2).内存可见性问题 内存可见性问题就是:一个线程针对变量进行修改可以被其他的线程及时看到,这里先来了解一下(JMM)模型:        在Java虚拟机当中线程之间共享的变量存在于主内存(main memory)当中,每一个线程都拥有一个自己的工作内存,当线程想要读取一个共享的变量的时候会先把变量从主内存当中加载到自己的工作内存当中,然后先从工作内存当中修改这个变量的值修改完之后再把修改操作同步到主内存当中,但是在多线程的环境下面一旦有线程修改了共享变量的值由于编译器优化等等的原因其他线程读取这个被修改的变量时候不一定继续读取来自于主内存当中的值而是仅仅继续读取自己的工作内存“当中的值,这样也就造成了读取数据的错误也就引发了线程安全问题 对应到操作系统当中就是这样的场景         当一个线程尝试修改内存当中变量的值的时候是按照:把内存的变量的值读取到寄存器当中然后首先修改寄存器当中的值修改完成之后再修改内存当中的值,但是在多线程的环境下面编译器有可能对这一系列指令进行优化导致其中一个线程修改完内存当中的变量的值之后其他线程想再次获取这个变量的值的时候读取到的数据不是来自于内存而是仅仅读取寄存器当中还没有来得及更新的值这样也就引发了线程安全问题 (3).代码顺序性问题 编译器在保持原有代码逻辑仍然不变的情况下对一系列指令进行了重新排序,如果在单线程的环境下面是没有任何问题的,但是在多线程的环境下面仍然执行指令重排序就有可能被”优化“过之后的代码逻辑发生了改变从而引发线程安全问题 2.那么怎么保证线程的安全性呢 这里引入synchronized关键字,还是以上面的代码执行案例说明 在代码当中引入synchronized(锁),让synchronized修饰的代码块当中的所有指令变为原子性,从而实现让Thread1的三个操作load,add,save变成原子,就是使用sychronized修饰add方法.让”load,add,save这三个操作变为不可再分的原子,代码如下: static class Counter{int count;synchronized public void add(){count;}} 可以理解为互斥使用也有的地方称为不可中断:         加上锁(synchronized)之后执行的效果就变成当两个线程同时调用add方法的时候其中一个线程,假如是(thread1)会竞争到锁,另外一个线程(thread2)会进入阻塞状态,进入阻塞队列,也就是Thread类的状态当中的BLOCKED状态,等待竞争到锁的线程执行完add方法之后,此时会自动解锁,也就是缩释放”,Thread2会从阻塞队列当中离开重新回到就绪队列当中,这个就是所谓的互斥使用:两个线程不可以同时拥有一把锁         所谓的原子性,就是:当其中一个线程进入synchronized修饰的代码块当中要么全部执行完毕再允许其他的线程进入这一段代码块要么都不执行 synchronized还保证了内存的可见性  在JMM当中,对于synchronized的内存可见性做了两条规定 线程进入同步代码块的时候将清空这个线程工作内存中共享变量的值从而使得其他线程如果针对这个变量进行读取操作一定要去主内存当中读取线程离开synchronized修饰的代码块的时候将会把这个变量修改之后的状态同步到主内存当中以此来保证共享变量的可见性。 可以理解为synchronized可以保证内存的刷新 synchronized还保证了有序性:        在synchronized代码块当中每次只允许一个线程进入,可以理解为:在synchronized代码块内部同一时刻是单线程执行的,因此,即使编译器针对一部分代码进行了优化但是仍然不影响代码原有的执行逻辑。         如果是多个线程同时进入同步代码块进行修改此时再发生编译器优化就有可能导致线程安全问题的发生。         synchronized保证有序性的原理可以理解为加synchronized后依然会发生重排序只不过有同步代码块可以保证只有一个线程执行同步代码中的代码因此保证了有序性。需要注意的是:synchronized虽然保证了代码的有序性但是不可以阻止编译器进行指令重排序 3. 思考一个问题:一个线程连续针对同一把锁连续加锁两次是否会产生死锁 一个线程连续针对同一把锁连续加锁两次是否会产生死锁?这个问题有两种情况: 如果加锁后不会阻塞自己那么这个锁就是一个特殊的锁,叫做可重入锁如果加锁后会阻塞自己,这个锁就不是可重入锁,如果阻塞了自己,那么就相当于产生了死锁 案例说明: class Counter{public int count;synchronized public void add(){synchronized (this) {count;}} } 分析上面代码的执行流程 当多个线程并发调用add()方法的时候,其中一个线程(Thread1)可以获取到锁,其中,该线程针对调用的对象count1加锁,此时该线程获得了锁其余线程进入阻塞状态,被加锁的对象就是(count1) 当进入add()方法内部的时候遇到了synchronized修饰的代码块,此时Thread1继续尝试获取锁,前面也提到加锁是线程针对对象加锁,可是当调用add()方法的时候已经针对(this也就是该方法的调用者count1)加锁了,当再次尝试获取锁的时候是否会阻塞呢 回顾一下什么情况下会出现因为加锁而产生的线程阻塞当多个线程尝试竞争同一个未被加锁的对象的时候没有竞争到锁的线程会进入阻塞状态,换而言之如果一个对象被加锁了那么其他线程想继续获取到这个对象的锁那么其他线程都无法获取到都会进入阻塞状态. 那么此时针对count1也就是下一个synchronized代码块当中的this不允许其他线程继续对this加锁但是如果Thread1此时也不允许对synchronized代码块中的代码加锁的话Thread1也会继续进入阻塞状态,这样的话所有的线程都进入了阻塞状态.  总结一下:如果一个线程针对同一把锁连续两次加锁,在第二次尝试加锁的时候,不会让自身进入阻塞等待的状态,那么称这个锁是可重入锁,根据代码的执行情况,synchronized就是可重入锁 4.死锁产生的条件 上面介绍了线程安全相关的问题,以及synchronized锁,现在回过头来看看死锁产生的相关条件 举个形象点例子:        张三和李四一起下馆子吃饺子,其中张三先拿到了酱油张三对李四说:你把醋给我我就把酱油给你。李四一听很不乐意他反过来说你如果把酱油先给我我才会把醋给你。这个时候两个人就僵持住了谁也给不出,也就产生了“死锁 (1).死锁准确的定义 死锁指的是在一组线程当中由于线程竞争共享的资源因为互相等待因而导致了“永久”阻塞的现象如果没有外力终止程序将永远无法结束进程 (2).死锁产生的四个必要条件 1)互斥使用 在上面的场景当中线程张三拿到了锁(酱油);线程李四也拿到了锁醋,这个时候如果线程张三尝试获取被李四加锁的对象”醋“那么张三就会获取锁失败,进而进入阻塞的状态,李四如果想获取张三的锁(酱油)也同理.所以互斥使用的含义就是其中一个线程拿到了锁其他与当前线程竞争锁的线程就必须进入阻塞状态等待锁的释放。 2)不可抢占 线程1拿到锁之后线程1一定要主动释放锁其他线程才可以获取到 3)请求和保持 在上述的场景当中线程张三获取到锁酱油之后当他想再次获取到李四的醋的时候不会因为去尝试获取李四的醋而丢失了本来属于自己的锁(酱油),所以请求和保持的含义就是:线程1获取到对应的一把锁之后如果想尝试再次获取其他的锁当前拥有的锁仍然是保持的不会丢失 4)循环等待 如上面的场景,张三和李四都在等待对方先释放锁但是都没有自行先释放锁,这个就是循环等待.再举个例子说明:例如有进程A、进程B和进程C三个进程进程A请求的资源被进程B占用进程B请求的资源被进程C占用进程C请求的资源被进程A占用于是形成了循环等待条件如下图: 在线程当中循环等待的场景就是两个线程都在等待获取到对应的锁之后,都在等待对方释放锁,这就是循环等待 注意:以上四个条件,缺一不可,是出现死锁的充分必要条件,但是,归根结底,还是因为synchronized是必须要等到获取到锁的线程执行完加锁的代码块之后,其他线程才能继续获取到当前的锁,但是,其他的锁不一定跟synchronized一样 5.如何处理死锁死锁 处理死锁有4种方法:分别为预防死锁、避免死锁、检测死锁和解除死锁 预防死锁         处理死锁最直接的方法就是破坏造成死锁的4个必要条件中的一个或多个以防止死锁的发生 避免死锁应当从产生死锁的原因出发: 1.尽量避免一个线程同时获取多把锁2.可以考虑一些特定的业务场景使用lock.tryLock(timeout),限制加锁的时间来代替synchronized,因为synchronized是一定要等到正在执行同步代码块的线程解锁之后,其他线程才可以获取锁3.针对锁进行排序,规定所有线程加锁的顺序 假设一个进程当中有n个线程和m把锁如果想要加锁的话可以在代码编写的时候对加锁的顺序进行规定所有的线程都必须按照从1号锁到2号锁......到m号锁的顺序进行加锁,不可以打乱这个加锁的顺序 在上面的案例中如果分别对酱油和醋这两把锁进行编号规定酱油位1醋位2,张三和李四都必须按照1,2的顺序来拿酱油和醋就不会发生相互阻塞的情况了 检测死锁         这种方法允许系统在运行过程中发生死锁但是能够检测死锁的发生并采取适当的措施清除死锁 解除死锁         当检测出死锁后采用适当的策略和方法将进程从死锁状态解脱出来 在实际工作中通常采用有序资源分配法和银行家算法这两种方式来避免死锁,大家可自行了解 好了,死锁的相关问题(线程安全,产生条件,避免死锁,处理死锁)就了解完了,归根到底,总结一下: 死锁指两个或多个事务相互等待对方释放锁从而导致进程无法继续执行的一种情况.当一个事务需要锁定一些资源时如果这些资源已经被其他事务锁定则该事务必须等待其他事务释放锁才能继续执行.如果多个事务同时等待对方释放锁就会发生死锁 那么在mysql当中也会出现死锁这里的死锁又是什么呢  二.MYSQL死锁详解 要想了解MYSQL死锁相关知识,就需要知道MYSQL有哪些锁以及锁的级别 1.锁机制 见:关于mysql锁机制详解 几个锁概念: 共享锁(S)允许多个事务同时读取同一份数据但不允许对数据进行修改,当一个事务获得共享锁时其他事务只能获得共享锁不能获得排他锁 排他锁(X)只允许一个事务对数据进行修改其他事务不能读取或修改该数据,当一个事务获得排他锁时其他事务不能获得任何类型的锁 意向共享锁(IS)表示事务想要在某个数据上获得共享锁但并不是真正的共享锁只是一个辅助锁,当一个事务获得意向共享锁时其他事务可以获得共享锁或意向共享锁但不能获得排他锁 意向排他锁(IX)表示事务想要在某个数据上获得排他锁但并不是真正的排他锁只是一个辅助锁,当一个事务获得意向排他锁时其他事务只能获得意向共享锁不能获得任何类型的锁 记录锁record lock:这是一个索引记录锁它是建立在索引记录上的锁主键和唯一索引都算很多时候锁定一条数据由于无索引往往会导致整个表被锁住建立合适的索引可以防止扫描整个表。如开两个会话两个事务并且都不commit该表有主键两个会话修改同一条数据第一个会话update执行后第二个会话的update是无法执行成功的会进入等待状态但是如果update别的数据行就可以成功.      再例如开两个会话两个事务并且都不commit并且该表无主键无索引那么第二个会话不管改什么都会进入等待状态。因为无索引的话整个表的数据都被第一个会话锁定了。间隙锁gap lock):MySQL默认隔离级别是可重复读这个隔离级别为了避免幻读现象引入了这个间隙锁对索引项之间的间隙上锁 2.锁级别 mysql锁级别页级、表级、行级 表级锁:开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低行级锁:开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高页面锁:开销和加锁时间界于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间并发度一般 从上面可以看出,表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB,而InnoDB存储引擎采用了一种叫作等待图wait-for graph的方法来自动检测死锁如果发现死锁,就会自动回滚一个事务,下面来看看MySQL中的死锁案例 3.案例讲解 案例一 第一步 打开终端A登录MySQL将事务隔离级别设置为可重复读开启事务后为account数据表中id为1的数据添加排他锁如下所示: mysql set session transaction isolation level repeatable read; Query OK, 0 rows affected (0.00 sec)mysql start transaction; Query OK, 0 rows affected (0.00 sec)mysql select * from account where id 1 for update; --------------------- | id | name | balance | --------------------- | 1 | 张三 | 300 | --------------------- 1 row in set (0.00 sec) 第二步 打开终端B登录MySQL将事务隔离级别设置为可重复读开启事务后为account数据表中id为2的数据添加排他锁如下所示: mysql set session transaction isolation level repeatable read; Query OK, 0 rows affected (0.00 sec)mysql start transaction; Query OK, 0 rows affected (0.00 sec)mysql select * from account where id 2 for update; --------------------- | id | name | balance | --------------------- | 2 | 李四 | 350 | --------------------- 1 row in set (0.00 sec) 第三步 在终端A为account数据表中id为2的数据添加排他锁如下所示: mysql select * from account where id 2 for update; 此时线程会一直卡住因为在等待终端B中id为2的数据释放排他锁 第四步 在终端B中为account数据表中id为1的数据添加排他锁如下所示: mysql select * from account where id 1 for update; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction 此时发生了死锁,通过如下命令可以查看死锁的日志信息: show engine innodb status 通过命令行查看LATEST DETECTED DEADLOCK选项相关的信息可以发现死锁的相关信息或者通过配置innodb_print_all_deadlocksMySQL 5.6.2版本开始提供参数为ON将死锁相关信息打印到MySQL错误日志中 案例二 假设有下面这一张表: id主键索引)no(非主键索引)name11001小明21002小李31003小华41004小黄 在这一张表当中,id为主键索引no为二级索引,name这一列没有任何索引的约束,现在这张表当中有以上的一些数据,现在有两个事务一个事务A另外一个事务B,下面根据步骤分析一下两个事务的执行流程: 第一步 在上述两个事物当中事务A首先开启了然后执行一条查询的sql语句,也就是select...for update这样的语句,因为记录的最大值为1004,1007不在这一个范围当中,此时事务A对于表当中no范围为(1004,∞)的no索引加上了一把锁间隙锁 第二步 事务B开启了因为no值为1008的记录不在范围(1004,∞)的范围之内,因此事务B也会加一个间隙锁范围是(1004,∞);由于间隙锁之间是互容的因此事务B在执行select语句的时候不会发生阻塞 第三步 事务A执行了一条插入的索引为1007的数值,但是由于事务B对于事务A插入的范围加上了间隙锁因此事务A一定要等待到事务B释放锁才可以继续执行 第四步 事务B执行了一条插入的索引值为1008的sql语句,但是由于事务A对于(1004,∞)的范围加锁了,因此事务B一定需要等待到事务A释放锁才可以继续执行 可以看到此时两个事务互相阻塞了 那么在上面的insert语句中,是怎么加锁来执行的呢? Insert语句在正常执行的时候是不会生成锁结构的它是靠聚簇索引自带的一个被称为trx_id的字段来作为隐式锁来保护记录的,只有在特殊的情况下面才会把隐式锁转化为显示锁也就是真正加锁的过程 举两个例子来说明隐式锁转换为显示锁的场景: (1).范围(a,b)内加有间隙锁当有一条记录在范围(a,b)之内插入记录的时候就会转化为显示锁        (2).如果insert语句插入的记录和已有的记录之间出现了主键也无法插入 记录之间加有间隙锁,还是上面这个表: id主键索引)no(非主键索引)name11001小明21002小李31003小华41004小黄 此时这一张表当中假如有一条语句执行: select * from t_order where order_no 1006 for update; 此时事务如果插入一条语句,insert....values(1007...)这个时候由于插入的数据正好在前一个sql语句插入的范围之内因此会被阻塞 案例三 将投资的钱拆成几份随机分配给借款人,程序思路如下         投资人投资后将金额随机分为几份然后随机从借款人表里面选几个然后通过一条条select for update 去更新借款人表里面的余额.例如:两个用户同时投资A用户金额随机分为2份分给借款人12; B用户金额随机分为2份分给借款人21.由于加锁的顺序不一样就出现了死锁         那么怎么进行改进,避免出现死锁呢,解决:把所有分配到的借款人直接一次锁住,加锁就会从小到大的加锁,然后顺序执行,这就避免了死锁,代码如下: select * from xxx where id in (xx,xx,xx) for update在in里面的列表值mysql是会自动从小到大排序加锁也是一条条从小到大加的锁 第一个会话         注意关闭掉自动提交set autocommit0; mysql select * from goods where goods_id in (2,3) for update; --------------------------------------- | good_id | goods_name | price             | --------------------------------------- |  2 | bbbb     | 1.00 | |  3 | vvv     | 3.00 | --------------------------------------- 第二个会话: select * from goods where goods_id in (3,4,5) for update; 锁等待中…… 案例四 表锁的死锁情况 用户A访问表A锁住了表A然后又访问表B另一个用户B访问表B锁住了表B然后企图访问表A这时用户A由于用户B已经锁住表B它必须等待用户B释放表B才能继续同样用户B要等用户A释放表A才能继续这样就产生了死锁 行锁的死锁情况 如果在事务中执行了一条没有索引条件的查询引发全表扫描把行级锁上升为全表记录锁定等价于表级锁多个这样的事务执行后就很容易产生死锁和阻塞 解决办法 以上死锁基本是由于程序的BUG产生的在对数据库的多表或单表操作时尽量按照相同的顺序进行处理且避免同时锁定两个资源.必须同时锁定两个资源时要保证在任何时刻都应该按照相同的顺序来锁定资源 select for update 如果有唯一索引命中了唯一记录行锁互斥锁;如果有唯一索引没命中gap锁另一个事务也可以获得这个gap锁但是不能插入数据(后续有死锁可能)如果有普通索引命中了记录行锁gap锁;(后续有死锁可能)如果有普通索引没有命中记录gap锁,和情况2相同(后续有死锁可能)如果没有索引直接锁全表互斥直接阻塞别的事务 针对上面出现的情况,再次举个列子说明 CREATE TABLE test_lock (id int NOT NULL AUTO_INCREMENT,user_name varchar(255) DEFAULT NULL,age int DEFAULT NULL,city varchar(255) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY idx_user_name (user_name),KEY idx_city (city) ) ENGINEInnoDB AUTO_INCREMENT0 DEFAULT CHARSETutf8mb4;insert into test_lock(id,user_name,age,city) values(1,张三,10,深圳); insert into test_lock(id,user_name,age,city) values(5,李四,32,成都); insert into test_lock(id,user_name,age,city) values (9,王五,55,广州);主键索引  BEGIN; select * from test_lock where id  1 for update;select * from performance_schema.data_locks;ROLLBACK; 查询条件是主键索引命中数据库表记录时一共会加两把锁一把IX意向排他锁表锁不影响插入一把对应主键的X排他锁行锁影响对应主键那一行的插入  唯一索引 BEGIN; select * from test_lock where user_name 张三 for update;select * from performance_schema.data_locks;ROLLBACK;查询条件是唯一索引命中数据库表记录时一共会加三把锁一把IX意向排他锁 表锁不影响插入一把对应主键的X排他锁行锁一把对应唯一索引的X排他锁 行锁  普通索引 BEGIN; select * from test_lock where city 成都 for update;select * from performance_schema.data_locks;ROLLBACK;查询条件是普通索引命中数据库表记录时一共会加四把锁一把IX意向排他锁 表锁不影响插入一把对应主键的X排他锁行锁一把对应普通索引的X排他锁 行锁一把对应普通索引的Gap间隙锁 锁住一个范围会影响插入 非索引 BEGIN; select * from test_lock where age 10 for update;select * from performance_schema.data_locks;ROLLBACK;查询条件不是索引命中或非命中数据库表记录时都会加一个IX锁表锁不影响插入每一行实际记录行的X锁还有对应于supremum pseudo-record的虚拟全表行锁通俗点讲其实就是锁表了 索引未命中 查询条件是中间值 BEGIN; select * from test_lock where id  4 for update;select * from performance_schema.data_locks;ROLLBACK;查询条件是主键未命中数据库表记录时查询条件是中间值会加一个IX锁表锁不影响插入一把对应主键索引的X排他锁 行锁一把对应主键索引的Gap间隙锁 锁住一个范围会影响插入 查询条件非中间值  BEGIN; select * from test_lock where id  10  for update;select * from performance_schema.data_locks;ROLLBACK;查询条件是主键未命中数据库表记录时查询条件非中间值会加一个IX锁表锁不影响插入每一行实际记录行的X锁还有对应于supremum pseudo-record的虚拟全表行锁通俗点讲其实就是锁表了 4.死锁排查 查看死锁日志:         通过 show engine innodb status命令查看近期死锁日志信息主要关注日志中的 LATEST DETECTED DEADLOCK部分,死锁记录只记录最近一个死锁信息若要将每个死锁信息都保存到错误日志启用以下参数: show variables like innodb_print_all_deadlocks;查当前正在运行的InnoDB事务的信息可以kill长期占用锁的事务对应的线程id select * from information_schema.INNODB_TRX; 5.MySQL中避免死锁的几种方式 尽量让数据表中的数据检索都通过索引来完成避免无效索引导致行锁升级为表锁 合理设计索引尽量缩小锁的范围 尽量减少查询条件的范围尽量避免间隙锁或缩小间隙锁的范围 尽量控制事务的大小避免长事务,减少一次事务锁定的资源数量缩短锁定资源的时间和占用范围,这样可以大大减少死锁产生的概率 如果一条SQL语句涉及事务加锁操作则尽量将其放在整个事务的最后执行 尽可能使用低级别的事务隔离机制 设置任务超时等待时间:当在一个任务的等待时间超过了这个时间之后,就进行回滚;在 InnoDB 中,参数innodb_lock_wait_timeout是用来设置超时时间的默认值时50秒 主动开启死锁检测: 将参数innodb_deadlock_detect设置为 on,当innodb检测发现死锁之后就会进行回滚死锁的事务,但是死锁检测会比较耗资源 对于更新频繁的字段采用唯一索引的设置方案:例如在上面的例子当中可以把no字段设置成唯一索引 保证资源的加锁顺序避免循环等待的产生 使用乐观锁mvcc机制读取数据不上锁在读情况下共享资源
http://www.zqtcl.cn/news/526976/

相关文章:

  • 在哪个网站做科目一考试题域名多少钱一年
  • 红孩子母婴网站开发背景建网站可行性分析
  • 北京 网站设计飞沐商城网站技术方案
  • 大连网站建设价格低怎么加入网站做微商城
  • 惠山网页制作北京优化推广
  • 武威做网站网站流量分析怎么做
  • 用动态和静态设计一个网站cname wordpress
  • php装修门户网站源码PHP是做网站最好的
  • 莆田哪里有网站开发北京大企业公司排名
  • 网站建设运营的成本丰宁县有做网站的吗
  • 网站建设如何上传文件中小企业网站建设好么
  • 安徽建设部网站国际网站 建设
  • 沈阳开发网站小程序名称大全
  • 做网站大概价格西安做网站电话
  • 前端做微网站台州做网站哪家公司好
  • 电信改公网ip可以做网站吗销售平台建设方案
  • 免费的公司网站怎么做网站建设招聘需求
  • 徐州金桥建设监理有限公司网站那个网站做系统好
  • 浙江网站制作做一个自我介绍的网页
  • 郑州做网站公司有多少网站建设需要自备什么
  • 齐齐哈尔网站seo重庆旅游
  • 顺德品牌网站建设信息网络编程课程
  • 广西南宁建设职业学图书馆网站wordpress 黑色主题
  • 网站建设需要准备那些内容阜阳微商城网站建设
  • flash全屏网站模板企业网站示例
  • 制作手机端网站开发厦门网站设计定制
  • 佛山网站开发公司做网站在什么地方发帖子呢
  • 无网站可以做cpc吗wordpress 12张表
  • 有些中小网站cnzz网站排名是怎么做的
  • 深圳做微商网站的公司高端做网站价格