首页 > 修改教程 > 用gg修改器游戏崩溃_游戏崩溃了gg修改器
用gg修改器游戏崩溃_游戏崩溃了gg修改器
  • gg修改器最新版
  • 大小:19.64MB版本:v5.99
  • 语言:简体中文系统:Android
绿色无毒,安全可靠!部分设备误报拦截请通过!

用gg修改器游戏崩溃_游戏崩溃了gg修改器

作者:佚名 来源:网友分享 日期:2024-04-26 09:02:00

大家好,今天小编为大家分享关于用gg修改器游戏崩溃_游戏崩溃了gg修改器的内容,赶快来一起来看看吧。

mysql 第1章

1、引入

2、还原mysql 面貌

2.1mysql 逻辑架构

mysql 的系统架构的分层:

第一层是大多数基于网络的客户端/服务器的工具或者服务都有的架构,用于处理网络请求的,连接处理,授权认证,安全等。

第二层是mysql的核心服务功能,包括查询解析、分析、优化、缓存以及所有的内置函数,所有跨存储引擎的功能都在这一层实现。

第三层包含了存储引擎,存储引擎负责了msyql 中的数据存储和提取。服务器通过API与存储引擎进行通信,存储引擎API包含了几十个底层函数,用于执行诸如开始一个事务。

3、mysql事务

例如:银行转账,A给B转账,A账号余额减少,B账号余额增多。这两个操作一定是同时成功或者同时失败。

我们有很多的业务都具有类似的特性,例如各种交易系统,电商系统,下单、库存、减余额,以及我们所有涉及多表操作的都需要事务管理。

事务有哪些特性?

3.1原子性

3.2一致性

3.3隔离性

时间

事务A

事务B

T1

开始事务

开始事务

T2

将B的money从1000修改为2000

T3

读取B的money,读到了2000

T4

提交事务

事务B读到了为提交的数据

时间

事务A

事务B

T1

开始事务

开始事务

T2

查询B的money,得到B的余额为1000

T3

修改B的money为2000

T4

提交事务

T5

查询B的money,得到B的余额为2000

事务A在同一个事务内读取同一条数据,由于其他事务提交了对改数据的修改,导致事务A获得了不同的结果,对于这种可称为不可重复读

时间

事务A

事务B

T1

开始事务

开始事务

T2

查询账户表里面所有money >= 1000 的数据

T3

插入一条新数据,该账户的money 2000

T4

提交事务

T5

更新账户表的所有账户,将大于1000的money全部更新为1000

T6

查询账户表里面所有money >= 1000 的数据

READ UNCOMMITTED(读未提交)
READ COMMITTED (读提交)
REPEATABLE READ (可重复读)
SERIALIZABEL (串行化)

隔离级别

脏读的可能性

不可重复读可能性

幻读可能性

加读锁

READ UNCOMMITTED

YES

YES

YES

NO

READ COMMITTED

NO

YES

YES

NO

REPEATABLE READ

NO

NO

YES

NO

SERALIZABLE

NO

NO

NO

NO

//关闭事务自动提交
set @@mit=0;

//查看当前会话隔离级别
select @@tx_isolation;

//查看系统当前隔离级别
select @@global.tx_isolation;

//设置当前会话隔离级别
set session transaction isolation level 隔离级别

//设置系统隔离级别
set global transaction isolation level 隔离级别

时间

事务A

事务B

T1

开始事务

开始事务

T2

查询user_t 表中userId > 2 (select * from use_t where userId > 2)

T3

insert into use_t(userId,userName)values(“5″,”张三”);

T4

T5

更新userId > 2 部分的数据 update use_t set college_id = “03” where useId = “2”;

T6

查询user_t 表中userId > 2 (select * from use_t where userId > 2)

不会发生幻读

时间

事务A

事务B

T1

开始事务

开始事务

T2

查询user_t 表中userId > 2 (select * from use_t where userId > 2)

T3

insert into use_t(userId,userName)values(“5″,”张三”);

T4

T5

更新userId > 2 部分的数据 update use_t set college_id = “03” where useId > 2;

T6

查询user_t 表中userId > 2 (select * from use_t where userId > 2)

会发生幻读

锁住的是索引,当where条件没有索引时,会使用表锁,将整张表锁住。

for {
user_t = select * from user_t where userId = "1"
version = user_t.Version + 1 update set college_id = "04",version = version + 1 where version = user_t.Version and id = user_t.Id
if ok { break }
}

lock tables user_t write;
update user_t set userName = "张三" where userId = "21";
unlock tables;

lock tables user_t read;
update user_t set userName = "t" where userId = "1"; -- ERROR 1099 (HY000): Table ’user_t’ was locked with a READ lock and can’t be updated
unlock tables;

3.4 持久性

4、尝试使用事务

4.1事务示例

-- 开启事务
begin;
-- 操作。。。
-- insert update delete
-- 回滚或提交
rollback;
mit;

-- 建表
CREATE TABLE `account` (
`id` bigint(20) NOT NULL COMMENT ’主键’,
`account` varchar(64) NOT NULL COMMENT ’账号’,
`money` bigint(255) DEFAULT NULL COMMENT ’余额’,
`create_time` datetime DEFAULT NULL COMMENT ’创建时间’,
`update_time` datetime DEFAULT NULL COMMENT ’更新时间’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

// A->B 转账
//开启
tx := Db.Begin()
where := map[string]interface{}{"account":"A"}
account,err := Query(tx,where)
if err != nil || account.Money < 800 {
//回滚
tx.Rollback()
return
}
err = tx.Debug().Table("account").Where("account","A").Update("money",gorm.Expr("money - ?",800)).Error
if err != nil {
//回滚
tx.Rollback()
}
err = tx.Debug().Table("account").Where("account","B").Update("money",gorm.Expr("money + ?",800)).Error
if err != nil {
//回滚
tx.Rollback()
}
//提交
tx.Commit()

假设有多个人需要给同一个用户转账,并且采用的方式是先查的这个人的余额,然后更新。此时会有什么问题?

例如我们业务中的名单,value值更新。

并发操作一行,正常来说只更新一行会给该行加行级锁,但是需要where 语句有索引。

//方式1 不做任何处理
for i := 0;i < 100; i++ {
go func() {
acc := model.Account{}
Db.Debug().Table("account").Where("account","B").Find(&acc)
money := acc.Money + 800
Db.Debug().Table("account").Where("account","B").Update("money",money)
}()
}
//方式2 事务
for i := 0;i < 100; i++ {
go func() {
tx := Db.Begin()
acc := model.Account{}
tx.Debug().Table("account").Where("account","B").Find(&acc)
money := acc.Money + 800
tx.Debug().Table("account").Where("account","B").Update("money",money)
tx.Commit()
}()
}
//方式3 数据库加锁select for update
for i := 0;i < 100; i++ {
go func() {
//select for update
tx := Db.Begin()
var acc model.Account
if err := tx.Debug().Select("money").Set("gorm:query_option", "FOR UPDATE").First(&acc, 2).Error;err != nil {
tx.Rollback()
}
money := acc.Money + 800
err := tx.Debug().Table("account").Where(map[string]interface{}{"account":"B"}).Update("money",money).Error
if err != nil {
tx.Rollback()
}
if err := tx.Commit().Error;err != nil {
tx.Rollback()
}
}()
}
//方式4 程序加锁
var muLock sync.Mutex
for i := 0;i < 100; i++ {
go func() {
muLock.Lock()
acc := model.Account{}
Db.Debug().Table("account").Where("account","B").Find(&acc)
money := acc.Money + 800
Db.Debug().Table("account").Where("account","B").Update("money",money)
muLock.Unlock()
}()
}
//方式5 分布式锁

4.2mysql 死锁

死锁:对方都需要自己持有的资源,但是自己都不愿意释放该资源,从而导致循环等待

mysql 死锁的示例

时间

A

B

T1

begin

begin

T2

select * from user_t where userId = “1” for update;

select * from user_t where userId = “2” for update;

T3

select * from user_t where userId = “2” for update;

T4

select * from user_t where userId = “1” for update;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

A B 都在等待对方的行锁释放。

时间

A

B

T1

begin

begin

T2

select * from user_t where userId = “31” for update;

select * from user_t where userId >= 32 for update

T3

insert into user_t(userId,userName)value(32,”张三”);

T4

insert into user_t(userId,userName)values(31,”李四”)

在RR隔离级别下,存在间隙锁,B锁住了32以后的,A锁住了31,B需要A 的间隙锁,A需要B 31的间隙锁。

避免死锁方法:

加锁时机,程序层面解决,悲观锁、合适的索引,优化查询条件。

5、分布式事务

2PC (两段式提交)

6、总结

数据库系统应该支持哪些需求

mysql 事务的概念以及特性

ACID 实现原理

mysql 隔离级别、锁机制、死锁

扩展展望,分布式事务

以上就是关于用gg修改器游戏崩溃_游戏崩溃了gg修改器的全部内容,希望对大家有帮助。

相关文章

热门下载

大家还在搜