并发控制和锁机制
锁概念
锁的分类
- 读锁:又称共享锁、S锁,所有事务(人)只能读不能写 并且多个读互不阻塞
- 写锁:又称独占锁、排它锁、X 锁,除了当前事务外 会阻塞其它事务的读和写
锁的粒度
- 表级锁:MyISAM
- 行级锁:InnodB
锁的实现
- 存储引擎:自行实现其锁策略和锁粒度(由存储引擎自动施加锁)
- 服务器级:实现了锁,表级锁,用户可显式请求(用户手动请求)
锁策略
- 在锁粒度及数据安全性寻求的平衡机制
锁的实现
- 这里指的是手动实现加锁
表加锁
语法
LOCK TABLES tbl_name [[AS] alias] lock_type [, tbl_name [[AS] alias] lock_type] ...
#lock_type:
READ
WRITE范例
加读锁
- 总结:只对加锁的表生效,任何终端对所有表的读操作不受任何影响 但增删改操作无法进行,在其他终端同样进行修改和插入内容都进入到阻塞状态
#表加读锁前
mysql> insert students (name,age) VALUES ('james',16);
Query OK, 1 row affected (0.01 sec)
mysql> select * from students;
...
26 rows in set (0.00 sec)
#加读锁
mysql> LOCK TABLES students READ;
Query OK, 0 rows affected (0.00 sec)
#表加读锁后
mysql> insert students (name,age) VALUES ('azheng',18);
ERROR 1099 (HY000): Table 'students' was locked with a READ lock and can't be updated
mysql> select * from students;
...
26 rows in set (0.00 sec)加写锁
- 总结:只对加锁的表生效,当前终端的任何操作不受影响,其它终端会阻塞增删改查
#表加写锁前
mysql> insert students (name,age) VALUES ('azheng',18);
Query OK, 1 row affected (0.00 sec)
mysql> select * from students;
...
27 rows in set (0.00 sec)
#加写锁
mysql> LOCK TABLES students WRITE;
Query OK, 0 rows affected (0.00 sec)
#表加写锁后
#当前终端读写正常
mysql> insert students (name,age) VALUES ('azheng',23);
Query OK, 1 row affected (0.01 sec)
mysql> select * from students;
...
28 rows in set (0.00 sec)
#其他终端针对加锁的表均卡住不动,等待锁释放才能成功执行
mysql> select * from teachers;
...
4 rows in set (0.01 sec)
mysql> select * from students; #执行后会一直卡住不动,直到解锁
mysql> insert students (name,age) VALUES ('azheng',23); #执行后会一直卡住不动,直到解锁解锁
- 解全部当前会话的锁,加锁的终端关闭的话同时也会解锁
UNLOCK TABLES加全局读锁
- 关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁
语法
FLUSH TABLES [tb_name[,...]] [WITH READ LOCK]范例
- **总结:**加全局读锁后,对所有库、所有表皆可查询,但不能对任何表和库进行增删改
#在当前终端加全局读锁
FLUSH TABLES WITH READ LOCK;
#当前终端
------------------------------------------------------------------------------
#当前终端查询不受阻塞
mysql> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 66 | M |
| 2 | Zhang Sanfeng | 66 | M |
| 3 | Miejue Shitai | 88 | F |
| 4 | Lin Chaoying | 66 | F |
| 5 | xiangzheng | 23 | M |
| 6 | xiaohong | 17 | F |
+-----+---------------+-----+--------+
#当前终端修改阻塞
mysql> update teachers set age='19' where tid=6;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
#当前终端插入阻塞
mysql> insert teachers (name,age,gender) value ('xiaoqiang',26,'M');
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
#当前终端创建新的数据库阻塞
mysql> create database abc;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
------------------------------------------------------------------------------
#其他终端
------------------------------------------------------------------------------
#其他终端查询不受阻塞
mysql> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 66 | M |
| 2 | Zhang Sanfeng | 66 | M |
| 3 | Miejue Shitai | 88 | F |
| 4 | Lin Chaoying | 66 | F |
| 5 | xiangzheng | 23 | M |
| 6 | xiaohong | 17 | F |
+-----+---------------+-----+--------+
#其他终端修改阻塞
mysql> update teachers set age='19' where tid=6;
#其他终端插入阻塞
mysql> insert teachers (name,age,gender) value ('xiaoqiang',26,'M');
#其他终端创建新的数据库阻塞
mysql> create database abc;
------------------------------------------------------------------------------
#解锁后立刻可以进行写操作
UNLOCK TABLES;查询时加写或读锁
- 使用较少
语法
SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]范例: 同时在两个终端对同一行记录修改
- 由存储引擎自动加的锁
#同时对同一行记录执行update
#在第一终端提示1行成功
MariaDB [hellodb]> update students set classid=1 where stuid=24;
Query OK, 1 row affected (0.002 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#在第二终端提示0行修改
MariaDB [hellodb]> update students set classid=1 where stuid=24;
Query OK, 0 rows affected (0.000 sec)
Rows matched: 1 Changed: 0 Warnings: 0