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、隔离级别

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

  • 未提交读(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;

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

时间: 2024-10-01 21:44:23

MySQL(八)的相关文章

mysql八:ORM框架SQLAlchemy

阅读目录 一 介绍 二 创建表 三 增删改查 四 其他查询相关 五 正查.反查 一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果. 1.安装 pip3 install sqlalchemy  2.架构与流程 #1.使用者通过ORM对象提交命令 #2.将命令交给SQLAlchemy Core(Schema/Types SQL Express

使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案

本文提供了对c3p0与DBCP连接池连接MySql数据库时, 8小时内无请求自动断开连接的解决方案.首先介绍一下我在项目(c3p0连接池)中遇到的问题,后面还提供了使用DBCP连接池的解决方案. 项目环境: Java Web项目框架为Spring MVC+JPA,使用c3p0连接池,发布环境为Tomcat 7 错误描述: 项目运行一段时间(大概几个小时)之后访问时会出现第一次访问报错,再次访问正常的现象,且多次出现此问题. 报错日志: [plain] view plaincopy org.spr

MySQL 5.6对已有Mysql单实例的机器,再添加mysql数据库,实现单机多实例

一.需求: 对已有Mysql单实例的机器,再添加两个mysql数据库,实现单机多实例. 一个绑定在端口3306,另外两个绑定在端口3307,3308: 数据分别存放在/data/mysqldata./data/mysqldata2./data/mysqldata3 三个实例均采用InnoDB作为默认的存储引擎,字符编码采用UTF-8: 三个实例均采用相同的性能优化配置参数: MySQL的源码安装请看我的另一篇博客http://yylinux.blog.51cto.com/8831641/1677

MYSQL的单机多实例部署

Centos6.6安装并配置单机多实例的MYSQL数据库 本文介绍安装单机多实例的MYSQL数据库的环境如下: 系统平台环境:Centos6.6 Mysql软件包:Mysql-5.5.32.tar.gz 一:安装MYSQL需要的依赖包和编译软件 #yum install ncurses-devel libaio-devel -y 二:安装编译MYSQL需要的软件(mysql5.2版本以后都需要使用cmake来编译安装MYSQL) #rpm -ivh cmake-2.8.12.2-4.el6.x8

mysql 5.5源码包安装

注:由于mysql5.5的源码包安装与mysql之前的版本安装方法不同,故写一篇随笔记录.5.5的版本不再是./configure make make install 这里用到了cmake了,cmake是一个跨平台的编译工具. 注意: mysql-5.5以后的版本不能使用make编译,只能使用cmake工具编译安装. cmake指定编译选项的方式不同于make . "./configure" 与 "cmake . "相似 "./configure --he

MySQL 常用基础命令

一.启动与关闭 1.1 Linux下启动mysql 的命令: a. rpm包安装:service mysqld start b. 源码包安装:/usr/local/mysql/bin/mysqld_safe --user=mysql & 1.2 Linux下重启mysql 的命令: a. rpm包安装:service mysqld restart b. 源码包安装: 先关闭mysql /usr/local/mysql/bin/mysqladmin -uroot -p shutdown 再启动my

使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方式

本文提供了对c3p0与DBCP连接池连接MySql数据库时. 8小时内无请求自己主动断开连接的解决方式.首先介绍一下我在项目(c3p0连接池)中遇到的问题,后面还提供了使用DBCP连接池的解决方式. 基本问题解决 项目环境: Java Web项目框架为Spring MVC+JPA,使用c3p0连接池,公布环境为Tomcat 7 错误描写叙述: 项目执行一段时间(大概几个小时)之后訪问时会出现第一次訪问报错,再次訪问正常的现象.且多次出现此问题. 报错日志: org.springframework

MySQL 基础常用命令

一.启动与关闭 1.1 Linux下启动mysql 的命令: a. rpm包安装:service mysqld start b. 源码包安装:/usr/local/mysql/bin/mysqld_safe --user=mysql & 1.2 Linux下重启mysql 的命令: a. rpm包安装:service mysqld restart b. 源码包安装: 先关闭mysql /usr/local/mysql/bin/mysqladmin -uroot -p shutdown 再启动my

【MySQL】mysql root密码忘记怎么办?

MySQL忘记密码了怎么解决 笔者曾经有一次误删了mysqlroot用户,怎么办? 之前的解决方式是通过忽略授权表的方式重启mysql然后插入相关数据解决该问题的,但是这种方式需要重启mysql,会影响现有业务,那么有没有其他方式可以不重启MySQL就解决呢? 因为mysql的user表示MyISAM引擎的,因此我们可以通过修改对应的文件来解决这个问题.下面是本人在测试环境的一次演练,仅供参考. 一.查看现有用户 04:18:34 [email protected] [mysql]>select

centos7下使用mysql离线安装包安装mysql5.7

服务器环境: centos7 x64 需要安装mysql5.7+ 一.卸载CentOS7系统自带mariadb # 查看系统自带的Mariadb [root@CDH-141 ~]# rpm -qa|grep mariadb mariadb-libs-5.5.44-2.el7.centos.x86_64 # 卸载系统自带的Mariadb [root@CDH-141 ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7.centos.x86_64 # 删除etc