mysql 学习记录(十八)--MyISAM表锁

一、理论:
1.mysql的myisam和memory引擎采用的是‘表级锁’。bdb存储引擎采用的是页面锁,但也支持表级锁。innodb存储引擎既支持行级锁也支持表级锁,但默认情况下采用行级锁。
2.表、行、页面锁的特性:
a.表级锁:开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发程度最低。
b.行级锁:开销大,加慢慢,会出现死销,锁定粒度小,发生锁冲突的概率低,并发程度最高。
c.页面锁:开销和加锁时间界于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发度一般。
3.锁的使用场景:
a.表级锁适应以查询为主,少量按索引条件更新数据的应用,如web应用
b.行级锁适应有大量按索引条件并发更新少量不同数据,同时又有并发查询应用
4.如果
show status like 'table%'显示的
talbe_locks_immediate 值较高,则存在着较严重的表级锁争用情况
5.mysql表级锁的锁模式:
a.表共享读锁和表独占写锁:读锁不会阻塞其他用户
6.mysiam引擎在执行查询(select)语句前,会自动给涉及的所有表加读销,在执行更新操作(update,delete,inesrt)前,会自动给涉及的所有表加写锁。给myisam表显式加锁,一般是为了在一定程度模拟事务操作,实现对某一时间点多个表的一致性读取。如订单类操作。
7.lock table .... read local.(这样可以在myisam表并发插入的情况下,也允许其他用户在表尾并发插入记录)
8.在用lock tables给表显式加锁时,必须时间取得所有涉及表的锁,并且mysql不支持锁升级。因此,myisam总是一次获得sql语句所需要的全部锁。
9.concurrent_insert用来控制并发插入
a.concurrent_insert=0:不允许并发插入
b.concurrent_insert=1:如果myisam表中没有被删除的行,则myisam允许在一个进程读表的同时另一个进程从表尾插入记录,这也是mysql的默认设置
c.concurrent_insert=2:无论myisam表中有没有被删除的行,都允许在表尾并发插入记录
10.mysql默认:如读锁在先,写锁在后,同在一个队列里则先执行‘写锁’。
此行为可以如下调度:
a.通过指定启动参数low-priority-updates,使myisam引擎默认给予读请求以优先的权利。
b.通过执行命令set low_priority_updates=1,使该连接发出的更新请求优先级降低。
c.通过指定insert,update,delete的low_priority属性,降低该语句的优先级。

二、实践:

1.myisam存储引擎的写阻塞:
session_1:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> show status like 'table%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 1369  |
| Table_locks_waited    | 1     |
+-----------------------+-------+
2 rows in set (0.01 sec)


mysql> lock table film_text write;
Query OK, 0 rows affected (0.00 sec)


mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> insert into film_text(film_id,title) values(10005,'test111');
Query OK, 1 row affected (0.02 sec)


mysql> update film_text set title = 'test333' where film_id = 10005;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0


mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


session_2:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> select film_id,title from film_text where film_id = 10005;


^CCtrl-C -- sending "KILL QUERY 2" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> select film_id,title from film_text where film_id = 10005;
+---------+---------+
| film_id | title   |
+---------+---------+
|   10005 | test333 |
+---------+---------+
1 row in set (0.01 sec)


2.myisam存储引擎的读阻塞:
session_1:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> show status like 'table%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 1369  |
| Table_locks_waited    | 1     |
+-----------------------+-------+
2 rows in set (0.01 sec)


mysql> lock table film_text write;
^CCtrl-C -- sending "KILL QUERY 143" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted


mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> insert into film_text(film_id,title) values(10005,'test111');
Query OK, 1 row affected (0.02 sec)


mysql> update film_text set title = 'test333' where film_id = 10005;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0


mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


mysql> lock table film_text read;
Query OK, 0 rows affected (0.00 sec)


mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


session_2:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> select film_id,title from film where film_id = 1;
+---------+------------------+
| film_id | title            |
+---------+------------------+
|       1 | ACADEMY DINOSAUR |
+---------+------------------+
1 row in set (0.00 sec)


mysql> update film set tile = 'film_id_1' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film set title = 'film_id_1' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film_text set title = 'test10009' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film_text set title = 'test10009' where film_id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0


3.myisam存储引擎的读写并发例子:
session_1:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> lock table film_text read local;
Query OK, 0 rows affected (0.00 sec)


mysql> insert into film_text(film_id,title) values (20001,'test');
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
mysql> update film_text set title = '20001test' where film_id = 20001;
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
mysql> select film_id,title from film_text where film_id = 1;
+---------+-----------+
| film_id | title     |
+---------+-----------+
|       1 | test10009 |
+---------+-----------+
1 row in set (0.01 sec)


mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


mysql> select film_id,title from film_text where film_id = 1;
+---------+-----------+
| film_id | title     |
+---------+-----------+
|       1 | test10009 |
+---------+-----------+
1 row in set (0.00 sec)


mysql> Ctrl-C -- exit!
Aborted
abc@ubuntu:~$ 


session_2:
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> select film_id,title from film_text where film_id = 1;
+---------+-------+
| film_id | title |
+---------+-------+
|       1 | test  |
+---------+-------+
1 row in set (0.00 sec)


mysql> select film_id,title from film where film_id = 1;
+---------+------------------+
| film_id | title            |
+---------+------------------+
|       1 | ACADEMY DINOSAUR |
+---------+------------------+
1 row in set (0.00 sec)


mysql> update film set tile = 'film_id_1' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film set title = 'film_id_1' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film_text set title = 'test10009' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film_text set title = 'test10009' where film_id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0


mysql> insert into film_text(film_id,title ) values (30001,'test30001');
Query OK, 1 row affected (0.00 sec)


mysql> update film_text set title = 'test' where film_id = 1;
^CCtrl-C -- sending "KILL QUERY 4" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> update film_text set title = 'test' where film_id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0


你可能感兴趣的:(sql,mysql,数据库,myisam,表锁)