关于MySql的事务隔离原理

学习了林晓斌<<MySQL45讲>>中关于事务的文章后, 把一些点总结一下, 便于之后记忆:

Mysql在事务开始时,会创建一个”一致性读视图”. 它没有物理结构,作用是事务执行期间用来定义”我能看到什么数据”.

  1. 每个事务有全局唯一的ID, 并且向上递增(由MySQL的事务系统控制).

2. 表的每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。也就是说,数据表中的一行记录,其实可能有多个版本 (row),每个版本有自己的 row trx_id。

3. InnoDB 为每个事务构造了一个数组, 用来保存这个事务启动瞬间,当前正在“活跃”的所有事务 ID。“活跃”指的就是,启动了但还没提交。

这样在事务内的数据可见性, 就转化为: 当前事务构造的事务ID数组和行数据对应的row trx_id之间的映射关系. 一个数据版本,对于一个事务视图来说,除了当前事务的更新总是可见以外,有三种情况:

未提交,不可见;

已提交,但是是在视图创建后提交的,不可见;

已提交,而且是在视图创建前提交的,可见。

另外附加一个原则: 所有更新数据都是先读后写的,而这个读,只能读当前的值(即实时被更新的值),称为“当前读”(current read)。

同时, 更新数据前都会加排它锁, 所以如果前一个更新未提交, 当前更新就一直处于等待状态.

CentOS 安装 mongodb

转:https://www.cnblogs.com/saryli/p/9822819.html

1、下载安装包

curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.12.tgz

2、解压

tar -zxvf mongodb-linux-x86_64-4.0.12.tgz

3、移动到指定位置

mv mongodb-linux-x86_64-4.2.12/ /usr/local/mongodb

4、在/usr/local/mongodb下创建文件夹

mkdir -p /data/dbmkdir /logs

5、在/usr/local/mongodb/bin下新建配置

vi mongodb.conf
#数据文件存放目录
dbpath = /usr/local/mongodb/data/db 
#日志文件存放目录
logpath = /usr/local/mongodb/logs/mongodb.log
#端口
port = 27017
#以守护程序的方式启用,即在后台运行
fork = true
#http访问控制(centos下会此项设置无效:注释掉这个配置或者下载企业评估版)
nohttpinterface = true
auth= true
bind_ip=0.0.0.0

6、环境变量配置

vi /etc/profile
export MONGODB_HOME=/usr/local/mongodb export PATH=$PATH:$MONGODB_HOME/bin

保存后,重启系统配置

source /etc/profile

7、启动
在/usr/local/mongodb/bin下

3mongod -f mongodb.conf 
或
./mongod -f mongodb.conf

8、关闭

#进入控制台
# mongo
> use admin
> db.shutdownServer()
# 命令行
mongod --shutdown
或
./mongod --shutdown

9、开启端口

firewall-cmd --zone=public --add-port=27017/tcp --permanent

查看端口

firewall-cmd --permanent --query-port=27017/tcp

重启防火墙

firewall-cmd --reload

10、创建用户

进入客户端

./mongo

创建用户管理员:

#使用admin数据库
use admin
#创建用户,并分配权限
db.createUser({user:"root",pwd:"root123456",roles:["userAdminAnyDatabase"]})
#给root添加system表的权限
db.grantRolesToUser("root",[{role:"__system",db:"admin"}])
#验证并切换到root用户
db.auth('root','root123456')

以用户管理员身份登录,并切换数据库,创建数据库用户:
切换到test数据库

use test

创建用户名、密码、角色

db.createUser({user:"username",pwd:"@user123456*",roles:[{role:"readWrite",db:"securitydata"}]})

设置mongodb配置中的auth为true(/etc/mongod.conf):

security:authorization: enabled

验证mongodb数据库权限。

db.auth('user','@user123456*')

查看所有用户信息

db.system.users.find()

删除用户

use admin
#验证并切换到root用户
db.auth('root','root123456')
db.system.users.remove({user:"haha"})
db.system.users.find()

11. 非正常关闭修复

# no any other options,不保存损坏数据
$ mongod --repair
# 数据文件路径下包含修复的文件和一个空的mongo.lock文件
$ mongod --dbpath /data/db --repair
# 使用MMAPv1存储引擎还可以指定 --repairpath作为临时的

官方修复文档

mysql 忘记密码的处理方法

【说明】MySQL5.7忘记root密码的时候,处理方式跟之前的版本有些不一样,这边整理如下:

【1】修改参数文件跳过密码验证
vim /etc/my.cnf
# 在 [mysqld] 中加上一行跳过权限限制
skip-grant-tables
# 保存退出 重启mysql服务
service mysqld restart

【2】修改密码字段

# 用户登录
mysql -uroot -p (直接点击回车,密码为空)
update mysql.user set authentication_string=password(‘123456′) where user=’root’;
# 刷新权限
flush privileges;
# 但是在5.7版本中不存在password字段,所有我们要用以下修改进行重置密码

【3】最开始修改的配置文件my.cnf中的skip-grant-tables删除 重启mysql
service mysqld restart

【4】 当你登陆mysql之后你会发现,当你执行命令时会出现
ERROR 1820 (HY000): You must reset your password using ALTER USER statement;
# 这是提示你需要修改密码 当你执行了
SET PASSWORD = PASSWORD(‘root’);
# 如果出现
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
# 你需要执行两个参数来把mysql默认的密码强度的取消了才行 当然也可以把你的密码复杂度提高也行啊
set global validate_password_policy=0;
set global validate_password_mixed_case_count=2;

【5】经过以上操作,便完成了密码的变更;

常用SQL

1. 行列转换--普通

假设有张学生成绩表(CJ)如下
Name Subject Result
张三 语文 80
张三 数学 90
张三 物理 85
李四 语文 85
李四 数学 92
李四 物理 82

想变成
姓名 语文 数学 物理
张三 80 90 85
李四 85 92 82

declare @sql varchar(4000)
set @sql = 'select Name'
select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result end) ['+Subject+']'
from (select distinct Subject from CJ) as a
select @sql = @sql+' from test group by name'
exec(@sql)

2. 行列转换--合并

有表A,
id pid
1 1
1 2
1 3
2 1
2 2
3 1
如何化成表B:
id pid
1 1,2,3
2 1,2
3 1

创建一个合并的函数
create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''
select @str=@str+','+cast(pid as varchar) from 表A where id=@id set @str=right(@str,len(@str)-1)
return(@str)
End
go

--调用自定义函数得到结果
select distinct id,dbo.fmerg(id) from 表A

3. 如何取得一个数据表的所有列名

方法如下:先从SYSTEMOBJECT系统表中取得数据表的SYSTEMID,然后再SYSCOLUMN表中取得该数据表的所有列名。
SQL语句如下:
declare @objid int,@objname char(40)
set @objname = 'tablename'
select @objid = id from sysobjects where id = object_id(@objname)
select 'Column_name' = name from syscolumns where id = @objid order by colid

是不是太简单了? 呵呵 不过经常用阿.

4. 通过SQL语句来更改用户的密码

修改别人的,需要sysadmin role
EXEC sp_password NULL, 'newpassword', 'User'

如果帐号为SA执行EXEC sp_password NULL, 'newpassword', sa

5. 怎么判断出一个表的哪些字段不允许为空?

select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where IS_NULLABLE='NO' and TABLE_NAME=tablename

6. 如何在数据库里找到含有相同字段的表?
a. 查已知列名的情况
SELECT b.name as TableName,a.name as columnname
From syscolumns a INNER JOIN sysobjects b
ON a.id=b.id
AND b.type='U'
AND a.name='你的字段名字'

b. 未知列名查所有在不同表出现过的列名
Select o.name As tablename,s1.name As columnname
From syscolumns s1, sysobjects o
Where s1.id = o.id
And o.type = 'U'
And Exists (
Select 1 From syscolumns s2
Where s1.name = s2.name
And s1.id <> s2.id
)

7. 查询第xxx行数据

假设id是主键:
select *
from (select top xxx * from yourtable) aa
where not exists(select 1 from (select top xxx-1 * from yourtable) bb where aa.id=bb.id)

如果使用游标也是可以的
fetch absolute [number] from [cursor_name]
行数为绝对行数

8. SQL Server日期计算
a. 一个月的第一天
SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
b. 本周的星期一
SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)
c. 一年的第一天
SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)
d. 季度的第一天
SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)
e. 上个月的最后一天
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))
f. 去年的最后一天
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
g. 本月的最后一天
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))
h. 本月的第一个星期一
select DATEADD(wk, DATEDIFF(wk,0,
dateadd(dd,6-datepart(day,getdate()),getdate())
), 0)
i. 本年的最后一天
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。
9.获取行号
mysql:
SELECT @rowno:=@rowno + 1 AS rowno,a.* FROM tableName a,(SELECT @rowno:=0) b
oracle:
SELECT rownum,a.* FROM tableName a

感谢那些网上提供相关SQL的作者