mysql锁特性_MySQL(八)之锁和事务特性

一、MySQL锁

相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

1、MySQL这3种锁的特性可大致归纳如下。

开销、加锁速度、死锁、粒度、并发性能表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

从上述特点可见,很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度来说:表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。

2、执行操作时施加的锁的模式

读锁:用户在读的时候施加的锁,为防止别人修改,但是用户可以读,还被称为共享锁。

写锁:也称为独占锁,排它锁。其他用户不能读,不能写。

3、锁的实现位置

MySQL锁:可以手动使用,可以使用显示锁。

存储引擎锁:自动进行的(隐式锁)。

4、显示锁(只能使用在表级锁)

锁添加于解除的语句:

LOCK TABLES :施加锁

UNLOCK TABLES:解锁

语法: LOCK TABLES

tbl_name lock_type

[, tbl_name lock_type] ...

READ | WRITE:锁的类型

读锁举例:MariaDB [hellodb]> LOCK TABLES classes READ;

Query OK, 0 rows affected (0.00 sec)

在打开一个终端,可以在classes表中进行查询,但若想写入数据需要手动释放锁。MariaDB [hellodb]> SELECT * FROM classes;

+---------+-----------------+----------+

| ClassID | Class           | NumOfStu |

+---------+-----------------+----------+

|       1 | Shaolin Pai     |       10 |

|       2 | Emei Pai        |        7 |

|       3 | QingCheng Pai   |       11 |

|       4 | Wudang Pai      |       12 |

|       5 | Riyue Shenjiao  |       31 |

|       6 | Lianshan Pai    |       27 |

|       7 | Ming Jiao       |       27 |

|       8 | Xiaoyao Pai     |       15 |

|       9 | Jiuyin Zhenjing |       22 |

+---------+-----------------+----------+

9 rows in set (0.00 sec)

MariaDB [hellodb]> INSERT INTO classes VALUE(10,'Jiuyang Shengong',23);

Query OK, 1 row affected (28.72 sec)

上面插入数据的操作在执行时会阻塞掉,除非在执行解锁才能执行插入数据。MariaDB [hellodb]> UNLOCK TABLES;

Query OK, 0 rows affected (0.00 sec)

写锁举例:MariaDB [hellodb]> LOCK TABLES classes WRITE;

Query OK, 0 rows affected (0.00 sec)

在打开一个终端,发现既不能执行写操作有不能执行查询操作,除非解锁。MariaDB [hellodb]> SELECT * FROM classes;

+---------+------------------+----------+

| ClassID | Class            | NumOfStu |

+---------+------------------+----------+

|       1 | Shaolin Pai      |       10 |

|       2 | Emei Pai         |        7 |

|       3 | QingCheng Pai    |       11 |

|       4 | Wudang Pai       |       12 |

|       5 | Riyue Shenjiao   |       31 |

|       6 | Lianshan Pai     |       27 |

|       7 | Ming Jiao        |       27 |

|       8 | Xiaoyao Pai      |       15 |

|       9 | Jiuyin Zhenjing  |       22 |

|      10 | Jiuyang Shengong |       23 |

+---------+------------------+----------+

10 rows in set (5.66 sec)

MariaDB [hellodb]> UNLOCK TABLES;

Query OK, 0 rows affected (0.00 sec)

注意:我们在日常进行做备份操作时,才需要手动施加读锁,避免出现数据不一致情况。一般情况是不会手动执行锁操作的。

5、行级锁

InnoDB存储引擎也支持另外一种显示锁(锁定挑选出的部分行,支持行级锁)

语法:SELECT ....LOCK IN SHARE MODE; //读锁

SELECT .... FOR UPDATE;         //写锁

6、事务:Transaction

概念:事务就是一组原子性的查询语句,也即将多个查询当作一个独立的工作单元。

ACID测试:能够满足ACID测试就表示其支持事务,或兼容事务。A:Atomicity,原子性,都执行或者都不执行。

C:Consistency,一致性,从一个一致性状态转到另外一个一致性状态。

I:Isolaction,隔离性,一个事务的所有修改操作在提交前对其他事务时不可见的。

D: Durability, 持久性,一旦事务得到提交,其所做的修改会永久有效。

7、隔离级别

在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。我们的数据库锁,也是为了构建这些隔离级别存在的。

4a18636505f72d507385249389528984.png未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据,数据库一般都不会用。

提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)。

可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读 。

串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。

跟事务相关的常用命令:MariaDB [hellodb]>start transaction:启动事务

MariaDB [hellodb]>commit:事务提交

MariaDB [hellodb]>rollback:事务回滚

MariaDB [hellodb]>SAVEPOINT identifier:控制回滚的位置

MariaDB [hellodb]>ROLLBACK [WORK] TO [SAVEPOINT] identifier

注意:MyISAM存储引擎不支持事务。

应用举例:MariaDB [hellodb]> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+------------------+----------+

| ClassID | Class            | NumOfStu |

+---------+------------------+----------+

|       1 | Shaolin Pai      |       10 |

|       2 | Emei Pai         |        7 |

|       3 | QingCheng Pai    |       11 |

|       4 | Wudang Pai       |       12 |

|       5 | Riyue Shenjiao   |       31 |

|       6 | Lianshan Pai     |       27 |

|       7 | Ming Jiao        |       27 |

|       8 | Xiaoyao Pai      |       15 |

|       9 | Jiuyin Zhenjing  |       22 |

|      10 | Jiuyang Shengong |       23 |

+---------+------------------+----------+

10 rows in set (0.00 sec)

MariaDB [hellodb]> DELETE FROM classes WHERE ClassID=10;

Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+-----------------+----------+

| ClassID | Class           | NumOfStu |

+---------+-----------------+----------+

|       1 | Shaolin Pai     |       10 |

|       2 | Emei Pai        |        7 |

|       3 | QingCheng Pai   |       11 |

|       4 | Wudang Pai      |       12 |

|       5 | Riyue Shenjiao  |       31 |

|       6 | Lianshan Pai    |       27 |

|       7 | Ming Jiao       |       27 |

|       8 | Xiaoyao Pai     |       15 |

|       9 | Jiuyin Zhenjing |       22 |

+---------+-----------------+----------+

9 rows in set (0.00 sec)

MariaDB [hellodb]> ROLLBACK;

Query OK, 0 rows affected (0.01 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+------------------+----------+

| ClassID | Class            | NumOfStu |

+---------+------------------+----------+

|       1 | Shaolin Pai      |       10 |

|       2 | Emei Pai         |        7 |

|       3 | QingCheng Pai    |       11 |

|       4 | Wudang Pai       |       12 |

|       5 | Riyue Shenjiao   |       31 |

|       6 | Lianshan Pai     |       27 |

|       7 | Ming Jiao        |       27 |

|       8 | Xiaoyao Pai      |       15 |

|       9 | Jiuyin Zhenjing  |       22 |

|      10 | Jiuyang Shengong |       23 |

+---------+------------------+----------+

10 rows in set (0.00 sec)

通过上面可以发现一旦事务没有提交就能执行回滚,而删除并提交后回滚就不能起作用了:MariaDB [hellodb]> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> DELETE FROM classes WHERE ClassID=10;

Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> COMMIT;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+-----------------+----------+

| ClassID | Class           | NumOfStu |

+---------+-----------------+----------+

|       1 | Shaolin Pai     |       10 |

|       2 | Emei Pai        |        7 |

|       3 | QingCheng Pai   |       11 |

|       4 | Wudang Pai      |       12 |

|       5 | Riyue Shenjiao  |       31 |

|       6 | Lianshan Pai    |       27 |

|       7 | Ming Jiao       |       27 |

|       8 | Xiaoyao Pai     |       15 |

|       9 | Jiuyin Zhenjing |       22 |

+---------+-----------------+----------+

9 rows in set (0.00 sec)

而使用COMMIT命令是回滚所有的,而若想回滚到指定位置需要使用SAVEPOINT命令:MariaDB [hellodb]> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> DELETE FROM classes WHERE ClassID=9;

Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> SAVEPOINT a;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> DELETE FROM classes WHERE ClassID=5;

Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> SAVEPOINT b;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> DELETE FROM classes WHERE ClassID=6;

Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> SAVEPOINT c;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+---------------+----------+

| ClassID | Class         | NumOfStu |

+---------+---------------+----------+

|       1 | Shaolin Pai   |       10 |

|       2 | Emei Pai      |        7 |

|       3 | QingCheng Pai |       11 |

|       4 | Wudang Pai    |       12 |

|       7 | Ming Jiao     |       27 |

|       8 | Xiaoyao Pai   |       15 |

+---------+---------------+----------+

6 rows in set (0.00 sec)

MariaDB [hellodb]> ROLLBACK TO b;

Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> SELECT * FROM classes;

+---------+---------------+----------+

| ClassID | Class         | NumOfStu |

+---------+---------------+----------+

|       1 | Shaolin Pai   |       10 |

|       2 | Emei Pai      |        7 |

|       3 | QingCheng Pai |       11 |

|       4 | Wudang Pai    |       12 |

|       6 | Lianshan Pai  |       27 |

|       7 | Ming Jiao     |       27 |

|       8 | Xiaoyao Pai   |       15 |

+---------+---------------+----------+

7 rows in set (0.00 sec)

8、关于事务的一些系统参数

如果没有显式启动事务,每个语句都会当作一个默认的事务,其执行完成会被自动提交。影响一定的IO性能。

查看自动提交功能是否启用:MariaDB [hellodb]> SELECT @@GLOBAL.autocommit;

+---------------------+

| @@GLOBAL.autocommit |

+---------------------+

|                   1 |

+---------------------+

1 row in set (0.00 sec)

关闭此功能:MariaDB [hellodb]> SET GLOBAL autocommit = 0;

Query OK, 0 rows affected (0.00 sec)

注意:关闭自动提交,请记得一定要手动启动事务,还要得手动提交事务!

9、mysql的事务隔离级别

查看mysql的事务隔离级别:MariaDB [hellodb]> SHOW GLOBAL VARIABLES LIKE '%iso%';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |

+---------------+-----------------+

1 row in set (0.00 sec)

还可以使用下面的语句:

MariaDB [hellodb]> SELECT @@GLOBAL.tx_isolation;

建议:对事物要求不特别严格的场景下,可以使用读提交,其性能比可重复读好点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值