mysql myisam的锁机制
首先我们知道
MySQL支持多种引擎,并且不同存储引擎有很多不同,最重要的
即便是自动提交模式下 当start transaction;之后,必须要显现的commit;才能释放锁资源,
myisam的锁机制:
不支持行级锁,支持的是表级锁,分为共享读锁和独占写锁。
1)什么是表锁
表锁:操作对象是数据表。Mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行
2)什么是读锁
读锁:也叫共享锁、S锁,若事务T对表A加上S锁,则事务T可以读表A但不能修改表A,其他事务只能再对表A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读表A,但在事务T释放表A上的S锁之前不能对表A做任何修改,总结起来就是:我读的时候你不能写;
3)什么是写锁
写锁:又称排他锁、X锁。若事务T对表A加上X锁,事务T可以读表A也可以修改表A,其他事务不能再对表A加任何锁,直到事务T释放表A上的锁。这保证了其他事务在事务T释放表A上的锁之前不能再读取和修改表A,总结起来就是:我写的时候,你不能读,也不能写。
实验一:我读的时候你不能写,但是你可以读;
首先表company_info是myisam引擎的表;
事务1,执行长时间的查询操作
mysql> select company_id from company_info where company_name like '%liluwedafasdf%';
Empty set (43.27 sec)
事务2,尝试更新表company_info ,发现等待。。。执行了21秒。
mysql>update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000';
+----------------------------------+--------------+
| company_id | company_name |
+----------------------------------+--------------+
| 4028809f60bf40fd0160bf4678be0000 | liuhehhe |
+----------------------------------+--------------+
Query OK, 0 rows affected(21.98 sec)
Rows matched: 1 Changed: 0 Warnings: 0
再打开一个窗口,可以看到,事务2确实在等待一个表级别的锁:
mysql> show processlist;
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
| 14 | root | localhost | liuwenhe | Sleep | 4506 | | NULL |
| 15 | root | localhost | liuwenhe | Query | 1 | Sending data | select company_id from company_info where company_name like '%liluwedafasdf%' |
| 16 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000 |
| 17 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)
然后再开启一个窗口,执行查询操作(事务3):发现事务1还没有执行完,事务3就执行完了,说明事务1不会阻塞事务3;
mysql> select company_name from company_info where company_id='4028809f60bf40fd0160bf4678be0000';
+--------------+
| company_name |
+--------------+
| liuhehhe |
+--------------+
1 row in set (2.10 sec)
实验一证明:事务1对表A加上S锁,则事务1可以读表A但不能修改表A,其他事务只能再对表A加S锁,而不能加X锁,直到T释放A上的S 锁。也就是说我读的时候你不能写,但是你可以读;
实验二:我写的时候,你不能读,也不能写;
事务1:执行更新一个表的一个字段。
mysql> update company_info set company_name='liuhehhe' where company_name like '%liuwehe%';
Query OK, 0 rows affected (1.95 sec)
Rows matched: 0 Changed: 0 Warnings: 0
事务2尝试查询这个表,发现等待。。
mysql> select count(*) from company_info;
+----------+
| count(*) |
+----------+
| 1818708 |
+----------+
1 row in set (1.11 sec)
再开启一个窗口,查看进程,发现事务2确实在等待一个表级别的锁;
mysql> show processlist;
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
| 19 | root | localhost | liuwenhe | Query | 1 | updating | update company_info set company_name='liuhehhe' where company_name like '%liuwehe%' |
| 20 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| select count(*) from company_info |
| 21 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
实验二证明:mysql的myisam引擎下,更新表的一行数据,也会上一个表级别的锁排他锁,不允许其他事务读取该表的数据,当然也不允许其他事务去写这个表,也就是说:我写的时候,你不能读,也不能写;
mysql myisam的锁小结:
MyISAM的读操作和写操作,以及写操作之间是串行的!MyISAM在执行读写操作的时候会自动给表加相应的锁(也就是说不用显示的使用lock table命令,然后注意是表级别的锁),MyISAM总是一次获得SQL语句所需要的全部锁,这也是MyISAM不会出现死锁的原因.区别于mysql innodb的锁机制,innodb的一般的select 是不会加任何锁的,接下来会介绍innodb的锁机制,请看下一篇文章