本篇文章为你整理了MySql锁机制(mysql锁机制应用场景)的详细内容,包含有mysql锁机制 隔离级别 mysql锁机制应用场景 mysql锁机制有几种 mysql锁机制解析 MySql锁机制,希望能帮助你了解 MySql锁机制。
1,MySQL锁的基本介绍
在数据库中,除传统的计算资源(如CPU,RAM,I / O等)的争用以外,数据也是一种供者用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来讲,锁对数据库而言尤其尤其重要,也更加复杂。
相对其他数据库而言,MySQL的锁机制比较简单,其最显着的特点是不同的存储引擎支持不同的锁机制。例如,MyISAM和MEMORY存储引擎采用的是表级锁(表级锁); InnoDB存储引擎既支持行级锁(行级锁),也支持表级锁,但多数情况下是采用行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:占用大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
从上述特点可见,很难笼统且本质上锁更好,只能就具体应用的特点来说就是锁更合适!只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
2,MyISAM表锁
MySQL的表级锁有两种模式:表共享读锁(表读锁)和表独占写锁(表写锁)。
对MyISAM表的读操作,不会多个其他用户对同一表的读请求,但会一对对同一表的写请求;对MyISAM表的写操作,对多个其他用户对同一表的读和写操作; MyISAM表的读操作与写操作之间,以及写操作之间是串行的!
建表语句:
CREATE TABLE `mylock` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`NAME` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `mylock` (`id`, `NAME`) VALUES (1, a);
INSERT INTO `mylock` (`id`, `NAME`) VALUES (2, b);
INSERT INTO `mylock` (`id`, `NAME`) VALUES (3, c);
INSERT INTO `mylock` (`id`, `NAME`) VALUES (4, d);
MyISAM写锁串口读的案例:
当一个线程获得对一个表的写锁之后,只有持有锁的线程可以对表进行更新操作。其他线程的读写操作都会等待,直到锁释放为止。
如:打开两个连接数据库的会话命令行窗口,当会话1窗口获取写锁以后,会话2不可以任何操作,会阻塞,包括查询也不可以,会话1执行完以后,会话2就会立马执行。
MyISAM读双向写的案例:
一个会话使用锁表给表加读锁,这个会话可以锁定表中的记录,但更新和访问其他表都会提示错误,同时,另一个会话可以查询表中的记录,但更新就会出现锁等待
会话1先加读锁:lock table mylock read,这时候会话2可以查询,但不能增改操作,
但是会话1也不能增改操作,只能查询,并且会话1不能查询其他表,会提示出错查的那个另外一个表没有加锁
MyISAM在执行查询语句之前,会自动给涉及的所有表加读锁,在执行更新操作前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此用户通常不需要使用命令来显式加锁,上例中的加锁时为了演示效果。
MyISAM的并发插入问题
MyISAM表的读和写是串行的,这是就总体而言的,在一定条件下,MyISAM也支持查询和插入操作的并发执行
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
InnoDB锁
1,事务及其ACID属性
事务是由一组SQL语句组成的逻辑处理单元,事务具有4属性,通常称为事务的ACID属性。
原子性(Actomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。
持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
2,并发事务带来的问题
相对于串行处理而言,并发事务处理能大大增加数据库资源的效率,提高数据库系统的交易总量,从而可以支持更多用户的并发操作,但同时,会带来以下问题:
脏读:一个事务正在对一条记录做修改,在这个事务并提交前,这条记录的数据就处于替换状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二一个事务读取了这些“脏”的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地称为“脏读”
不可重复读:一个事务在读取某些数据已经发生了改变,或某些记录已经被删除了!这种现象叫做“不可重复读”。
幻读:一个事务按相同的查询条件重新恢复以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”
上述出现的问题都是数据库读一致性的问题,可以通过事务的隔离机制来进行保证。
数据库的事务隔离越严格,并发副本就越小,但付出的代价也就只是,因为事务隔离本质上就是使事务在一定程度上串行化,需要根据具体的业务需求来决定使用隔离等级
可以通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
3,InnoDB的行锁模式及加锁方法
共享锁(S) :。又称读锁允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁若事务Ť对数据对象甲加上小号锁,则事务Ť可以读甲但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对甲做任何修改。
排他锁(X) :。又称写锁允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和排他写锁若事务Ť对数据对象甲加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。
mysql InnoDB引擎默认的修改数据语句:
更新,删除,插入都会自动给涉及到的数据加上排他锁,select语句不会加任何锁类型,如果加排他锁可以使用…进行更新语句,加共享锁可以使用选择...锁定在共享模式语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过用于更新和锁,共享模式锁的方式查询数据,但可以直接通过从…查询数据中选择…,因为普通查询没有任何锁机制。
InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,另外是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
1,在不通过索引条件查询的时候,innodb使用的是表锁而不是行锁
create table tab_no_index(id int,name varchar(10)) engine=innodb;
insert into tab_no_index values(1,1),(2,2),(3,3),(4,4);
session1只给一行加了排他锁,但是session2在请求其他行的排他锁的时候,会出现锁等待。原因是在没有索引的情况下,innodb只能使用表锁。
2,创建带索引的表进行条件查询,innodb使用的是行锁
create table tab_with_index(id int,name varchar(10)) engine=innodb;
alter table tab_with_index add index id(id);
insert into tab_with_index values(1,1),(2,2),(3,3),(4,4);
3,由于mysql的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但仍然无法访问到特定的数据
insert into tab_with_index values(1,4);
对于MyISAM的表锁,主要讨论了以下几点:
(1)共享读锁(S)之间是兼容的,但共享读锁(S)与排他写锁(X)之间,以及排他写锁( X)之间是互斥的,也就是说读和写是串行的。
(2)在一定条件下,MyISAM的允许查询和插入并发执行,我们可以利用这一点来解决应用中对同一表查询和(3)MyISAM的锁调度机制是写优先,这并不一定适合所有应用,用户可以通过设置LOW_PRIORITY_UPDATES参数,或在INSERT,UPDATE,DELETE语句中指定LOW_PRIORITY选项来调节读(4)由于表锁的锁定粒度大,读取之间又是串行的,因此,如果更新操作指针,MyISAM表可能会出现严重的锁等待,可以考虑采用InnoDB表来减少锁冲突。
对于InnoDB表,此处主要讨论了以下几项内容:
(1)InnoDB的行锁是基于索引实现的,如果不通过索引访问数据,InnoDB会使用表锁。
(2)在不同的隔离等级下,InnoDB的锁机制和一致性读策略不同。
在了解InnoDB锁特性后,用户可以通过设计和SQL调整等措施减少锁冲突和死锁,包括:
最好使用适当的隔离等级;精心设计索引,并正确使用索引访问数据,使加锁更精确,从而减少锁冲突的机会;
选择合理的事务大小,小事务发生锁冲突的几率也更小;
给记录集显式加锁时,最好一次性请求足够等级的锁。某些要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁
不同的程序访问一组表时,应尽量遵循相同的顺序访问各表,对一个表而言,可以以固定的顺序访问表中的行。这样可以大大减少死锁的机会;
尽量使用预定条件访问数据,这样可以避免间隙锁对并发插入的影响;不要申请超过实际需要的锁等级;除非必须,查询时不要显示加锁;
对于某些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能。
以上就是MySql锁机制(mysql锁机制应用场景)的详细内容,想要了解更多 MySql锁机制的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。