mysql的存储引擎-事务-锁

第一层:
mysql 服务支持接口,也就是数据库访问技术,标准C的API,JDBC ,ODBC,NET,PHP,Python,等等
第二层:
mysql启动连接池,默认的连接池是150个,具体多少取决于上层web服务开多少连接。

第三层:
mysqlSQL接口,数据库管理语言,数据库定义语言,视图,触发器等等,接收工作台输入的SQL语句命令。

解析器,就是解析SQL语句的,查询,事务功能。

优化器,访问路径,统计,优化SQL语句。

缓存和缓冲池,全局和引擎的缓存和缓冲池相连。加快搜索速度。

第四层:

存储引擎。InnoDB MyISAM,Falcon,Archive 等等。

第五层:

存储引擎下层是硬盘,文件系统,日志等等

存储引擎:
调用在文件系统上的数据,然后用sql进行操作。存储引擎将内存中的操作结果等,存入硬盘。

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

看到所有的存储引擎
DEFAULT 当前mysql默认使用的存储引擎
YES 当前mysql可以使用这种存储引擎
NO 当前mysql无法使用

mysql 5.5.08 以前,默认的存储引擎是 MyISAM。以后,默认的存储引擎是 InnoDB。

MyISAM:
	适用于读频率远远大于写频率的应用场景。
	查询的效率相当高,而且占用内存很小。

	表的保存方式:
		.frm 表的框架
		.MYD 表的数据
		.MYI 表的索引

	缺点:
		不支持事务操作
		也不支持外键
InnoDB:
	为了处理巨大的数据量,如果表的数据量很大,选择使用innodb。

	提供了良好的事务处理,针对数据崩溃有很好的修复机制

	缺点:读写的效率差。
		
	表的存储方式:
		innodb存储引擎使用表空间存储数据。

		独立表空间:每个表都有自己的表空间文件
			.frm 表的框架结构
			.ibd 表的独立表空间文件
		共享表空间:所有的表共享使用同一个表空间文件
			.frm 表的框架结构
			ibdata1 所有表的共享表空间文件
			
表空间:是数据库里最大的逻辑单位,保存表数据
	一个表空间可以包含一个或多个数据文件
	一个数据文件只能属于一个表空间

切换独立表空间和共享表空间

mysql> show variables like "%per_table%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.01 sec)

mysql> set global innodb_file_per_table=0;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "%per_table%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | OFF   |
+-----------------------+-------+
1 row in set (0.01 sec)

这时创建的表就没有.ibd,独立表空间文件
在这里插入图片描述

因为整个数据库的数据都存储在ibdatal文件,共享表空间文件中了。

**注意:**默认为独立表空间文件,改为共享表空间文件后,已经创建的表不会改变,新创建的表才会没有ibd文件,存到ibdatal文件中。如果这时切换回独立表空间模式,已经是共享创建的也不会变回独立表空间。

当然,在这里改的话并不会永久生效,退出连接,再重新连接,就没有了,想要永久生效的话要填写配置文件。

[mysqld]
innodb-file-per-table=[01]
	0	共享
	1	独立,默认的
重启服务生效

memory
也叫:内存存储引擎
速度快。
缺点:
服务一重启,或虚拟机重启。
数据全部丢失。

mysql> use gsc1
mysql> create table t999(id int ,name char(10))engine=memory;
mysql> show tables;
+----------------+
| Tables_in_gsc1 |
+----------------+
| passwd         |
| shop           |
| t1             |
| t999           |
+----------------+
mysql> insert into t999 values (111,"name1");
mysql> select * from t999;
+------+-------+
| id   | name  |
+------+-------+
|  111 | name1 |
+------+-------+
mysql> exit
Bye

[root@localhost scripts]# netstat -antlup | grep mysql
tcp6       0      0 :::3306                 :::*                    LISTEN      6927/mysqld         
[root@localhost scripts]# kill 6927
[root@localhost scripts]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

mysql> use gsc1;
mysql> show tables;
+----------------+
| Tables_in_gsc1 |
+----------------+
| passwd         |
| shop           |
| t1             |
| t999           |
+----------------+
mysql> select * from t999;
Empty set (0.00 sec)
//重启服务数据丢失。

事务:
事务就是做的操作,哪怕做了1000个操作完成一件事,都叫一个事务。

特性:
A:atomic:原子性;对数据的修改,要么执行,要么不执行
C:consistency:一致性;事务在开始和结束时,数据必须保证是一致的状态
I:isolation:隔离性;事务的操作不允许外界干扰
D:duration:持久性;事务要一直执行到最后

不过默认情况下,事务是自动提交的,所以我们输入命令后即时生效,并且不能回滚。

mysql> select * from t8;
+------+-------+
| id   | name  |
+------+-------+
|  111 | kaili |
|  112 | kitty |
+------+-------+
2 rows in set (0.00 sec)

mysql> delete from t8 where id=111;
Query OK, 1 row affected (0.02 sec)

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

mysql> select * from t8;
+------+-------+
| id   | name  |
+------+-------+
|  112 | kitty |
+------+-------+
1 row in set (0.00 sec)

回滚也不生效。

可以手动关闭自动提交来进行测试。

mysql> set autocommit=off;
//关闭自动提交,变为手动提交

在这里插入图片描述
关闭自动提交后需要手动提交才会生效,否则就只在当前shell生效。

比如上图,添加了一条数据,当前端口也能够看到,但是另一个端口就不能看到了。

提交后再查就能看到了。commit提交。

在这里插入图片描述

事务的回滚,rollback;

在这里插入图片描述
另外有一些刺头非常的牛X,他们不受事务操作的约束。就是DDL语句。
这些不管事务提没提交或者怎么样,都直接生效。

DDL语句
	create
	drop
	alter
	truncate

在这里插入图片描述
右边的端口删除表,没提交,左边的也没有了。。

另外,我们并不是这么用事务的,常用的是spring的事务机制,在开发的过程中,总会遇到bug或者报错,但是报错之前,确是能正常执行的。

public method() {
    Dao1.save(People1);
    Dao1.save(People2);
    Dao1.save(People3);//这里
    Dao1.save(People4);
}

这里调用的是存储方法,向数据库里写数据。
假如Dao1.save(People3);执行报错,但是前边的都正常,造成的结果就是,前两条添加了,第三第四不添加,但是我们想要的逻辑确是这几条都不添加。

就拿银行取钱举例,账户扣钱正常,ATM出钱报错不执行,你是希望账户扣钱,还是不扣钱??当然是不扣钱。

这时我们可以用spring的事务回滚机制来解决这个问题。

用@ Transaction 注解在对应方法上声明为一个事务方法。
这个在这里就不讨论了。

锁:
锁就是再多并发的情况下保证数据库的数据安全和完整的机制。让访问数据库的接口有序的进行操作。

按照粒度分类:

表级锁:

直接锁定整个表,在上锁以后,其他用户操作该表会受限。
锁定的粒度大,发生冲突的概率比较高,并发性差。

行级锁:

只锁定操作的那行,表中的其他行不受影响。
锁定的粒度小,几乎不会产生冲突,并发性高。
有可能出现死锁。
mysql5.7以后,会自动解开死锁。

这个是原始数据。

mysql> select * from t1;
+------+--------+
| id   | name   |
+------+--------+
|    1 | name11 |
|    1 | name22 |
+------+--------+
2 rows in set (0.00 sec)

在这里插入图片描述

在上图可以看到,开了两个终端,都关闭了自动提交,左边的 终端修改了,name11这个数据,没有提交。 右边的终端再修改这个name11,这时发现进行不下去,会卡住。证明锁生效了。

到一定时间或者左边的终端提交了。
右边的终端就会结束,并报错,此时没有做修改。

mysql> update t1 set name="name11aaaa" where name="name11";
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
//提交之后。
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+----------+
| id   | name     |
+------+----------+
|    1 | name11aa |
|    1 | name22   |
+------+----------+
2 rows in set (0.00 sec)
//看到修改的数据。

死锁:

终端1:
mysql> update t2 set b="niu111" where name="name11aa";

终端2:
mysql> update t2 set b="niu22" where name="name22";

终端1:
mysql> update t2 set b="niu222" where name="name22";

终端2:
mysql> update t2 set b="niu123" where name="name11aa";
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
	自动解开死锁

这个失策 了,id应该设成主键的,那样就不用写这些乱七八糟的name了。QAQ

按类型分:

读锁(共享锁):
当上了读锁时任何人不能进行写操作。
在做备份时会使用读锁。

写锁(排它锁):
当给表加写锁后,只有自己可以对表进行读写,其他用户没有任何权限。

mysql> lock table t2 read;
Query OK, 0 rows affected (0.02 sec)

mysql> select * from t2;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> insert into t2 values (3);
ERROR 1099 (HY000): Table 't2' was locked with a READ lock and can't be updated

mysql> insert into t1 values (12,"name33");

ERROR 1100 (HY000): Table 't1' was not locked with LOCK TABLES


mysql> unlock tables;
//解锁

如果某个终端使用lock table tname read / write锁定某个表。

那么同一个终端中只能对锁定的表进行查询操作,不能对锁定的表进行修改、插入、删除,不允许对没有锁定的表进行查询、修改、插入、删除。

其他终端对锁定的表只能查询,不能进行修改,插入,删除操作。

其他终端对没有锁定的表仍然可以进行查询、修改、插入、delete操作。

mysql> lock table t3 write;
	给表加写锁

mysql> insert into t3 values(3);
mysql> select * from t3;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+

其他用户:
mysql> select * from t3;
mysql> insert into t3 values(4);
	被阻塞

查看表的上锁情况:

mysql> show open tables where in_use>0;
+----------+-------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+-------+--------+-------------+
| db400    | t1    |      1 |           0 |
+----------+-------+--------+-------------+
1 row in set (0.01 sec)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值