即:
即 快照读 的问题在于:在同一个事务中,能够读取到之前提交的数据。表现为:
字面意思:在事务中,为查询创建的快照,并不适用与 DML 语句。
也就是说:如果事务 A 开始时创建的快照,查询不到数据 col1=1 ,但此时事务 B 刚刚提交 insert col1=1 和 insert col1=1 ,此时如果事务 A 执行, delete col1=1 ,是能将事务 B 生成的数据删除的。
字面意思:即使事务 A 的快照是在事务 B 提交之前创建的,但事务 A 也只有在事务 A 和事务 B 都提交后,才能看到事务 B 新增的数据。
首先我们做一个模拟,执行以下的sql,其中有如下图数据:
我把执行结果按照表格如下展示:
分析:
在会话1当中,只有当会话1的事务提交后,才能查到最终会话2更改的数据。
在会话2当中,开启事务后更新数据,之后查询发现数据变成了17。
针对上面的现象我们进行个原理分析:
实际上产生上述显现是因为InnoDB采用的MVCC(多版本并发控制),其中针对每条数据会有它自己的事务id,以及一个最大事务id。针对事务中数据每次修改,会产生不同的版本。
1)假设开始id = 2的数据,其事务txid = 1000;
2)当会话1开始,此时txid变成了1001,而会话2开启,txid又变成了1002,同理会话3会变成1003,此时都生成了不同版本的快照。
3)会话1在事务当中去读取时候,采用了快照读的方式,即拿到一个1001的事务id,此时只会读取小于等于自己版本的数据,所以在事务中最终只能拿到值为17的数据。
4)会话2在更新数据的时候,采用的当前读的方式,即对数据增加X锁,获取最新的事务id,读取最新的版本数据。所以在更新之前,就读取到了age的年龄是16,之后在进行+1,得到17.
总结一下:
快照读 解决了幻读的问题,即多次读取数据不一致的问题。
update、insert、delete都会执行 当前读 ,防止并发更新数据导致数据错误,此过程或添加X锁。
新建一个lvm磁盘,这里我建的lv为mydatalv,挂载到了/data下[root@localhost
~]#
lvs
LV
VG
Attr
LSize
Pool
Origin
Data%
Meta%
Move
Log
Cpy%Sync
Convert
mydatalv
mydata
-wi-ao----
1.00g
[root@localhost
~]#
df
-h
文件系统
容量
已用
可用
已用%
挂载点
/dev/mapper/mydata-mydatalv
976M
2.6M
907M
1%
/data
将原数据库文件复制到/data目录下
[root@localhost
~]#
cp
-a
/var/lib/mysql
/data/
修改配置文件,将mysql数据库文件放在lvm盘中,二进制文件放在非lvm盘的/var/lib/mysql/目录下
[root@ns1
~]#
vim
/etc/my.cnf
[mysqld]
log_bin=/var/lib/mysql/mysql-bin
datadir=/data/mysql
[root@localhost
~]#
service
mariadb
restart
[root@localhost
~]#
ls
/data/mysql
aria_log.00000001
ibdata1
ib_logfile1
mysql-bin.000001
mysql-bin.000003
performance_schema
aria_log_control
ib_logfile0
mysql
mysql-bin.000002
mysql-bin.index
test
可以看到重启后数据库文件已存放在了/data/mysql目录中了
对mysql进行锁表备份
[root@localhost
~]#
mysql
-e
'flush
tables
with
read
lock'
锁表
[root@localhost
~]#
mysql
-e
'flush
logs'
对日志进行滚动,
[root@localhost
~]#
mysql
-e
'show
master
status'
>
/root/back.$(date
+%F+%T)
[root@localhost
~]#
ls
back.2016-07-13+10:14:29
对lv创建快照
[root@localhost
~]#
lvcreate
-L
1G
-n
mysqlback
-p
r
-s
/dev/mydata/mydatalv
释放锁
[root@localhost
~]#
mysql
-e
'unlock
tables'
在别的磁盘上创建备份目录,只读挂载快照后备份至备份目录
[root@localhost
~]#
mkdir
/myback
[root@localhost
~]#
mount
-r
/dev/mydata/mysqlback
/mnt
[root@localhost
~]#
cp
-a
/mnt/mysql
/myback
修改表内容,然后删除掉数据库文件内容即/data/mysql中的内容
[root@localhost
~]#
mysql
MariaDB
[hellodb]>
use
hellodb
MariaDB
[hellodb]>
insert
into
classes
(class,numofstu)
values
('xxoo',39)
[root@localhost
~]#
rm
-rf
/data/*
修改配置文件中二进制日志和数据库文件的位置
[root@localhost
~]#
vim
/etc/my.cnf
[mysqld]
log_bin=/data/mysql/mysql-bin
datadir=/data/mysql
利用/myback/中的内容还原
[root@localhost
~]#
cp
-a
/myback/*
/data/
[root@localhost
~]#
service
mariadb
restart
利用二进制日志还原快照后的 *** 作,由下面这个文件来查看快照执行时二进制日志的位置
[root@localhost
~]#
cat
back.2016-07-13+10\:14\:29
File
Position
Binlog_Do_DB
Binlog_Ignore_DB
mysql-bin.000014
245
将000014中245之后的 *** 作做成sql文件,进行还原
[root@localhost
~]#
mysqlbinlog
--start-position=245
/var/lib/mysql/mysql-bin.000014
>
binlog.sql
[root@localhost
~]#
mysql
<
/root/binlog.sql
查看恢复情况
[root@localhost
~]#
mysql
MariaDB
[(none)]>
use
hellodb
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
|
xxoo
|
39
|
+---------+----------------+----------+
9
rows
in
set
(0.00
sec)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)