go实践八 操作mysql事务和数据的增删查改

事务(transaction)

事物:保持逻辑数据一致性与可恢复性,必不可少的利器!

为什么要使用事务

银行转账是经典的解释事务的例子,如:用户A给用户B转账5000元主要步骤可以概括为以下几步:

  1. 检测A账户余额 > 5000元

  2. A账户余额减去 5000元

  3. B账户余额增加 5000元

这几步要么都成功,要么一个都不成功,否则都会导致数据不一致(5000元不翼而飞)。这就可以用到事务来保证,如果是不同银行之间的转账还需要用到分布式事务。

事务的应用场景

1. 同时更新多个表  
2. 同时更新多行数据  

事务的ACID

 

1. 原子性  

一个事务的执行被视为一个不可分割的最小单元。事务里面的操作,要么全部成功执行,要么全部失败回滚。

2. 一致性  

事务结束的时候,所有的内部数据都是正确的。

3. 隔离性  

并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。

4. 持久性 

事务提交之后,数据是永久性的,不可再回滚。

 

连接mysql的方式请参照:https://blog.csdn.net/daily886/article/details/95592913

以下说明的是使用mysql事务和数据的增删查改

编辑一个 testdb.go 文件,内容如下

使用 go run testdb.go 运行该文件即可

package main

import (
	"fmt"
	"web/model"
)

func main() {
	initdb()
	testtransaction()
	testmysql()
}

//建立db的初始连接
func initdb(){
	var DB = model.Init()
	//建立链接
	err := DB.Ping()
	if(err != nil){
		panic("连接失败")
	}
	fmt.Printf("连接正常\n")
	DB.Close(); //关闭数据库连接池
	println();
}

//测试事务
func testtransaction(){
	var DB = model.Init()
	//开启事务
	var err error
	transaction_con,err := DB.Begin()
	if err != nil{
		panic(err)
	}
	result, err := transaction_con.Exec("insert into erp_admin(name,password) values(?,?)","test","123456")
	if err != nil{
		// 失败回滚
		transaction_con.Rollback()
		panic(err)
	}
	id, err := result.LastInsertId()//获取自增id
	//affected, err = result.RowsAffected() //获取update影响的行数
	if err != nil{
		// 失败回滚
		transaction_con.Rollback()
		panic(err)
	}
	fmt.Println(result)
	fmt.Println(id)

	result,err = transaction_con.Exec("insert into erp_admin_log(admin_id,action) values(?,?)",1,"test")
	if err != nil{
		// 失败回滚
		transaction_con.Rollback()
		panic(err)
	}
	id, err = result.LastInsertId() //获取自增id
	//affected, err = result.RowsAffected() //获取update影响的行数
	if err != nil{
		// 失败回滚
		transaction_con.Rollback()
		panic(err)
	}
	fmt.Println(result)
	fmt.Println(id)

	err = transaction_con.Commit()
	if(err != nil){
		// 失败回滚
		transaction_con.Rollback()
		panic(err)
	}
	fmt.Println("测试事务成功\n")

	DB.Close(); //关闭数据库连接池
	println();
}

func testmysql(){
	var DB = model.Init()
	//新建表
	/*
	DROP TABLE IF EXISTS `student`;
	CREATE TABLE `student` (
		`id` int(11) NOT NULL AUTO_INCREMENT,
		`name` varchar(50) CHARACTER SET latin1 NOT NULL DEFAULT '',
		`age` tinyint(4) DEFAULT '0',
		PRIMARY KEY (`id`)
	) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
	*/
	//创建表
	stmt, err := DB.Prepare(`DROP TABLE IF EXISTS student`)
	res, err := stmt.Exec()
	if(err != nil){
		panic(err)
	}
	stmt, err = DB.Prepare(`
	CREATE TABLE student (
		id int(11) NOT NULL AUTO_INCREMENT,
		name varchar(50) CHARACTER SET latin1 NOT NULL DEFAULT "",
		age tinyint(4) DEFAULT "0",
		PRIMARY KEY (id)
	) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
`)
	res, err = stmt.Exec()
	if(err != nil){
		panic(err)
	}

	//增加数据
	stmt, err = DB.Prepare(`INSERT student (name,age) values (?,?)`)
	res, err = stmt.Exec("wangwu", 26)
	id, err := res.LastInsertId()
	fmt.Println("自增id=", id)
	fmt.Printf("error %v\n", err)
	//修改数据
	stmt, err = DB.Prepare(`UPDATE student SET age=? WHERE id=?`)
	res, err = stmt.Exec(21, 5)
	num, err := res.RowsAffected() //影响行数
	fmt.Println(num)
	fmt.Printf("error %v\n", err)
	//删除数据
	stmt, err = DB.Prepare(`DELETE FROM student WHERE id=?`)
	res, err = stmt.Exec(5)
	num, err = res.RowsAffected()
	fmt.Println(num)
	fmt.Printf("error %v\n", err)
	//查询数据
	rows, err := DB.Query("SELECT * FROM student")

	//--------简单一行一行输出---start
	//    for rows.Next() { //满足条件依次下一层
	//        var id int
	//        var name string
	//        var age int
	//        rows.Columns()

	//        err = rows.Scan(&id, &name, &age)
	//        fmt.Println(id)
	//        fmt.Println(name)
	//        fmt.Println(age)
	//    }
	//--------简单一行一行输出---end

	//--------遍历放入map----start
	//构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址
	columns, _ := rows.Columns()
	scanArgs := make([]interface{}, len(columns))
	values := make([]interface{}, len(columns))

	for i := range values {
		scanArgs[i] = &values[i]
	}

	for rows.Next() {
		//将行数据保存到record字典
		err = rows.Scan(scanArgs...)
		record := make(map[string]string)
		for i, col := range values {
			if col != nil {
				record[columns[i]] = string(col.([]byte))
			}
		}
		fmt.Println(record)
	}
	//--------遍历放入map----end

	DB.Close(); //关闭数据库连接池
	println();
}

 mysql事务参考:https://www.cnblogs.com/Survivalist/articles/10439122.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值