MySQL之DDL、DML、读锁,写锁、显示锁、事务、隔离级别详解
mysql> help insert;
DDL:
DATABASE
TABLE
VIEW
DML:
SELECT
INSERT/REPLACE
UPDATE
DELETE
INSERT INTO:
第一种:
INSERT INTO tb_name [(col1, col2,...)] {VALUES|VALUE} (val1, val2,...)[,(val21,val22,...),...]
第二种:
INSERT INTO tb_name SET col1=val1, col2=val2, ...
第三种:
INSERT INTO tb_name SELECT clause
REPLACE的工作机制:与INSERT相同,除了在新插入的数据与表中的主键或惟一索引定义的数据相同会替换老的行;
UPDATE:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET col_name1=val1 [, col_name2=val2] ...
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
UPDATE通常情况下,必须要使用WHERE子句,或者使用LIMIT限制要修改的行数;
--safe-updates
DELETE:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
TRUNCATE tb_name
explain
MySQL锁:
执行操作时施加的锁模式
读锁:共享锁
写锁:独占锁,排它锁
锁粒度:
表锁:table lock
锁定了整张表
行锁:row lock
锁定了需要的行
粒度越小,开销越大,但并发性越好;
粒度越大,开销越小,但并发性越差;
锁的实现位置:
MySQL锁:可以使用显式锁
存储引擎锁:自动进行的(隐式锁);
显式锁(表级锁):
LOCK TABLES
UNLOCK TABLES
LOCK TABLES
tbl_name lock_type
[, tbl_name lock_type] ...
锁类型:READ|WRITE
【读锁】 以后备份时可以使用这个锁
[root@pc0003 ~]# mysql -p
mysql> use hellodb;
Database changed
mysql> lock tables classes read;
Query OK, 0 rows affected (0.00 sec)
【再启动一个终端2 mysql】
mysql> use hellodb;
Database changed
mysql> 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 | Liangshan | 22 |
+---------+----------------+----------+
9 rows in set (0.00 sec)
【尝试插入数据,被阻塞】
mysql> insert into classes value (10,'TaoYuan',23);
【直到对方释放锁,终端2 mysql才能被执行】
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
【对方释放锁,终端2 mysql才能被执行看阻塞时间】
mysql> insert into classes value (10,'TaoYuan',23);
Query OK, 1 row affected (2 min 13.29 sec)
【写锁,排他锁】
mysql> lock tables classes write;
Query OK, 0 rows affected (0.00 sec)
【终端2 mysql不可读不可写】
mysql> select * from classes;
【释放锁】
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
【终端2 返回数据】
mysql> 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 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
10 rows in set (1 min 29.86 sec)
【存储引擎锁】
InnoDB存储引擎也支持另外一种显式锁(锁定挑选出的部分行,行级锁 ):
SELECT ... LOCK IN SHARE MODE;
SELECT ... FOR UPDATE;
mysql> select * from classes where ClassID <=3 lock in share mode;
+---------+---------------+----------+
| ClassID | Class | NumOfStu |
+---------+---------------+----------+
| 1 | Shaolin Pai | 10 |
| 2 | Emei Pai | 7 |
| 3 | QingCheng Pai | 11 |
+---------+---------------+----------+
3 rows in set (0.02 sec)
【查看表状态,看看存储引擎】
mysql> show table status \G
mysql> show table status like 'classes' \G
*************************** 1. row ***************************
Name: classes
Engine: MyISAM
Version: 10
Row_format: Dynamic
Rows: 10
Avg_row_length: 21
Data_length: 212
Max_data_length: 281474976710655
Index_length: 2048
Data_free: 0
Auto_increment: 11
Create_time: 2015-09-10 08:36:37
Update_time: 2015-09-10 16:52:54
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.03 sec)
【修改表存储引擎】表很大时,不建议
mysql> alter table classes engine 'InnoDB';
Query OK, 10 rows affected (0.22 sec)
Records: 10 Duplicates: 0 Warnings: 0
【看看修改后】
mysql> show table status like 'classes' \G
*************************** 1. row ***************************
Name: classes
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 10
Avg_row_length: 1638
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 9437184
Auto_increment: 11
Create_time: 2015-09-10 17:11:26
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
【自动锁】
【for update 执行过程被锁,执行完毕就释放,所以不好捕捉这个锁的效果,除非表非常大非常大】
mysql> select * from classes where ClassID <=3 for update;
+---------+---------------+----------+
| ClassID | Class | NumOfStu |
+---------+---------------+----------+
| 1 | Shaolin Pai | 10 |
| 2 | Emei Pai | 7 |
| 3 | QingCheng Pai | 11 |
+---------+---------------+----------+
3 rows in set (0.00 sec)
【事务:Transaction】
【事务:Transaction】
事务就是一组原子性的查询语句,也即将多个查询当作一个独立的工作单元。
ACID测试:能满足ACID测试就表示其支持事务,或兼容事务。
A:Atomicity,原子性
C:Consistency, 一致性
I: Isolation, 隔离性, 一个事务的所有修改操作在提交之前对其它事务是不可见的
Tom: 7000-3000
Jerry: 5000+3000
D:Durability, 持久性, 一旦事务得到提交,其所做的修改会永久有效
隔离级别:
READ UNCOMMITTED (读未提交)
脏读,不可重读,幻读
READ COMMITTED (读提交)
不可重读,幻读
REPEATABLE READ (可重读)
幻读
SERIALIZABLE (可串行化)
强制事务的串行执行避免了幻读;性能极低
跟事务相关的常用命令 myISMA不支持事务
mysql> help transactions
mysql> START TRANSACTION
mysql> COMMIT
mysql> ROLLBACK 回滚
mysql> SAVEPOINT identifier 回滚到指定的点
mysql> ROLLBACK [WORK] TO [SAVEPOINT] identifier
【事务回滚演示】
mysql> show table status like 'classes' \G
*************************** 1. row ***************************
Name: classes
Engine: MyISAM
MyISAM 是不支持事务的
【修改表的存储引擎】
mysql> alter table classes engine 'InnoDB';
Query OK, 9 rows affected (0.01 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> show table status like 'classes' \G
*************************** 1. row ***************************
Name: classes
Engine: InnoDB
【查看打开的数据库】
mysql> select database();
+------------+
| database() |
+------------+
| hellodb |
+------------+
【开启事务】:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
【查看表】
mysql> 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 |
| 7 | Ming Jiao | 27 |
| 8 | Xiaoyao Pai | 15 |
| 9 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
【插入数据】
mysql> insert into classes values (6,'Lianshan Pai',27);
【回滚】
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
【查看未提交的事务】
mysql> 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 |
| 7 | Ming Jiao | 27 |
| 8 | Xiaoyao Pai | 15 |
| 9 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
9 rows in set (0.00 sec)
【提交事务 演示】commit
mysql> 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 |
| 7 | Ming Jiao | 27 |
| 8 | Xiaoyao Pai | 15 |
| 9 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
9 rows in set (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into classes values (6,'Lianshan Pai',27);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> 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 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
10 rows in set (0.03 sec)
【总结】事务提交前的所有都可以回滚
【回滚到指定点 演示】
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> 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 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
10 rows in set (0.00 sec)
mysql> delete from classes where ClassID=1;
Query OK, 1 row affected (0.00 sec)
mysql> savepoint a;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from classes where ClassID=4;
Query OK, 1 row affected (0.00 sec)
mysql> savepoint b;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from classes where ClassID=9;
Query OK, 1 row affected (0.00 sec)
mysql> select * from classes;
+---------+----------------+----------+
| ClassID | Class | NumOfStu |
+---------+----------------+----------+
| 2 | Emei Pai | 7 |
| 3 | QingCheng Pai | 11 |
| 5 | Riyue Shenjiao | 31 |
| 6 | Lianshan Pai | 27 |
| 7 | Ming Jiao | 27 |
| 8 | Xiaoyao Pai | 15 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
7 rows in set (0.00 sec)
【回滚到 b 记录到现在的状态,b之前的不会回来】
mysql> rollback to b;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from classes;
+---------+----------------+----------+
| ClassID | Class | NumOfStu |
+---------+----------------+----------+
| 2 | Emei Pai | 7 |
| 3 | QingCheng Pai | 11 |
| 5 | Riyue Shenjiao | 31 |
| 6 | Lianshan Pai | 27 |
| 7 | Ming Jiao | 27 |
| 8 | Xiaoyao Pai | 15 |
| 9 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
8 rows in set (0.00 sec)
【全部滚回来】
mysql> 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 | Liangshan | 22 |
| 10 | TaoYuan | 23 |
+---------+----------------+----------+
10 rows in set (0.00 sec)
【查看commit的全局设置】 默认ON
mysql> show global variables like '%commit%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| autocommit | ON |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
3 rows in set (0.00 sec)
mysql> select @@global.autocommit ;
+---------------------+
| @@global.autocommit |
+---------------------+
| 1 |
+---------------------+
1 row in set (0.00 sec
【关闭 autocommit,减少IO操作, 提高mysql性能,仅对新的事务有影响】
那么就只能手动启动事务,手动提交!否则数据丢失。
mysql> set global autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.autocommit ;
+---------------------+
| @@global.autocommit |
+---------------------+
| 0 |
+---------------------+
1 row in set (0.00 sec)
如果没有显式启动事务,每个语句都会当作一个独立的事务,其执行完成后会被自动提交;
mysql> SELECT @@global.autocommit;
mysql> SET GLOBAL autocommit = 0;
关闭自动提交,请记得手动启动事务,手动进行提交;
【MySQL的事务隔离级别】
【MySQL的事务隔离级别】
【MySQL的事务隔离级别】
mysql> SHOW GLOBAL VARIABLES LIKE 'tx_isolation';
mysql> SELECT @@global.tx_isolation;
设置事务隔离:SET GLOBAL.tx_isolation='READ-UNCOMMITED';
建议:对事务要求不特别严格的场景下,可以使用读提交;
【永久生效需要修改配置文件】
READ-UNCOMMITED
脏读也会幻读 即使别人没有commit,也能读到别人修改了的数据,同样的查看结果不一致。
READ-COMMITED
不可重读,别人提交了,数据就会读的不一样。【推荐】
REPEATABLE-READ 【mysql 默认的设置】
幻读,两终端同时mysql> start transaction; 终端1 删除一行未提交,终端2看到删除前的数据。 即使终端1 删除数据并且也提交了,终端2依然可以读到删除前的数据。【如果终端2 没有做任何修改,commit,再次查看就是终端1修改后的数据了】
SERIALIZABLE 可串行化,效率太低
两终端同时mysql> start transaction;终端1 修改数据未提交,终端2 select查看就会被阻塞,等待终端1提交或者回滚,才可以执行被阻塞的操作。
MVCC:多版本并发控制
每个事务启动时,InnoDB为会每个启动的事务提供一个当下时刻的快照;
为了实现此功能,InnoDB会为每个表提供两隐藏的字段,一个用于保存行的创建时间,一个用于保存行的失效时间;
里面存储的是系统版本号;(system version number)
只在两个隔离级别下有效:READ COMMITTED和REPEATABLE READ
转载于:https://blog.51cto.com/990487026/1693633