Mysql

陷入僵局,

  • August 28, 2014

我有這個程式碼:

public void saveItems(List<Pair<Item, MapleInventoryType>> items, int id) throws SQLException {
   PreparedStatement ps = null;

   PreparedStatement pse = null;

   try {
       StringBuilder query = new StringBuilder();
       query.append("DELETE FROM `inventoryitems` WHERE `type` = ? AND `");
       query.append(account ? "accountid" : "characterid").append("` = ?");
       Connection con = DatabaseConnection.getConnection();
       ps = con.prepareStatement(query.toString());
       ps.setInt(1, value);
       ps.setInt(2, id);
       ps.executeUpdate();
       ps.close();
       ps = con.prepareStatement("INSERT INTO `inventoryitems` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
       pse = con.prepareStatement("INSERT INTO `inventoryequipment` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

       for (Pair<Item, MapleInventoryType> pair : items) {
           Item item = pair.getLeft();
           MapleInventoryType mit = pair.getRight();
           ps.setInt(1, value);
           ps.setString(2, account ? null : String.valueOf(id));
           ps.setString(3, account ? String.valueOf(id) : null);
           ps.setInt(4, item.getItemId());
           ps.setInt(5, mit.getType());
           ps.setInt(6, item.getPosition());
           ps.setInt(7, item.getQuantity());
           ps.setString(8, item.getOwner());
           ps.setInt(9, item.getPetId());
           ps.setInt(10, item.getFlag());
           ps.setLong(11, item.getExpiration());
           ps.setString(12, item.getGiftFrom());
           ps.executeUpdate();

           if (mit.equals(MapleInventoryType.EQUIP) || mit.equals(MapleInventoryType.EQUIPPED)) {
               try (ResultSet rs = ps.getGeneratedKeys()) {

                   if (!rs.next()) {
                       throw new RuntimeException("Inserting item failed.");
                   }

                   pse.setInt(1, rs.getInt(1));
                   rs.close();
               }
               Equip equip = (Equip) item;
               pse.setInt(2, equip.getUpgradeSlots());
               pse.setInt(3, equip.getLevel());
               pse.setInt(4, equip.getStr());
               pse.setInt(5, equip.getDex());
               pse.setInt(6, equip.getInt());
               pse.setInt(7, equip.getLuk());
               pse.setInt(8, equip.getHp());
               pse.setInt(9, equip.getMp());
               pse.setInt(10, equip.getWatk());
               pse.setInt(11, equip.getMatk());
               pse.setInt(12, equip.getWdef());
               pse.setInt(13, equip.getMdef());
               pse.setInt(14, equip.getAcc());
               pse.setInt(15, equip.getAvoid());
               pse.setInt(16, equip.getHands());
               pse.setInt(17, equip.getSpeed());
               pse.setInt(18, equip.getJump());
               pse.setInt(19, 0);
               pse.setInt(20, equip.getVicious());
               pse.setInt(21, equip.getItemLevel());
               pse.setInt(22, equip.getItemExp());
               pse.setInt(23, equip.getRingId());
               pse.executeUpdate();
           }
       }
       pse.close();
       ps.close();
   } catch (Exception e) {
       e.printStackTrace();
   } finally {
       if (ps != null) {
           ps.close();
       }
       if (pse != null) {
           pse.close();
       }
   }
}

死鎖錯誤:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:嘗試獲取鎖時發現死鎖;嘗試在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.GeneratedConstructorAccessor15.newInstance(Unknown Source) 在 java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util 重新啟動事務.handleNewInstance(Util.java:408) 在 com.mysql.jdbc.Util.getInstance(Util.java:383) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074) 在 com.mysql.jdbc。 MysqlIO.checkErrorPacket(MysqlIO.java:4226) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158) 在 com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615) 在 com.mysql.jdbc .MysqlIO.sqlQueryDirect(MysqlIO. $ TailFilter.mess ageReceived(DefaultIoFilterChain.java:690) at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage Received(DefaultIoFilterChain.java:417) at org.apache.mina.core.filterchain.DefaultIoFilterChain.access $ org.apache.mina.core.filterchain.DefaultIoFilterChain 處的 1200(預設 IoFilterChain.java:47) $ EntryImpl $ 1.mes sageReceived(DefaultIoFilterChain.java:765) 在 org.apache.mina.filter.codec.ProtocolCodecFilter $ ProtocolDecoderOutpu tImpl.flush(ProtocolCodecFilter.java:407) at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(Prot ocolCodecFilter.java:236) at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage Received(DefaultIoFilterChain.java:417) at org.apache.mina.core.filterchain.DefaultIoFilterChain.access $ org.apache.mina.core.filterchain.DefaultIoFilterChain 處的 1200(預設 IoFilterChain.java:47) $ EntryImpl $ 1.messageReceived(DefaultIoFilterChain.java:765) at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFi lterAdapter.java:109) at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage Received(DefaultIoFilterChain .java:417) 在 org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:410) 在 org.apache.mina.core.polling.AbstractPollingIoProcessor.read(Abstract PollingIoProcessor.java:710) 在org.apache.mina.core.polling.AbstractPollingIoProcessor.process(Abstr actPollingIoProcessor.java:664) 在 org.apache.mina.core.polling.AbstractPollingIoProcessor.process(Abstr actPollingIoProcessor.java:653) 在 org.apache.mina。 core.polling.AbstractPollingIoProcessor.access $ 600(Ab stractPollingIoProcessor.java:67) at org.apache.mina.core.polling.AbstractPollingIoProcessor $ Processor.run (AbstractPollingIoProcessor.java:1124) at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnabl e.java:64) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent .ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)

saveItems(ItemFactory.java:147) 是 ps.executeUpdate(); 我試圖檢查“SHOW ENGINE INNODB STATUS;” 在 mysql 上,我得到了這個註釋:


'InnoDB', '', '
=====================================
2014-08-24 12:38:54 bcc INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 49 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 1034 srv_active, 0 srv_shutdown, 1111 srv_idle
srv_master_thread log flush and writes: 2145
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 1238
OS WAIT ARRAY INFO: signal count 1208
Mutex spin waits 91061, rounds 86815, OS waits 817
RW-shared spins 443, rounds 11553, OS waits 377
RW-excl spins 78, rounds 1712, OS waits 44
Spin rounds per wait: 0.95 mutex, 26.08 RW-shared, 21.95 RW-excl
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2014-08-24 12:38:54 1a24 Transaction:
TRANSACTION 2127395, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
34 lock struct(s), heap size 6544, 357 row lock(s), undo log entries 297
MySQL thread id 602, OS thread handle 0x1a24, query id 249063 localhost 127.0.0.1 root update
INSERT INTO `inventoryitems` VALUES (DEFAULT, 4, '595', null, 5390001, 5, 1, 1, '', -1, 0, -1, '')
Foreign key constraint fails for table `israeldev`.`inventoryitems`:
,
 CONSTRAINT `FK_inventoryitems_1` FOREIGN KEY (`characterid`) REFERENCES `characters` (`id`) ON DELETE CASCADE
Trying to add in child table, in index `FK_inventoryitems_1` tuple:
DATA TUPLE: 2 fields;
0: len 4; hex 80000253; asc    S;;
1: len 4; hex 01d4c23b; asc    ;;;

But in parent table `israeldev`.`characters`, in index `PRIMARY`,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 70; compact format; info bits 0
0: len 4; hex 80007564; asc   ud;;
1: len 6; hex 000000204b8d; asc     K ;;
2: len 7; hex 5a000001ea0110; asc Z      ;;
3: len 4; hex 80000003; asc     ;;
4: len 4; hex 80000000; asc     ;;
5: len 6; hex 42696c6c6f77; asc Billow;;
6: len 4; hex 80000087; asc     ;;
7: len 4; hex 801a6202; asc   b ;;
8: len 4; hex 80000000; asc     ;;
9: len 4; hex 80000004; asc     ;;
10: len 4; hex 800000ae; asc     ;;
11: len 4; hex 800001c6; asc     ;;
12: len 4; hex 80000004; asc     ;;
13: len 4; hex 80007530; asc   u0;;
14: len 4; hex 8000751f; asc   u ;;
15: len 4; hex 80007530; asc   u0;;
16: len 4; hex 80007530; asc   u0;;
17: len 4; hex 8e694a2c; asc  iJ,;;
18: len 4; hex 00000000; asc     ;;
19: len 4; hex 8000038e; asc     ;;
20: len 4; hex 80000000; asc     ;;
21: len 4; hex 80000000; asc     ;;
22: len 4; hex 80000001; asc     ;;
23: len 4; hex 80009132; asc    2;;
24: len 4; hex 80004fbc; asc   O ;;
25: len 4; hex 8000223c; asc   "

庫存物品 sql :


'inventoryitems', 'CREATE TABLE `inventoryitems` (
 `inventoryitemid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `type` tinyint(3) unsigned NOT NULL,
 `characterid` int(11) DEFAULT NULL,
 `accountid` int(11) DEFAULT NULL,
 `itemid` int(11) NOT NULL DEFAULT '0',
 `inventorytype` int(11) NOT NULL DEFAULT '0',
 `position` int(11) NOT NULL DEFAULT '0',
 `quantity` int(11) NOT NULL DEFAULT '0',
 `owner` tinytext NOT NULL,
 `petid` int(11) NOT NULL DEFAULT '-1',
 `flag` int(11) NOT NULL,
 `expiration` bigint(20) NOT NULL DEFAULT '-1',
 `giftFrom` varchar(26) NOT NULL,
 PRIMARY KEY (`inventoryitemid`),
 KEY `FK_inventoryitems_1` (`characterid`),
 CONSTRAINT `FK_inventoryitems_1` FOREIGN KEY (`characterid`) REFERENCES `characters` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=31099641 DEFAULT CHARSET=latin1'

庫存設備 SQL:


'inventoryequipment', 'CREATE TABLE `inventoryequipment` (
 `inventoryequipmentid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `inventoryitemid` int(10) unsigned NOT NULL DEFAULT '0',
 `upgradeslots` int(11) NOT NULL DEFAULT '0',
 `level` int(11) NOT NULL DEFAULT '0',
 `str` int(11) NOT NULL DEFAULT '0',
 `dex` int(11) NOT NULL DEFAULT '0',
 `int` int(11) NOT NULL DEFAULT '0',
 `luk` int(11) NOT NULL DEFAULT '0',
 `hp` int(11) NOT NULL DEFAULT '0',
 `mp` int(11) NOT NULL DEFAULT '0',
 `watk` int(11) NOT NULL DEFAULT '0',
 `matk` int(11) NOT NULL DEFAULT '0',
 `wdef` int(11) NOT NULL DEFAULT '0',
 `mdef` int(11) NOT NULL DEFAULT '0',
 `acc` int(11) NOT NULL DEFAULT '0',
 `avoid` int(11) NOT NULL DEFAULT '0',
 `hands` int(11) NOT NULL DEFAULT '0',
 `speed` int(11) NOT NULL DEFAULT '0',
 `jump` int(11) NOT NULL DEFAULT '0',
 `locked` int(11) NOT NULL DEFAULT '0',
 `vicious` int(11) unsigned NOT NULL DEFAULT '0',
 `itemlevel` int(11) NOT NULL DEFAULT '1',
 `itemexp` int(11) unsigned NOT NULL DEFAULT '0',
 `ringid` int(11) NOT NULL DEFAULT '-1',
 PRIMARY KEY (`inventoryequipmentid`),
 KEY `inventoryitemid` (`inventoryitemid`),
 CONSTRAINT `inventoryequipment_ibfk_1` FOREIGN KEY (`inventoryitemid`) REFERENCES `inventoryitems` (`inventoryitemid`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=8811024 DEFAULT CHARSET=latin1'

人物 :


'characters', 'CREATE TABLE `characters` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `accountid` int(11) NOT NULL DEFAULT '0',
 `world` int(11) NOT NULL DEFAULT '0',
 `name` varchar(13) NOT NULL DEFAULT '',
 `level` int(11) NOT NULL DEFAULT '1',
 `exp` int(11) NOT NULL DEFAULT '0',
 `gachaexp` int(11) NOT NULL DEFAULT '0',
 `str` int(11) NOT NULL DEFAULT '12',
 `dex` int(11) NOT NULL DEFAULT '5',
 `luk` int(11) NOT NULL DEFAULT '4',
 `int` int(11) NOT NULL DEFAULT '4',
 `hp` int(11) NOT NULL DEFAULT '50',
 `mp` int(11) NOT NULL DEFAULT '5',
 `maxhp` int(11) NOT NULL DEFAULT '50',
 `maxmp` int(11) NOT NULL DEFAULT '5',
 `meso` int(11) NOT NULL DEFAULT '0',
 `hpMpUsed` int(11) unsigned NOT NULL DEFAULT '0',
 `job` int(11) NOT NULL DEFAULT '0',
 `skincolor` int(11) NOT NULL DEFAULT '0',
 `gender` int(11) NOT NULL DEFAULT '0',
 `fame` int(11) NOT NULL DEFAULT '0',
 `hair` int(11) NOT NULL DEFAULT '0',
 `face` int(11) NOT NULL DEFAULT '0',
 `ap` int(11) NOT NULL DEFAULT '0',
 `sp` int(11) NOT NULL DEFAULT '0',
 `map` int(11) NOT NULL DEFAULT '0',
 `spawnpoint` int(11) NOT NULL DEFAULT '0',
 `gm` tinyint(1) NOT NULL DEFAULT '0',
 `party` int(11) NOT NULL DEFAULT '0',
 `buddyCapacity` int(11) NOT NULL DEFAULT '25',
 `createdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 `rank` int(10) unsigned NOT NULL DEFAULT '1',
 `rankMove` int(11) NOT NULL DEFAULT '0',
 `jobRank` int(10) unsigned NOT NULL DEFAULT '1',
 `jobRankMove` int(11) NOT NULL DEFAULT '0',
 `guildid` int(10) unsigned NOT NULL DEFAULT '0',
 `guildrank` int(10) unsigned NOT NULL DEFAULT '5',
 `messengerid` int(10) unsigned NOT NULL DEFAULT '0',
 `messengerposition` int(10) unsigned NOT NULL DEFAULT '4',
 `mountlevel` int(9) NOT NULL DEFAULT '1',
 `mountexp` int(9) NOT NULL DEFAULT '0',
 `mounttiredness` int(9) NOT NULL DEFAULT '0',
 `omokwins` int(11) NOT NULL DEFAULT '0',
 `omoklosses` int(11) NOT NULL DEFAULT '0',
 `omokties` int(11) NOT NULL DEFAULT '0',
 `matchcardwins` int(11) NOT NULL DEFAULT '0',
 `matchcardlosses` int(11) NOT NULL DEFAULT '0',
 `matchcardties` int(11) NOT NULL DEFAULT '0',
 `MerchantMesos` int(11) DEFAULT '0',
 `HasMerchant` tinyint(1) DEFAULT '0',
 `equipslots` int(11) NOT NULL DEFAULT '96',
 `useslots` int(11) NOT NULL DEFAULT '96',
 `setupslots` int(11) NOT NULL DEFAULT '96',
 `etcslots` int(11) NOT NULL DEFAULT '96',
 `familyId` int(11) NOT NULL DEFAULT '-1',
 `monsterbookcover` int(11) NOT NULL DEFAULT '0',
 `allianceRank` int(10) NOT NULL DEFAULT '5',
 `vanquisherStage` int(11) unsigned NOT NULL DEFAULT '0',
 `dojoPoints` int(11) unsigned NOT NULL DEFAULT '0',
 `lastDojoStage` int(10) unsigned NOT NULL DEFAULT '0',
 `finishedDojoTutorial` tinyint(1) unsigned NOT NULL DEFAULT '0',
 `vanquisherKills` int(11) unsigned NOT NULL DEFAULT '0',
 `summonValue` int(11) unsigned NOT NULL DEFAULT '0',
 `reborns` int(11) NOT NULL DEFAULT '0',
 `uniqName` int(11) NOT NULL DEFAULT '0',
 `pvpkills` int(11) NOT NULL DEFAULT '0',
 `pvpdeaths` int(11) NOT NULL DEFAULT '0',
 `familiar` int(11) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 KEY `accountid` (`accountid`),
 KEY `party` (`party`),
 KEY `ranking1` (`level`,`exp`),
 KEY `ranking2` (`gm`,`job`)
) ENGINE=InnoDB AUTO_INCREMENT=32944 DEFAULT CHARSET=latin1 PACK_KEYS=0'

SQL 程式碼 .-. 錯誤發生時

-----------------------------
從 `inventoryitems` 中刪除 WHERE `type` = ? AND `accountid` = ?
值:2
編號:490
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:死鎖發現
d 試圖獲得鎖時;嘗試重啟事務

請幫我解決這個死鎖:(。

系統開始抱怨評論的數量。

我有興趣查看發送到伺服器的語句 - 即完全生成的 SQL 語句,即具有實際值,不是嗎?參數佔位符。

似乎導致問題的聲明就是這個。

INSERT INTO `inventoryitems` VALUES (DEFAULT, 4, '595', null, 5390001, 5, 1, 1, '', -1, 0, -1, '')

現在,庫存項目有一個 FOREIGN KEY 約束

刪除級聯時的約束FK_inventoryitems_1外鍵 ( characterid) 引用characters( )id

以下查詢的結果是什麼

SELECT COUNT(*) FROM characters WHERE characters.id = 595;

這裡的值也很有趣。

ps = con.prepareStatement("INSERT INTO `inventoryitems` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
pse = con.prepareStatement("INSERT INTO `inventoryequipment` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

$$ EDIT $$ 我開始對可能發生的事情有所了解。您似乎正在使用某種框架進行數據庫訪問(這就是為什麼您的 SQL 使用 ‘595’ 表示整數插入而不是 595。

框架可能將事務隔離級別設置為讀取送出以外的其他內容(請參閱此處)。嘗試並確保您的事務使用已送出的讀取 - 設置事務級別。嘗試在該行之後將此程式碼添加到您的程式碼中

連接 con = DatabaseConnection.getConnection(); con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); // 添加的行。

另外,請查看內容和執行緒的其餘部分。

$$ EDIT $$回應“我如何檢查它?,你能指導我嗎?” 我的意思是讓您將上面的行添加到您的程式碼中,然後重新執行您的系統,直到您遇到原始錯誤。你仍然收到錯誤嗎?如果你這樣做,那麼它與原始錯誤不同嗎?如果不同,請在此處發布錯誤文本。HTH。

你能把你的數據庫轉儲到網上嗎?您可以匿名任何敏感內容。此外,壓縮您的 Java 程式碼,我將在此處針對您的架構執行它。我的 Java 有點生疏了,但在不同的系統上執行它可能會給我們一些線索!:-)

$$ EDIT $$回應 OP 的評論“你能給我一個索引的例子嗎?$$ code example $$?”。 請參見此處(您也可以使用 KEY 關鍵字作為 INDEX 的同義詞 - 請參見此處的 docco 。您應該在您的清單項中添加 CREATE TABLE 語句行,例如

INDEX `ii_type_ix` (type), 
INDEX `ii_account_id_ix` (accountid),

至於更改您的 Java 程式碼 - 我不是 100% 確定,但問題出在數據庫上,因此您的工作應該集中在那裡。您可以更改程式碼的地方是改變查詢的順序(但保留原始功能)。

$$ Solved $$ 怎麼修:


'inventoryitems', 'CREATE TABLE `inventoryitems` (
 `inventoryitemid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `type` tinyint(3) unsigned NOT NULL,
 `characterid` int(11) DEFAULT NULL,
 `accountid` int(11) DEFAULT NULL,
 `itemid` int(11) NOT NULL DEFAULT '0',
 `inventorytype` int(11) NOT NULL DEFAULT '0',
 `position` int(11) NOT NULL DEFAULT '0',
 `quantity` int(11) NOT NULL DEFAULT '0',
 `owner` tinytext NOT NULL,
 `petid` int(11) NOT NULL DEFAULT '-1',
 `flag` int(11) NOT NULL,
 `expiration` bigint(20) NOT NULL DEFAULT '-1',
 `giftFrom` varchar(26) NOT NULL,
 PRIMARY KEY (`inventoryitemid`),
 KEY `FK_inventoryitems_1` (`characterid`),
 KEY `FK_inventoryitems_2` (`accountid`) USING BTREE,
 CONSTRAINT `FK_inventoryitems_1` FOREIGN KEY (`characterid`) REFERENCES `characters` (`id`) ON DELETE CASCADE,
 CONSTRAINT `FK_inventoryitems_2` FOREIGN KEY (`accountid`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=40321116 DEFAULT CHARSET=latin1'

代替 :


'inventoryitems', 'CREATE TABLE `inventoryitems` (
 `inventoryitemid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `type` tinyint(3) unsigned NOT NULL,
 `characterid` int(11) DEFAULT NULL,
 `accountid` int(11) DEFAULT NULL,
 `itemid` int(11) NOT NULL DEFAULT '0',
 `inventorytype` int(11) NOT NULL DEFAULT '0',
 `position` int(11) NOT NULL DEFAULT '0',
 `quantity` int(11) NOT NULL DEFAULT '0',
 `owner` tinytext NOT NULL,
 `petid` int(11) NOT NULL DEFAULT '-1',
 `flag` int(11) NOT NULL,
 `expiration` bigint(20) NOT NULL DEFAULT '-1',
 `giftFrom` varchar(26) NOT NULL,
 PRIMARY KEY (`inventoryitemid`),
 KEY `FK_inventoryitems_1` (`characterid`),
 CONSTRAINT `FK_inventoryitems_1` FOREIGN KEY (`characterid`) REFERENCES `characters` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=31099641 DEFAULT CHARSET=latin1'

引用自:https://dba.stackexchange.com/questions/74781