MySQL行级锁、表级锁、页级锁详细介绍
时间:2024-05-11 12:24:58 来源:未知 作者:站长技术网 点击:次
页级:引擎 BDB。 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果你是写锁,则其它进程则读也不允许 MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行页级锁定,对InnoDB表进行行级锁定。 对READ,MySQL使用的锁定方法原理如下: InnoDB使用行锁定,BDB使用页锁定。对于这两种存储引擎,都可能存在死锁。这是因为,在SQL语句处理期间,InnoDB自动获得行锁定和BDB获得页锁定,而不是在事务启动时获得。 行级锁定的优点: 行级锁定的缺点: 在以下情况下,表锁定优先于页级或行级锁定: /* ========================= mysql 锁表类型和解锁语句 ========================= */ 如果想要在一个表上做大量的 INSERT 和 SELECT 操作,但是并行的插入却不可能时,可以将记录插入到临时表中,然后定期将临时表中的数据更新到实际的表里。可以用以下命令实现: 复制代码 代码如下:
行级锁的优点有: 行级锁的缺点有: MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。 例如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level-locking);BDB存储引擎采用的是页面锁(page-level-locking),同时也支持表级锁;InnoDB存储引擎既支持行级锁,也支持表级锁,默认情况下是采用行级锁。 上述三种锁的特性可大致归纳如下: 三种锁各有各的特点,若仅从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如WEB应用;行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。 MySQL表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。什么意思呢,就是说对MyISAM表进行读操作时,它不会阻塞其他用户对同一表的读请求,但会阻塞 对同一表的写操作;而对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作。 MyISAM表的读和写是串行的,即在进行读操作时不能进行写操作,反之也是一样。但在一定条件下MyISAM表也支持查询和插入的操作的并发进行,其机制是通过控制一个系统变量(concurrent_insert)来进行的,当其值设置为0时,不允许并发插入;当其值设置为1 时,如果MyISAM表中没有空洞(即表中没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录;当其值设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。 MyISAM锁调度是如何实现的呢,这也是一个很关键的问题。例如,当一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,此时MySQL将会如优先处理进程呢?通过研究表明,写进程将先获得锁(即使读请求先到锁等待队列)。但这也造成一个很大的缺陷,即大量的写操作会造成查询操作很难获得读锁,从而可能造成永远阻塞。所幸我们可以通过一些设置来调节MyISAM的调度行为。我们可通过指定参数low-priority-updates,使MyISAM默认引擎给予读请求以优先的权利,设置其值为1(set low_priority_updates=1),使优先级降低。 InnoDB锁与MyISAM锁的最大不同在于:一是支持事务(TRANCSACTION),二是采用了行级锁。我们知道事务是由一组SQL语句组成的逻辑处理单元,其有四个属性(简称ACID属性),分别为: 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全都不执行; InnoDB有两种模式的行锁: 1)共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。 2)排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和 排他写锁。(select * from table_name where.....for update) 另外:插入,更新性能优化的几个重要参数 复制代码 代码如下:
concurrent_insert 值可以设0不允许并发插入, 1当表没有空洞时, 执行并发插入, 2不管是否有空洞都执行并发插入. delay_key_write delayed_insert_limit, delayed_insert_timeout, delayed_queue_size /* ==================== MySQL InnoDB 锁表与锁行 ======================== */ 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料表单给锁住)。 举个例子: 假设有个表单products ,里面有id跟name二个栏位,id是主键。 例1: (明确指定主键,并且有此笔资料,row lock) 复制代码 代码如下: SELECT * FROM products WHERE FOR UPDATE; 例2: (明确指定主键,若查无此笔资料,无lock) 复制代码 代码如下: SELECT * FROM products WHERE FOR UPDATE; 例3: (无主键,table lock) 复制代码 代码如下: SELECT * FROM products WHERE FOR UPDATE; 例4: (主键不明确,table lock) 复制代码 代码如下: SELECT * FROM products WHERE id<>'3' FOR UPDATE; 例5: (主键不明确,table lock) 复制代码 代码如下: SELECT * FROM products WHERE id LIKE '3' FOR UPDATE; 注1: FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。 在MySql 5.0中测试确实是这样的 另外:MyAsim 只支持表级锁,InnerDB支持行级锁 |