mysql单个表回退到某个点_MySQL锁模型与事物

本文深入探讨了MySQL中MyISAM和InnoDB存储引擎的锁机制,包括表级锁和行级锁的特点及应用。重点介绍了表级锁的读写操作、并发插入、事务隔离级别以及死锁的处理。对于InnoDB,强调了其行级锁的优势以及在事务处理中的重要作用。此外,还提供了避免和处理死锁的建议。
摘要由CSDN通过智能技术生成

MySQL中不同的存储引擎支持不同的锁机制,比如,MySAM和MEMORY存储引擎采用表级锁,InnoDB支持表级锁和行级锁(默认采用行级锁),BDB(被InnoDB取代)支持表级锁和页面锁。

查看mysq提供的存储引擎:mysql> show engines;

查看mysql当前默认的存储引擎:mysql> show variables like '%storage_engine%';

查看某个表用的引擎:mysql> show create table 表名;

一、表级锁

1、表级锁特点

开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。当需要频繁对大部分数据做 GROUP BY 操作或者需要频繁扫描整个表时,推荐使用表级锁。

命令mysql> show status like 'Table%';

Table_locks_immediate 指的是能够立即获得表级锁的次数,而Table_locks_waited指的是不能立即获取表级锁而需要等待的次数。如果 Table_locks_waited的值比较大的话,则说明存在着较严重的表级锁争用情况,这是可能需要创建一个专有的缓存表,或者通过其它方式来减小表的大小,或者降低表级锁命令调用的频率。

2、表级锁的锁模式

读锁:成功申请读锁的前提是当前没有线程对该表使用写锁,否则该语句会被阻塞。申请读锁成功后,其他线程也可以对该表进行读操作,但不允许有线程对其进行写操作,包括当前线程。 用法:申请——LOCK TABLE table_name [ AS alias_name ] READ,释放——UNLOCK tables。

写锁:成功申请写锁的前提是当前没有线程对表加读锁和其他写锁,否则会被阻塞。写锁可以加优先级,当多个线程同时申请多种锁(LOW_PRIORITY,READ,WRITE)时,LOW_PRIORITY的优先级最低。 用法:申请——LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE。

3、如何给表加锁

MyISAM执行SELECT前会自动把涉及的所有的表加读锁,在执行UPDATE、DELETE、INSERT前会自动把涉及的所有的表加写锁。用户一般不需要直接用LOCK TABLE命令给MyISAM表加锁。

显式地给MyISAM表加锁,一般是为了模拟事物操作,实现在某一个时间点多个表的一致性读取。例如,order表记录了每个订单的总金额(total),order_detail记录了每个订单中每个产品的金额小计(subtotal),如果需要检查俩个表的金额是否一致,则:

Lock tables orders read local, order_detail read local;

Select sum(total) from orders;

Select sum(subtotal) from order_detail;

Unlock tables;

注:local选项作用是在满足MyISAM表并发插入条件的情况下,允许其他用户在表尾并发插入记录

4、一个表锁导致阻塞的例子

Session1

Session2

CREATE TABLE my_contacts # 创建表联系人

(

id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,

NAME VARCHAR (30) NOT NULL,

gender CHAR(1) NOT NULL DEFAULT 'M',  #'M'或'F'

birthday DATE,   # 1980-09-15

phone VARCHAR (11) NOT NULL,

information BLOB

) ENGINE = MYISAM ;

INSERT  INTO my_contacts(NAME,gender,birthday,phone,information) VALUES ('ZhangSan','F','1990-09-09','13513513513','Friend');

INSERT  INTO my_contacts(NAME,gender,birthday,phone,information) VALUES ('LiSi','F','1991-08-12','18989107021','strange boy');

LOCK TABLE my_contacts WRITE;

SELECT * FROM my_contacts WHERE NAME="ZhangSan";

返回查询结果

SELECT * FROM my_contacts WHERE NAME="LiSi"; 阻塞… …

UNLOCK TABLES;

阻塞… …

返回查询结果

5、注意事项

Lock table时,如果查询语句中用到别名以及其他的表,那么别名和其他的表均需要锁住。如果锁住了别名,那么查询语句中就不能直接用表名了。在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。

LOCK TABLE my_contacts READ;

SELECT a.name ,b.math FROM my_contacts a, scores b WHERE a.`name`=b.`name`;

以上查询语句中,my_contacts被锁住了,但使用了别名a,a没有被锁住;表scores也没有被锁住,且scores也用了别名,修改为:

LOCK TABLE my_contacts as a READ, scores as b READ;

SELECT a.name ,b.math FROM my_contacts a, scores b WHERE a.`name`=b.`name`;

6、并发插入

一般而言,MyISAM表的读和写是串行的。在一定条件下,MyISAM表也支持查询和插入并发执行。

MyISAM有一个系统变量concurrent_insert,专用于控制并行插入的行为,其值可以为0、1或2。为0时,不允许并发插入;为1时,(默认设置),如果MyISAM表中没有空洞(即表的中间没有被删除的行),则允许一个进程读表,另一个进程在表尾插入;为2时,允许在表尾并发插入记录。

Session1

Session2

SHOW VARIABLES LIKE "%current_insert%";

current_insert的值为AUTO,(1)

LOCK TABLE my_contacts READ LOCAL;

当前session可以查询,不能更新;其它session可以并发插入(如果无空洞),不能删除更新

INSERT INTO my_contacts (NAME,gender,birthday,phone,information) VALUES ('LiHong','F','1960-01-01','18956234756','');

插入失败,my_contacts被locked;

UPDATE my_contacts SET gender = 'M' WHERE NAME = 'ZhangSan';

更新失败,my_contacts被locked;

INSERT INTO my_contacts (NAME,gender,birthday,phone,information) VALUES ('WangHui','M','1990-01-01','13758694231','');

并发插入成功;

SELECT id, gender FROM my_contacts WHERE NAME  = 'ZhangSan';

查询当前session内的记录成功;

SELECT * FROM my_contacts WHERE NAME  = 'WangHui';

无法查询到并发插入的记录;

UPDATE my_contacts SET gender = 'M' WHERE NAME = 'LiSi';

更新操作被阻塞… …

UNLOCK TABLES;

被阻塞… …

SELECT * FROM my_contacts WHERE NAME  = 'WangHui';

查询其它session插入的记录成功

更新记录成功

当一个表获得READ LOCAL锁后,该线程可以对表进行查询,不能更新,插入等,但其它线程可以并发插入,(concurrent_insert=2或者concurrent_insert=1且无空洞),但不能删除和更新。

MyISAM的并发插入特性可用来解决对同一表查询和插入的锁争用。例如,设置concurrent_insert=2,且通过空闲时段执行OPTIMIZE TABLE语句来整理空间碎片,收回因删除记录产生的中间空洞。

7、MyISAM的粒调度

MySQL一般认为写请求比度请求更重要,所以一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,写进程会先获得锁,不仅如此,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。这时,可以通过一些设置来调节MyISAM 的调度行为。

通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。

通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。

通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。

给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。

需要注意的是,一些需要长时间运行的查询操作,也会使写进程“饿死”!应用中应尽量避免长时间运行的查询操作,可以通过使用中间表等措施对SQL语句做一定的“分解”,使每一步查询都能在较短时间完成,从而减少锁冲突。如果复杂查询不可避免,应尽量安排在数据库空闲时段执行,比如一些定期统计可以安排在夜间执行。

二、行级锁

InnoDB与MyISAM的最大不同点是:1、支持事物(Transaction),2、支持行级锁。锁定粒度最细的一种锁,能大大减少数据库操作的冲突,由于其粒度小,加锁的开销最大。

1、事物

事务是由一组SQL语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值