err := tx.Create(&cwsh).Error

在执行Create插入语句的时候,测试环境没遇到报错,但是生产环境报了1406异常,查了一下原来是生产环境和测试环境的mysql配置不同;

网络上找到的解决错误的方法是:

在my.ini里找到
sql-mode=”STRICT_TRANS_TABLES,NO_AUTO_Create_USER,NO_ENGINE_SUBSTITUTION”
把其中的STRICT_TRANS_TABLES,去掉,
或者把sql-mode=STRICT_TRANS_TABLES,NO_AUTO_Create_USER,NO_ENGINE_SUBSTITUTION

注释掉,然后重启mysql就ok了

但是生产环境的mysql是不能随便重启的,这块我们还是不能这样就重启了,因此专门看了一下text属性的mysql字段能存储的最大长度到底是多少。

找到的结果是:

MySQL长度

varchar定义的长度单位是字符。中英文字幕都被当做一个字符来看,最大长度取决于使用的字符集。

text定义的是字节

  • TEXT:65,535 bytes,64kb;
  • MEDIUMTEXT:16,777,215bytes,16Mb;
  • LONGTEXT:4,294,967,295 bytes,4Gb;

         因此可见text的最大长度是:65535bytes 字节;那么我们含着中文的字符串是如何计算的呢,我就专门设计了一个很长很长的字符串长度超过65535字节,插入到数据库,之后再查询数据库看看结果:

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)
var mysqlDb2 *gorm.DB

type TextContent struct {
	Id int `gorm:"id" json:"id"`
	Content string `gorm:"content" json:"content"`
}

func init() {
	var err error
	mysqlDb2, err = gorm.Open("mysql", "xxx:xxx@tcp(xx.xx.x.xxxx:3306)/test?charset=utf8mb4&parseTime=True")
	if err != nil {
		panic(err)
	}
	//mysqlDb2.LogMode(true)
}

func main()  {
    // 这里是我把长度删掉了,测试的时候我把长度拉到很长
	str := "{\"content\":\"一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十" +
		"一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十\"}"
	var cot = TextContent{
		Content:str,
	}
	fmt.Printf("字符串的长度是:%d \n", len(str))

	err := mysqlDb2.Table("text_content").Create(&cot).Error
	if err != nil {
		fmt.Printf("插入报错:%s", err.Error())
	}
	fmt.Println("数据插入成功")

}

我go run执行之后的效果是:

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:6494
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:60494
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:66494
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:108734
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:139934
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:171134
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:186734
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:192014
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:207854
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:224174
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:430574
数据插入成功

D:\work\example-for-go\src\twzQA>go run mysqlText.go
字符串的长度是:843374
数据插入成功

意思相当于多长我都可以插入,但是我在查看后面的数据的时候发现,text把字符串截取了!

mysql1406错误 mysql error1406_golang

 最后我使用len函数查询一下这个长度是多少:

func main()  {
	var content TextContent

	err := mysqlDb2.Table("text_content").Where("`id` = ?", 17).First(&content).Error
	if err != nil {
		fmt.Printf("数据查询报错:%s", err.Error())
	}
	fmt.Printf("数据查询结果中content长度是:%d", len(content.Content))

}

 查询结果是:

go run mysqlText.go
数据查询结果中content长度是:65535

可见你你插入多少带中文字符串都是65535的长度。

总结:go 中一个中文占3个字节,text长度是65535字节跟utf8mb4 utf8编码格式无关。

解决方案:要么修改mysql my.ini配置;如果不想改数据库设置可以进行字符串截取,或者丢弃内容。